From f7f58e718d2bb43726deef1dff5b51929d24ffb4 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 6 Jul 2026 08:23:07 +0200 Subject: [PATCH] Extend alert dialog with copy-to-clipboard functionality --- .../user-account-membership.component.ts | 13 ++++++++---- .../alert-dialog/alert-dialog.component.ts | 20 ++++++++++++++++++- .../alert-dialog/alert-dialog.html | 16 +++++++++++++-- .../alert-dialog/interfaces/interfaces.ts | 1 + .../notifications/interfaces/interfaces.ts | 2 ++ .../lib/notifications/notification.service.ts | 7 +++++-- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts index b13a983fc..70248068d 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts @@ -146,11 +146,16 @@ export class GfUserAccountMembershipComponent { ) .subscribe(({ apiKey }) => { this.notificationService.alert({ + copyFn: () => { + this.snackBar.open( + '✅ ' + $localize`${apiKey} has been copied to the clipboard`, + undefined, + { duration: ms('3 seconds') } + ); + }, + copyValue: apiKey, discardLabel: $localize`Okay`, - message: - $localize`Set this API key in your self-hosted environment:` + - '
' + - apiKey, + message: $localize`Set this API key in your self-hosted environment:`, title: $localize`Ghostfolio Premium Data Provider API Key` }); }); diff --git a/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.component.ts b/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.component.ts index 3dbe70387..df91c6479 100644 --- a/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.component.ts +++ b/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.component.ts @@ -1,3 +1,4 @@ +import { Clipboard } from '@angular/cdk/clipboard'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; @@ -12,6 +13,7 @@ import { AlertDialogParams } from './interfaces/interfaces'; templateUrl: './alert-dialog.html' }) export class GfAlertDialogComponent { + public copyValue?: string; public discardLabel: string; public message?: string; public title: string; @@ -19,9 +21,25 @@ export class GfAlertDialogComponent { protected readonly dialogRef = inject>(MatDialogRef); - public initialize({ discardLabel, message, title }: AlertDialogParams) { + private readonly clipboard = inject(Clipboard); + + public initialize({ + copyValue, + discardLabel, + message, + title + }: AlertDialogParams) { + this.copyValue = copyValue; this.discardLabel = discardLabel; this.message = message; this.title = title; } + + public onCopyToClipboard() { + if (this.copyValue) { + this.clipboard.copy(this.copyValue); + } + + this.dialogRef.close('copy'); + } } diff --git a/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.html b/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.html index 6602078d3..f690a8e5d 100644 --- a/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.html +++ b/libs/ui/src/lib/notifications/alert-dialog/alert-dialog.html @@ -2,10 +2,22 @@
} -@if (message) { -
+@if (message || copyValue) { +
+ @if (message) { +
+ } + @if (copyValue) { +
{{ copyValue }}
+ } +
}
+ @if (copyValue) { + + }
diff --git a/libs/ui/src/lib/notifications/alert-dialog/interfaces/interfaces.ts b/libs/ui/src/lib/notifications/alert-dialog/interfaces/interfaces.ts index fa330c463..7b2c16e52 100644 --- a/libs/ui/src/lib/notifications/alert-dialog/interfaces/interfaces.ts +++ b/libs/ui/src/lib/notifications/alert-dialog/interfaces/interfaces.ts @@ -1,4 +1,5 @@ export interface AlertDialogParams { + copyValue?: string; discardLabel: string; message?: string; title: string; diff --git a/libs/ui/src/lib/notifications/interfaces/interfaces.ts b/libs/ui/src/lib/notifications/interfaces/interfaces.ts index 071597691..326fd1c99 100644 --- a/libs/ui/src/lib/notifications/interfaces/interfaces.ts +++ b/libs/ui/src/lib/notifications/interfaces/interfaces.ts @@ -1,6 +1,8 @@ import { ConfirmationDialogType } from '@ghostfolio/common/enums'; export interface AlertParams { + copyFn?: () => void; + copyValue?: string; discardFn?: () => void; discardLabel?: string; message?: string; diff --git a/libs/ui/src/lib/notifications/notification.service.ts b/libs/ui/src/lib/notifications/notification.service.ts index b9a2562f7..5b0c4587c 100644 --- a/libs/ui/src/lib/notifications/notification.service.ts +++ b/libs/ui/src/lib/notifications/notification.service.ts @@ -31,13 +31,16 @@ export class NotificationService { }); dialog.componentInstance.initialize({ + copyValue: aParams.copyValue, discardLabel: aParams.discardLabel, message: aParams.message, title: aParams.title }); - return dialog.afterClosed().subscribe(() => { - if (isFunction(aParams.discardFn)) { + return dialog.afterClosed().subscribe((result) => { + if (result === 'copy' && isFunction(aParams.copyFn)) { + aParams.copyFn(); + } else if (isFunction(aParams.discardFn)) { aParams.discardFn(); } });