From 4e1867682f487d2cc1e4e474a614f5bfd2effc11 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 2 May 2023 18:46:03 +0200 Subject: [PATCH] [PM-1504] Migrate Dialogs to DialogService (#5013) This PR introduces a generic `DialogService` which can be used by all the clients. This allows us to decouple dialogs from the `PlatformUtilsHelper`. The `DialogService` provides a new method, `openSimpleDialog` which is the new interface for that type of dialogs. This gives us 3 different implementations: - Web: DialogService modern dialogs - Browser: SweetAlert - Desktop: Native electron based --- apps/browser/src/auth/popup/lock.component.ts | 7 +- .../src/auth/popup/register.component.ts | 7 +- .../src/auth/popup/set-password.component.ts | 7 +- .../src/auth/popup/two-factor.component.ts | 15 +-- .../background/nativeMessaging.background.ts | 54 ++++---- .../src/background/runtime.background.ts | 11 +- apps/browser/src/popup/app.component.ts | 60 +++------ apps/browser/src/popup/app.module.ts | 10 +- .../popup/services/browser-dialog.service.ts | 79 ++++++++++++ .../src/popup/services/services.module.ts | 6 + .../settings/folder-add-edit.component.ts | 13 +- .../src/popup/settings/premium.component.ts | 6 +- .../src/popup/settings/settings.component.ts | 117 +++++++++--------- .../services/browserPlatformUtils.service.ts | 71 ----------- .../popup/send/send-add-edit.component.ts | 7 +- .../popup/send/send-groupings.component.ts | 7 +- .../tools/popup/send/send-type.component.ts | 7 +- .../tools/popup/settings/export.component.ts | 7 +- .../components/vault/add-edit.component.ts | 7 +- .../components/vault/attachments.component.ts | 7 +- .../popup/components/vault/view.component.ts | 7 +- .../services/cli-platform-utils.service.ts | 10 -- .../src/app/accounts/settings.component.ts | 84 ++++++------- apps/desktop/src/app/app.component.ts | 43 ++++--- apps/desktop/src/app/app.module.ts | 3 +- .../src/app/services/services.module.ts | 6 + .../src/app/tools/export/export.component.ts | 35 +++--- .../src/app/tools/send/add-edit.component.ts | 7 +- .../src/app/tools/send/send.component.ts | 7 +- apps/desktop/src/auth/lock.component.ts | 18 +-- apps/desktop/src/auth/register.component.ts | 7 +- .../src/auth/set-password.component.ts | 7 +- .../src/services/electron-dialog.service.ts | 62 ++++++++++ .../electron-platform-utils.service.ts | 26 ---- .../vault/app/accounts/premium.component.ts | 6 +- .../src/vault/app/vault/add-edit.component.ts | 7 +- .../vault/app/vault/attachments.component.ts | 7 +- .../app/vault/folder-add-edit.component.ts | 13 +- .../src/vault/app/vault/vault.component.ts | 16 +-- .../src/vault/app/vault/view.component.ts | 7 +- .../organizations/guards/is-paid-org.guard.ts | 18 +-- .../manage/group-add-edit.component.ts | 21 ++-- .../organizations/manage/groups.component.ts | 31 +++-- .../member-dialog/member-dialog.component.ts | 39 +++--- .../components/reset-password.component.ts | 17 +-- .../organizations/members/people.component.ts | 40 +++--- .../collection-dialog.component.ts | 20 +-- .../import-export/org-export.component.ts | 7 +- .../import-export/org-import.component.ts | 17 ++- .../settings/sponsoring-org-row.component.ts | 19 +-- apps/web/src/app/app.component.ts | 40 +++--- ...ganization-subscription-cloud.component.ts | 44 +++---- .../settings/payment-method.component.ts | 34 ++--- .../settings/user-subscription.component.ts | 74 +++++------ .../src/app/common/base.people.component.ts | 29 +++-- .../app/core/web-platform-utils.service.ts | 61 --------- .../change-kdf/change-kdf.component.ts | 4 +- .../app/settings/change-password.component.ts | 36 +++--- .../src/app/settings/preferences.component.ts | 17 +-- .../tools/import-export/export.component.ts | 7 +- .../tools/import-export/import.component.ts | 4 +- .../src/app/tools/send/add-edit.component.ts | 7 +- apps/web/src/app/tools/send/send.component.ts | 7 +- .../individual-vault/add-edit.component.ts | 7 +- .../individual-vault/attachments.component.ts | 7 +- .../bulk-delete-dialog.component.ts | 4 +- .../bulk-move-dialog.component.ts | 4 +- .../bulk-restore-dialog.component.ts | 4 +- .../bulk-share-dialog.component.ts | 4 +- .../folder-add-edit.component.ts | 13 +- .../organization-options.component.ts | 30 ++--- .../vault/individual-vault/vault.component.ts | 35 +++--- .../app/vault/org-vault/add-edit.component.ts | 7 +- .../vault/org-vault/attachments.component.ts | 7 +- .../vault-header/vault-header.component.ts | 16 +-- .../app/vault/org-vault/vault.component.ts | 48 ++++--- apps/web/src/auth/lock.component.ts | 7 +- .../register-form/register-form.component.ts | 7 +- apps/web/src/auth/set-password.component.ts | 7 +- .../emergency-access-attachments.component.ts | 7 +- .../emergency-access-takeover.component.ts | 7 +- .../emergency-access.component.ts | 49 ++++---- .../emergency-add-edit.component.ts | 7 +- .../two-factor-authenticator.component.ts | 13 +- .../settings/two-factor-base.component.ts | 19 ++- .../auth/settings/two-factor-duo.component.ts | 13 +- .../settings/two-factor-email.component.ts | 13 +- .../settings/two-factor-webauthn.component.ts | 27 ++-- .../settings/two-factor-yubikey.component.ts | 13 +- .../web/src/auth/update-password.component.ts | 7 +- apps/web/src/scss/tailwind.css | 13 ++ .../domain-add-edit-dialog.component.ts | 17 +-- .../domain-verification.component.ts | 17 ++- .../organizations/manage/scim.component.ts | 18 +-- .../clients/add-organization.component.ts | 19 +-- .../providers/clients/clients.component.ts | 16 +-- .../providers/manage/people.component.ts | 7 +- .../manage/user-add-edit.component.ts | 17 +-- .../overview/overview.component.ts | 4 +- .../dialog/project-delete-dialog.component.ts | 4 +- .../project/project-people.component.ts | 5 +- .../project/project-secrets.component.ts | 4 +- .../projects/project/project.component.ts | 6 +- .../projects/projects/projects.component.ts | 4 +- .../secrets/dialog/secret-delete.component.ts | 4 +- .../secrets/dialog/secret-dialog.component.ts | 4 +- .../secrets/secrets.component.ts | 4 +- .../access/access-tokens.component.ts | 4 +- .../access-token-create-dialog.component.ts | 6 +- ...service-account-delete-dialog.component.ts | 4 +- .../service-account-people.component.ts | 12 +- .../service-account.component.ts | 4 +- .../service-accounts.component.ts | 4 +- .../settings/porting/sm-import.component.ts | 4 +- .../shared/new-menu.component.ts | 4 +- .../secrets-manager/trash/trash.component.ts | 4 +- .../components/change-password.component.ts | 56 ++++----- .../src/auth/components/lock.component.ts | 18 +-- .../components/remove-password.component.ts | 18 +-- .../components/update-password.component.ts | 8 +- .../update-temp-password.component.ts | 8 +- .../src/components/register.component.ts | 43 ++++--- .../src/components/set-password.component.ts | 7 +- .../dialog/dialog.service.abstraction.ts | 26 ++++ .../src/services/dialog/dialog.service.ts | 65 ++++++++++ libs/angular/src/services/dialog/index.ts | 6 + .../dialog}/simple-dialog-close-type.enum.ts | 0 .../services/dialog}/simple-dialog-options.ts | 0 .../dialog}/simple-dialog-type.enum.ts | 0 .../src/services/dialog}/translation.ts | 0 .../export/components/export.component.ts | 34 ++--- .../src/tools/send/add-edit.component.ts | 37 +++--- libs/angular/src/tools/send/send.component.ts | 33 ++--- .../vault/components/add-edit.component.ts | 61 +++++---- .../vault/components/attachments.component.ts | 47 +++---- .../components/folder-add-edit.component.ts | 20 +-- .../src/vault/components/premium.component.ts | 29 +++-- .../src/vault/components/view.component.ts | 35 +++--- .../src/abstractions/platformUtils.service.ts | 9 -- libs/components/src/dialog/dialog.module.ts | 9 +- libs/components/src/dialog/dialog.service.ts | 41 ++++-- libs/components/src/dialog/index.ts | 4 - .../simple-configurable-dialog.component.ts | 13 +- ...ple-configurable-dialog.service.stories.ts | 32 ++--- 144 files changed, 1514 insertions(+), 1212 deletions(-) create mode 100644 apps/browser/src/popup/services/browser-dialog.service.ts create mode 100644 apps/desktop/src/services/electron-dialog.service.ts create mode 100644 libs/angular/src/services/dialog/dialog.service.abstraction.ts create mode 100644 libs/angular/src/services/dialog/dialog.service.ts create mode 100644 libs/angular/src/services/dialog/index.ts rename libs/{components/src/dialog/simple-configurable-dialog/models => angular/src/services/dialog}/simple-dialog-close-type.enum.ts (100%) rename libs/{components/src/dialog/simple-configurable-dialog/models => angular/src/services/dialog}/simple-dialog-options.ts (100%) rename libs/{components/src/dialog/simple-configurable-dialog/models => angular/src/services/dialog}/simple-dialog-type.enum.ts (100%) rename libs/{components/src/dialog/simple-configurable-dialog/models => angular/src/services/dialog}/translation.ts (100%) diff --git a/apps/browser/src/auth/popup/lock.component.ts b/apps/browser/src/auth/popup/lock.component.ts index 385ac667d0d..ffcc6efa2cf 100644 --- a/apps/browser/src/auth/popup/lock.component.ts +++ b/apps/browser/src/auth/popup/lock.component.ts @@ -2,6 +2,7 @@ import { Component, NgZone } from "@angular/core"; import { Router } from "@angular/router"; import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; @@ -48,7 +49,8 @@ export class LockComponent extends BaseLockComponent { policyApiService: PolicyApiServiceAbstraction, policyService: InternalPolicyService, passwordGenerationService: PasswordGenerationServiceAbstraction, - private authService: AuthService + private authService: AuthService, + dialogService: DialogServiceAbstraction ) { super( router, @@ -66,7 +68,8 @@ export class LockComponent extends BaseLockComponent { ngZone, policyApiService, policyService, - passwordGenerationService + passwordGenerationService, + dialogService ); this.successRoute = "/tabs/current"; this.isInitialLockScreen = (window as any).previousPopupUrl == null; diff --git a/apps/browser/src/auth/popup/register.component.ts b/apps/browser/src/auth/popup/register.component.ts index 11b01dd38f4..f7a80b62938 100644 --- a/apps/browser/src/auth/popup/register.component.ts +++ b/apps/browser/src/auth/popup/register.component.ts @@ -3,6 +3,7 @@ import { UntypedFormBuilder } from "@angular/forms"; import { Router } from "@angular/router"; import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -36,7 +37,8 @@ export class RegisterComponent extends BaseRegisterComponent { passwordGenerationService: PasswordGenerationServiceAbstraction, environmentService: EnvironmentService, logService: LogService, - auditService: AuditService + auditService: AuditService, + dialogService: DialogServiceAbstraction ) { super( formValidationErrorService, @@ -51,7 +53,8 @@ export class RegisterComponent extends BaseRegisterComponent { passwordGenerationService, environmentService, logService, - auditService + auditService, + dialogService ); } } diff --git a/apps/browser/src/auth/popup/set-password.component.ts b/apps/browser/src/auth/popup/set-password.component.ts index 2f50db7c2b3..35af812714a 100644 --- a/apps/browser/src/auth/popup/set-password.component.ts +++ b/apps/browser/src/auth/popup/set-password.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -34,7 +35,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { syncService: SyncService, route: ActivatedRoute, organizationApiService: OrganizationApiServiceAbstraction, - organizationUserService: OrganizationUserService + organizationUserService: OrganizationUserService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -50,7 +52,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { route, stateService, organizationApiService, - organizationUserService + organizationUserService, + dialogService ); } } diff --git a/apps/browser/src/auth/popup/two-factor.component.ts b/apps/browser/src/auth/popup/two-factor.component.ts index 56424cd107e..678675ba389 100644 --- a/apps/browser/src/auth/popup/two-factor.component.ts +++ b/apps/browser/src/auth/popup/two-factor.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AppIdService } from "@bitwarden/common/abstractions/appId.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; @@ -46,7 +47,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { logService: LogService, twoFactorService: TwoFactorService, appIdService: AppIdService, - loginService: LoginService + loginService: LoginService, + private dialogService: DialogServiceAbstraction ) { super( authService, @@ -102,12 +104,11 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { this.selectedProviderType === TwoFactorProviderType.Email && this.popupUtilsService.inPopup(window) ) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("popup2faCloseMessage"), - null, - this.i18nService.t("yes"), - this.i18nService.t("no") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "warning" }, + content: { key: "popup2faCloseMessage" }, + type: SimpleDialogType.WARNING, + }); if (confirmed) { this.popupUtilsService.popOut(window); } diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index df78380cd36..7e4b91694c9 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -153,10 +153,11 @@ export class NativeMessagingBackground { this.connected = false; this.messagingService.send("showDialog", { - text: this.i18nService.t("nativeMessagingInvalidEncryptionDesc"), - title: this.i18nService.t("nativeMessagingInvalidEncryptionTitle"), - confirmText: this.i18nService.t("ok"), - type: "error", + title: { key: "nativeMessagingInvalidEncryptionTitle" }, + content: { key: "nativeMessagingInvalidEncryptionDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: "danger", }); break; case "verifyFingerprint": { @@ -199,10 +200,11 @@ export class NativeMessagingBackground { showWrongUserDialog() { this.messagingService.send("showDialog", { - text: this.i18nService.t("nativeMessagingWrongUserDesc"), - title: this.i18nService.t("nativeMessagingWrongUserTitle"), - confirmText: this.i18nService.t("ok"), - type: "error", + title: { key: "nativeMessagingWrongUserTitle" }, + content: { key: "nativeMessagingWrongUserDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: "danger", }); } @@ -258,10 +260,11 @@ export class NativeMessagingBackground { this.connected = false; this.messagingService.send("showDialog", { - text: this.i18nService.t("nativeMessagingInvalidEncryptionDesc"), - title: this.i18nService.t("nativeMessagingInvalidEncryptionTitle"), - confirmText: this.i18nService.t("ok"), - type: "error", + title: { key: "nativeMessagingInvalidEncryptionTitle" }, + content: { key: "nativeMessagingInvalidEncryptionDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: "danger", }); } } @@ -285,18 +288,20 @@ export class NativeMessagingBackground { if (message.response === "not enabled") { this.messagingService.send("showDialog", { - text: this.i18nService.t("biometricsNotEnabledDesc"), - title: this.i18nService.t("biometricsNotEnabledTitle"), - confirmText: this.i18nService.t("ok"), - type: "error", + title: { key: "biometricsNotEnabledTitle" }, + content: { key: "biometricsNotEnabledDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: "danger", }); break; } else if (message.response === "not supported") { this.messagingService.send("showDialog", { - text: this.i18nService.t("biometricsNotSupportedDesc"), - title: this.i18nService.t("biometricsNotSupportedTitle"), - confirmText: this.i18nService.t("ok"), - type: "error", + title: { key: "biometricsNotSupportedTitle" }, + content: { key: "biometricsNotSupportedDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: "danger", }); break; } @@ -377,13 +382,8 @@ export class NativeMessagingBackground { await this.cryptoService.getFingerprint(await this.stateService.getUserId(), this.publicKey) ).join(" "); - this.messagingService.send("showDialog", { - html: `${this.i18nService.t( - "desktopIntegrationVerificationText" - )}

${fingerprint}`, - title: this.i18nService.t("desktopSyncVerificationTitle"), - confirmText: this.i18nService.t("ok"), - type: "warning", + this.messagingService.send("showNativeMessagingFinterprintDialog", { + fingerprint: fingerprint, }); } } diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index 6f66e28a68a..da9e196410b 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -119,9 +119,6 @@ export default class RuntimeBackground { BrowserApi.closeBitwardenExtensionTab(); }, msg.delay ?? 0); break; - case "showDialogResolve": - this.platformUtilsService.resolveDialogPromise(msg.dialogId, msg.confirmed); - break; case "bgCollectPageDetails": await this.main.collectPageDetailsForContentScript(sender.tab, msg.sender, sender.frameId); break; @@ -204,10 +201,10 @@ export default class RuntimeBackground { break; case "emailVerificationRequired": this.messagingService.send("showDialog", { - dialogId: "emailVerificationRequired", - title: this.i18nService.t("emailVerificationRequired"), - text: this.i18nService.t("emailVerificationRequiredDesc"), - confirmText: this.i18nService.t("ok"), + title: { key: "emailVerificationRequired" }, + content: { key: "emailVerificationRequiredDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, type: "info", }); break; diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index dd231e865cf..1f4ddfc36ce 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -10,8 +10,9 @@ import { DomSanitizer } from "@angular/platform-browser"; import { NavigationEnd, Router, RouterOutlet } from "@angular/router"; import { IndividualConfig, ToastrService } from "ngx-toastr"; import { Subject, takeUntil } from "rxjs"; -import Swal, { SweetAlertIcon } from "sweetalert2"; +import Swal from "sweetalert2"; +import { DialogServiceAbstraction, SimpleDialogOptions } from "@bitwarden/angular/services/dialog"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; @@ -48,7 +49,8 @@ export class AppComponent implements OnInit, OnDestroy { private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone, private sanitizer: DomSanitizer, - private platformUtilsService: PlatformUtilsService + private platformUtilsService: PlatformUtilsService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -102,6 +104,9 @@ export class AppComponent implements OnInit, OnDestroy { } } else if (msg.command === "showDialog") { await this.showDialog(msg); + } else if (msg.command === "showNativeMessagingFinterprintDialog") { + // TODO: Should be refactored to live in another service. + await this.showNativeMessagingFingerprintDialog(msg); } else if (msg.command === "showToast") { this.ngZone.run(() => { this.showToast(msg); @@ -222,51 +227,24 @@ export class AppComponent implements OnInit, OnDestroy { this.toastrService.show(message, msg.title, options, "toast-" + msg.type); } - private async showDialog(msg: any) { - let iconClasses: string = null; - const type = msg.type; - if (type != null) { - // If you add custom types to this part, the type to SweetAlertIcon cast below needs to be changed. - switch (type) { - case "success": - iconClasses = "bwi-check text-success"; - break; - case "warning": - iconClasses = "bwi-exclamation-triangle text-warning"; - break; - case "error": - iconClasses = "bwi-error text-danger"; - break; - case "info": - iconClasses = "bwi-info-circle text-info"; - break; - default: - break; - } - } + private async showDialog(msg: SimpleDialogOptions) { + await this.dialogService.openSimpleDialog(msg); + } - const cancelText = msg.cancelText; - const confirmText = msg.confirmText; - const confirmed = await Swal.fire({ + private async showNativeMessagingFingerprintDialog(msg: any) { + await Swal.fire({ heightAuto: false, buttonsStyling: false, - icon: type as SweetAlertIcon, // required to be any of the SweetAlertIcons to output the iconHtml. - iconHtml: - iconClasses != null ? `` : undefined, - text: msg.text, - html: msg.html, - titleText: msg.title, - showCancelButton: cancelText != null, - cancelButtonText: cancelText, + icon: "warning", + iconHtml: '', + html: `${this.i18nService.t("desktopIntegrationVerificationText")}

${ + msg.fingerprint + }`, + titleText: this.i18nService.t("desktopSyncVerificationTitle"), showConfirmButton: true, - confirmButtonText: confirmText == null ? this.i18nService.t("ok") : confirmText, + confirmButtonText: this.i18nService.t("ok"), timer: 300000, }); - - this.messagingService.send("showDialogResolve", { - dialogId: msg.dialogId, - confirmed: confirmed.value, - }); } private async clearComponentStates() { diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index b809a63a587..a0cd5e8887b 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -1,14 +1,10 @@ import { A11yModule } from "@angular/cdk/a11y"; +import { DialogModule } from "@angular/cdk/dialog"; import { DragDropModule } from "@angular/cdk/drag-drop"; import { LayoutModule } from "@angular/cdk/layout"; import { OverlayModule } from "@angular/cdk/overlay"; import { ScrollingModule } from "@angular/cdk/scrolling"; -// eslint-disable-next-line import/order import { CurrencyPipe, DatePipe } from "@angular/common"; - -// Register the locales for the application -import "./locales"; - import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { BrowserModule } from "@angular/platform-browser"; @@ -76,6 +72,9 @@ import { SyncComponent } from "./settings/sync.component"; import { VaultTimeoutInputComponent } from "./settings/vault-timeout-input.component"; import { TabsComponent } from "./tabs.component"; +// Register the locales for the application +import "./locales"; + @NgModule({ imports: [ A11yModule, @@ -96,6 +95,7 @@ import { TabsComponent } from "./tabs.component"; ReactiveFormsModule, ScrollingModule, ServicesModule, + DialogModule, ], declarations: [ ActionButtonsComponent, diff --git a/apps/browser/src/popup/services/browser-dialog.service.ts b/apps/browser/src/popup/services/browser-dialog.service.ts new file mode 100644 index 00000000000..44028695198 --- /dev/null +++ b/apps/browser/src/popup/services/browser-dialog.service.ts @@ -0,0 +1,79 @@ +import { Injectable } from "@angular/core"; +import Swal, { SweetAlertIcon } from "sweetalert2"; + +import { + DialogService, + SimpleDialogOptions, + SimpleDialogType, +} from "@bitwarden/angular/services/dialog"; + +@Injectable() +export class BrowserDialogService extends DialogService { + async openSimpleDialog(options: SimpleDialogOptions) { + const defaultCancel = + options.cancelButtonText === undefined + ? options.acceptButtonText == null + ? "no" + : "cancel" + : null; + + return this.legacyShowDialog( + this.translate(options.content), + this.translate(options.title), + this.translate(options.acceptButtonText, "yes"), + this.translate(options.cancelButtonText, defaultCancel), + options.type + ); + } + + private async legacyShowDialog( + body: string, + title?: string, + confirmText?: string, + cancelText?: string, + type?: SimpleDialogType + ) { + let iconClasses: string = null; + let icon: SweetAlertIcon = null; + if (type != null) { + // If you add custom types to this part, the type to SweetAlertIcon cast below needs to be changed. + switch (type) { + case "success": + iconClasses = "bwi-check text-success"; + icon = "success"; + break; + case "warning": + iconClasses = "bwi-exclamation-triangle text-warning"; + icon = "warning"; + break; + case "danger": + iconClasses = "bwi-error text-danger"; + icon = "error"; + break; + case "info": + iconClasses = "bwi-info-circle text-info"; + icon = "info"; + break; + default: + break; + } + } + + const confirmed = await Swal.fire({ + heightAuto: false, + buttonsStyling: false, + icon: icon, + iconHtml: + iconClasses != null ? `` : undefined, + text: body, + titleText: title, + showCancelButton: cancelText != null, + cancelButtonText: cancelText, + showConfirmButton: true, + confirmButtonText: confirmText == null ? this.i18nService.t("ok") : confirmText, + timer: 300000, + }); + + return confirmed.value; + } +} diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 2103a014a3e..0534be363a9 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -2,6 +2,7 @@ import { APP_INITIALIZER, LOCALE_ID, NgModule } from "@angular/core"; import { LockGuard as BaseLockGuardService } from "@bitwarden/angular/auth/guards/lock.guard"; import { UnauthGuard as BaseUnauthGuardService } from "@bitwarden/angular/auth/guards/unauth.guard"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { MEMORY_STORAGE, SECURE_STORAGE } from "@bitwarden/angular/services/injection-tokens"; import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module"; import { ThemingService } from "@bitwarden/angular/services/theming/theming.service"; @@ -101,6 +102,7 @@ import { PasswordRepromptService } from "../../vault/popup/services/password-rep import { BrowserFolderService } from "../../vault/services/browser-folder.service"; import { VaultFilterService } from "../../vault/services/vault-filter.service"; +import { BrowserDialogService } from "./browser-dialog.service"; import { DebounceNavigationService } from "./debounceNavigationService"; import { InitService } from "./init.service"; import { PopupSearchService } from "./popup-search.service"; @@ -489,6 +491,10 @@ function getBgService(service: keyof MainBackground) { useClass: BrowserConfigService, deps: [StateServiceAbstraction, ConfigApiServiceAbstraction], }, + { + provide: DialogServiceAbstraction, + useClass: BrowserDialogService, + }, ], }) export class ServicesModule {} diff --git a/apps/browser/src/popup/settings/folder-add-edit.component.ts b/apps/browser/src/popup/settings/folder-add-edit.component.ts index 54c7cc7d435..92db7e4ba56 100644 --- a/apps/browser/src/popup/settings/folder-add-edit.component.ts +++ b/apps/browser/src/popup/settings/folder-add-edit.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -22,9 +23,17 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { platformUtilsService: PlatformUtilsService, private router: Router, private route: ActivatedRoute, - logService: LogService + logService: LogService, + dialogService: DialogServiceAbstraction ) { - super(folderService, folderApiService, i18nService, platformUtilsService, logService); + super( + folderService, + folderApiService, + i18nService, + platformUtilsService, + logService, + dialogService + ); } async ngOnInit() { diff --git a/apps/browser/src/popup/settings/premium.component.ts b/apps/browser/src/popup/settings/premium.component.ts index 2bb7383da35..63d45d79141 100644 --- a/apps/browser/src/popup/settings/premium.component.ts +++ b/apps/browser/src/popup/settings/premium.component.ts @@ -1,6 +1,7 @@ import { CurrencyPipe, Location } from "@angular/common"; import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { PremiumComponent as BasePremiumComponent } from "@bitwarden/angular/vault/components/premium.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -22,9 +23,10 @@ export class PremiumComponent extends BasePremiumComponent { stateService: StateService, logService: LogService, private location: Location, - private currencyPipe: CurrencyPipe + private currencyPipe: CurrencyPipe, + dialogService: DialogServiceAbstraction ) { - super(i18nService, platformUtilsService, apiService, logService, stateService); + super(i18nService, platformUtilsService, apiService, logService, stateService, dialogService); // Support old price string. Can be removed in future once all translations are properly updated. const thePrice = this.currencyPipe.transform(this.price, "$"); diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts index 25879f28a98..383e18de292 100644 --- a/apps/browser/src/popup/settings/settings.component.ts +++ b/apps/browser/src/popup/settings/settings.component.ts @@ -4,6 +4,7 @@ import { Router } from "@angular/router"; import { concatMap, debounceTime, filter, map, Observable, Subject, takeUntil, tap } from "rxjs"; import Swal from "sweetalert2"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; @@ -82,7 +83,8 @@ export class SettingsComponent implements OnInit { private stateService: StateService, private popupUtilsService: PopupUtilsService, private modalService: ModalService, - private keyConnectorService: KeyConnectorService + private keyConnectorService: KeyConnectorService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -185,13 +187,12 @@ export class SettingsComponent implements OnInit { async saveVaultTimeout(newValue: number) { if (newValue == null) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("neverLockWarning"), - null, - this.i18nService.t("yes"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "warning" }, + content: { key: "neverLockWarning" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { this.form.controls.vaultTimeout.setValue(this.previousVaultTimeout); return; @@ -222,13 +223,12 @@ export class SettingsComponent implements OnInit { async saveVaultTimeoutAction(newValue: VaultTimeoutAction) { if (newValue === VaultTimeoutAction.LogOut) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("vaultTimeoutLogOutConfirmation"), - this.i18nService.t("vaultTimeoutLogOutConfirmationTitle"), - this.i18nService.t("yes"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "vaultTimeoutLogOutConfirmationTitle" }, + content: { key: "vaultTimeoutLogOutConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { this.vaultTimeoutActionOptions.forEach((option: any, i) => { if (option.value === this.form.value.vaultTimeoutAction) { @@ -284,24 +284,28 @@ export class SettingsComponent implements OnInit { console.error(e); if (this.platformUtilsService.isFirefox() && this.popupUtilsService.inSidebar(window)) { - await this.platformUtilsService.showDialog( - this.i18nService.t("nativeMessaginPermissionSidebarDesc"), - this.i18nService.t("nativeMessaginPermissionSidebarTitle"), - this.i18nService.t("ok"), - null - ); + await this.dialogService.openSimpleDialog({ + title: { key: "nativeMessaginPermissionSidebarTitle" }, + content: { key: "nativeMessaginPermissionSidebarDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.INFO, + }); + this.form.controls.biometric.setValue(false); return; } } if (!granted) { - await this.platformUtilsService.showDialog( - this.i18nService.t("nativeMessaginPermissionErrorDesc"), - this.i18nService.t("nativeMessaginPermissionErrorTitle"), - this.i18nService.t("ok"), - null - ); + await this.dialogService.openSimpleDialog({ + title: { key: "nativeMessaginPermissionErrorTitle" }, + content: { key: "nativeMessaginPermissionErrorDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.DANGER, + }); + this.form.controls.biometric.setValue(false); return; } @@ -349,13 +353,13 @@ export class SettingsComponent implements OnInit { const error = BiometricErrors[e as BiometricErrorTypes]; - this.platformUtilsService.showDialog( - this.i18nService.t(error.description), - this.i18nService.t(error.title), - this.i18nService.t("ok"), - null, - "error" - ); + this.dialogService.openSimpleDialog({ + title: { key: error.title }, + content: { key: error.description }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.DANGER, + }); }), ]); } else { @@ -375,24 +379,23 @@ export class SettingsComponent implements OnInit { } async logOut() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("logOutConfirmation"), - this.i18nService.t(VaultTimeoutAction.LogOut), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "logOut" }, + content: { key: "logOutConfirmation" }, + type: SimpleDialogType.INFO, + }); + if (confirmed) { this.messagingService.send("logout"); } } async changePassword() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("changeMasterPasswordConfirmation"), - this.i18nService.t("changeMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "changeMasterPassword" }, + content: { key: "changeMasterPasswordConfirmation" }, + type: SimpleDialogType.INFO, + }); if (confirmed) { BrowserApi.createNewTab( "https://bitwarden.com/help/master-password/#change-your-master-password" @@ -401,24 +404,22 @@ export class SettingsComponent implements OnInit { } async twoStep() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("twoStepLoginConfirmation"), - this.i18nService.t("twoStepLogin"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "twoStepLogin" }, + content: { key: "twoStepLoginConfirmation" }, + type: SimpleDialogType.INFO, + }); if (confirmed) { BrowserApi.createNewTab("https://bitwarden.com/help/setup-two-step-login/"); } } async share() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("learnOrgConfirmation"), - this.i18nService.t("learnOrg"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "learnOrg" }, + content: { key: "learnOrgConfirmation" }, + type: SimpleDialogType.INFO, + }); if (confirmed) { BrowserApi.createNewTab("https://bitwarden.com/help/about-organizations/"); } diff --git a/apps/browser/src/services/browserPlatformUtils.service.ts b/apps/browser/src/services/browserPlatformUtils.service.ts index 5cfd232f57c..3120e740560 100644 --- a/apps/browser/src/services/browserPlatformUtils.service.ts +++ b/apps/browser/src/services/browserPlatformUtils.service.ts @@ -5,14 +5,7 @@ import { ClientType, DeviceType } from "@bitwarden/common/enums"; import { BrowserApi } from "../browser/browserApi"; import { SafariApp } from "../browser/safariApp"; -const DialogPromiseExpiration = 600000; // 10 minutes - export default class BrowserPlatformUtilsService implements PlatformUtilsService { - private showDialogResolves = new Map void; date: Date }>(); - private passwordDialogResolves = new Map< - number, - { tryResolve: (canceled: boolean, password: string) => Promise; date: Date } - >(); private static deviceCache: DeviceType = null; constructor( @@ -215,29 +208,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService }); } - showDialog( - body: string, - title?: string, - confirmText?: string, - cancelText?: string, - type?: string, - bodyIsHtml = false - ) { - const dialogId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); - this.messagingService.send("showDialog", { - text: bodyIsHtml ? null : body, - html: bodyIsHtml ? body : null, - title: title, - confirmText: confirmText, - cancelText: cancelText, - type: type, - dialogId: dialogId, - }); - return new Promise((resolve) => { - this.showDialogResolves.set(dialogId, { resolve: resolve, date: new Date() }); - }); - } - isDev(): boolean { return process.env.ENV === "development"; } @@ -339,47 +309,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService return null; } - resolveDialogPromise(dialogId: number, confirmed: boolean) { - if (this.showDialogResolves.has(dialogId)) { - const resolveObj = this.showDialogResolves.get(dialogId); - resolveObj.resolve(confirmed); - this.showDialogResolves.delete(dialogId); - } - - // Clean up old promises - this.showDialogResolves.forEach((val, key) => { - const age = new Date().getTime() - val.date.getTime(); - if (age > DialogPromiseExpiration) { - this.showDialogResolves.delete(key); - } - }); - } - - async resolvePasswordDialogPromise( - dialogId: number, - canceled: boolean, - password: string - ): Promise { - let result = false; - if (this.passwordDialogResolves.has(dialogId)) { - const resolveObj = this.passwordDialogResolves.get(dialogId); - if (await resolveObj.tryResolve(canceled, password)) { - this.passwordDialogResolves.delete(dialogId); - result = true; - } - } - - // Clean up old promises - this.passwordDialogResolves.forEach((val, key) => { - const age = new Date().getTime() - val.date.getTime(); - if (age > DialogPromiseExpiration) { - this.passwordDialogResolves.delete(key); - } - }); - - return result; - } - async supportsBiometric() { const platformInfo = await BrowserApi.getPlatformInfo(); if (platformInfo.os === "android") { diff --git a/apps/browser/src/tools/popup/send/send-add-edit.component.ts b/apps/browser/src/tools/popup/send/send-add-edit.component.ts index d1f72bf8b3c..8a45d39dcc8 100644 --- a/apps/browser/src/tools/popup/send/send-add-edit.component.ts +++ b/apps/browser/src/tools/popup/send/send-add-edit.component.ts @@ -3,6 +3,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -45,7 +46,8 @@ export class SendAddEditComponent extends BaseAddEditComponent { private location: Location, private popupUtilsService: PopupUtilsService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -57,7 +59,8 @@ export class SendAddEditComponent extends BaseAddEditComponent { policyService, logService, stateService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/browser/src/tools/popup/send/send-groupings.component.ts b/apps/browser/src/tools/popup/send/send-groupings.component.ts index c2188c6d4a7..8c84df39768 100644 --- a/apps/browser/src/tools/popup/send/send-groupings.component.ts +++ b/apps/browser/src/tools/popup/send/send-groupings.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectorRef, Component, NgZone } from "@angular/core"; import { Router } from "@angular/router"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { SendComponent as BaseSendComponent } from "@bitwarden/angular/tools/send/send.component"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; @@ -49,7 +50,8 @@ export class SendGroupingsComponent extends BaseSendComponent { private changeDetectorRef: ChangeDetectorRef, private broadcasterService: BroadcasterService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( sendService, @@ -60,7 +62,8 @@ export class SendGroupingsComponent extends BaseSendComponent { searchService, policyService, logService, - sendApiService + sendApiService, + dialogService ); super.onSuccessfulLoad = async () => { this.calculateTypeCounts(); diff --git a/apps/browser/src/tools/popup/send/send-type.component.ts b/apps/browser/src/tools/popup/send/send-type.component.ts index 836fcef714d..f7637070413 100644 --- a/apps/browser/src/tools/popup/send/send-type.component.ts +++ b/apps/browser/src/tools/popup/send/send-type.component.ts @@ -3,6 +3,7 @@ import { ChangeDetectorRef, Component, NgZone } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { SendComponent as BaseSendComponent } from "@bitwarden/angular/tools/send/send.component"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; @@ -49,7 +50,8 @@ export class SendTypeComponent extends BaseSendComponent { private broadcasterService: BroadcasterService, private router: Router, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( sendService, @@ -60,7 +62,8 @@ export class SendTypeComponent extends BaseSendComponent { searchService, policyService, logService, - sendApiService + sendApiService, + dialogService ); super.onSuccessfulLoad = async () => { this.selectType(this.type); diff --git a/apps/browser/src/tools/popup/settings/export.component.ts b/apps/browser/src/tools/popup/settings/export.component.ts index 2235ff23406..b90dda05232 100644 --- a/apps/browser/src/tools/popup/settings/export.component.ts +++ b/apps/browser/src/tools/popup/settings/export.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { UntypedFormBuilder } from "@angular/forms"; import { Router } from "@angular/router"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; @@ -29,7 +30,8 @@ export class ExportComponent extends BaseExportComponent { logService: LogService, userVerificationService: UserVerificationService, formBuilder: UntypedFormBuilder, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cryptoService, @@ -42,7 +44,8 @@ export class ExportComponent extends BaseExportComponent { logService, userVerificationService, formBuilder, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/browser/src/vault/popup/components/vault/add-edit.component.ts b/apps/browser/src/vault/popup/components/vault/add-edit.component.ts index 4e9f51f8505..1c4dc5dadef 100644 --- a/apps/browser/src/vault/popup/components/vault/add-edit.component.ts +++ b/apps/browser/src/vault/popup/components/vault/add-edit.component.ts @@ -3,6 +3,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/vault/components/add-edit.component"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; @@ -53,7 +54,8 @@ export class AddEditComponent extends BaseAddEditComponent { organizationService: OrganizationService, passwordRepromptService: PasswordRepromptService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -69,7 +71,8 @@ export class AddEditComponent extends BaseAddEditComponent { logService, passwordRepromptService, organizationService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/browser/src/vault/popup/components/vault/attachments.component.ts b/apps/browser/src/vault/popup/components/vault/attachments.component.ts index 152ece9c099..68f59def546 100644 --- a/apps/browser/src/vault/popup/components/vault/attachments.component.ts +++ b/apps/browser/src/vault/popup/components/vault/attachments.component.ts @@ -3,6 +3,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -31,7 +32,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { private route: ActivatedRoute, stateService: StateService, logService: LogService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -42,7 +44,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { window, logService, stateService, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/browser/src/vault/popup/components/vault/view.component.ts b/apps/browser/src/vault/popup/components/vault/view.component.ts index 5dac1a0d9d6..237a4cfed21 100644 --- a/apps/browser/src/vault/popup/components/vault/view.component.ts +++ b/apps/browser/src/vault/popup/components/vault/view.component.ts @@ -3,6 +3,7 @@ import { ChangeDetectorRef, Component, NgZone } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ViewComponent as BaseViewComponent } from "@bitwarden/angular/vault/components/view.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; @@ -65,7 +66,8 @@ export class ViewComponent extends BaseViewComponent { apiService: ApiService, passwordRepromptService: PasswordRepromptService, logService: LogService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -85,7 +87,8 @@ export class ViewComponent extends BaseViewComponent { passwordRepromptService, logService, stateService, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/cli/src/services/cli-platform-utils.service.ts b/apps/cli/src/services/cli-platform-utils.service.ts index 35fc00af726..b109610a4ae 100644 --- a/apps/cli/src/services/cli-platform-utils.service.ts +++ b/apps/cli/src/services/cli-platform-utils.service.ts @@ -112,16 +112,6 @@ export class CliPlatformUtilsService implements PlatformUtilsService { throw new Error("Not implemented."); } - showDialog( - text: string, - title?: string, - confirmText?: string, - cancelText?: string, - type?: string - ): Promise { - throw new Error("Not implemented."); - } - isDev(): boolean { return process.env.BWCLI_ENV === "development"; } diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index 9ddd357c565..0e95b3fc54c 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -3,6 +3,7 @@ import { FormBuilder } from "@angular/forms"; import { Observable, Subject } from "rxjs"; import { concatMap, debounceTime, filter, map, takeUntil, tap } from "rxjs/operators"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -109,7 +110,8 @@ export class SettingsComponent implements OnInit { private cryptoService: CryptoService, private modalService: ModalService, private themingService: AbstractThemingService, - private settingsService: SettingsService + private settingsService: SettingsService, + private dialogService: DialogServiceAbstraction ) { const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop; @@ -295,13 +297,12 @@ export class SettingsComponent implements OnInit { async saveVaultTimeout(newValue: number) { if (newValue == null) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("neverLockWarning"), - "", - this.i18nService.t("yes"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "warning" }, + content: { key: "neverLockWarning" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { this.form.controls.vaultTimeout.setValue(this.previousVaultTimeout); return; @@ -332,13 +333,12 @@ export class SettingsComponent implements OnInit { async saveVaultTimeoutAction(newValue: VaultTimeoutAction) { if (newValue === "logOut") { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("vaultTimeoutLogOutConfirmation"), - this.i18nService.t("vaultTimeoutLogOutConfirmationTitle"), - this.i18nService.t("yes"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "vaultTimeoutLogOutConfirmationTitle" }, + content: { key: "vaultTimeoutLogOutConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { this.form.controls.vaultTimeoutAction.patchValue(VaultTimeoutAction.Lock, { emitEvent: false, @@ -462,13 +462,11 @@ export class SettingsComponent implements OnInit { !this.form.value.enableTray && (this.form.value.startToTray || this.form.value.enableCloseToTray) ) { - const confirm = await this.platformUtilsService.showDialog( - this.i18nService.t("confirmTrayDesc"), - this.i18nService.t("confirmTrayTitle"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirm = await this.dialogService.openSimpleDialog({ + title: { key: "confirmTrayTitle" }, + content: { key: "confirmTrayDesc" }, + type: SimpleDialogType.WARNING, + }); if (confirm) { this.form.controls.startToTray.setValue(false, { emitEvent: false }); @@ -524,35 +522,35 @@ export class SettingsComponent implements OnInit { async saveBrowserIntegration() { if (process.platform === "darwin" && !this.platformUtilsService.isMacAppStore()) { - await this.platformUtilsService.showDialog( - this.i18nService.t("browserIntegrationMasOnlyDesc"), - this.i18nService.t("browserIntegrationUnsupportedTitle"), - this.i18nService.t("ok"), - null, - "warning" - ); + await this.dialogService.openSimpleDialog({ + title: { key: "browserIntegrationUnsupportedTitle" }, + content: { key: "browserIntegrationMasOnlyDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); this.form.controls.enableBrowserIntegration.setValue(false); return; } else if (isWindowsStore()) { - await this.platformUtilsService.showDialog( - this.i18nService.t("browserIntegrationWindowsStoreDesc"), - this.i18nService.t("browserIntegrationUnsupportedTitle"), - this.i18nService.t("ok"), - null, - "warning" - ); + await this.dialogService.openSimpleDialog({ + title: { key: "browserIntegrationUnsupportedTitle" }, + content: { key: "browserIntegrationWindowsStoreDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); this.form.controls.enableBrowserIntegration.setValue(false); return; } else if (process.platform == "linux") { - await this.platformUtilsService.showDialog( - this.i18nService.t("browserIntegrationLinuxDesc"), - this.i18nService.t("browserIntegrationUnsupportedTitle"), - this.i18nService.t("ok"), - null, - "warning" - ); + await this.dialogService.openSimpleDialog({ + title: { key: "browserIntegrationUnsupportedTitle" }, + content: { key: "browserIntegrationLinuxDesc" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); this.form.controls.enableBrowserIntegration.setValue(false); return; diff --git a/apps/desktop/src/app/app.component.ts b/apps/desktop/src/app/app.component.ts index 5700d6abbb3..c87a2eacfc5 100644 --- a/apps/desktop/src/app/app.component.ts +++ b/apps/desktop/src/app/app.component.ts @@ -14,6 +14,7 @@ import { IndividualConfig, ToastrService } from "ngx-toastr"; import { firstValueFrom, Subject, takeUntil } from "rxjs"; import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction"; @@ -135,7 +136,8 @@ export class AppComponent implements OnInit, OnDestroy { private policyService: InternalPolicyService, private modalService: ModalService, private keyConnectorService: KeyConnectorService, - private configService: ConfigServiceAbstraction + private configService: ConfigServiceAbstraction, + private dialogService: DialogServiceAbstraction ) {} ngOnInit() { @@ -231,12 +233,15 @@ export class AppComponent implements OnInit, OnDestroy { const fingerprint = await this.cryptoService.getFingerprint( await this.stateService.getUserId() ); - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("yourAccountsFingerprint") + ":\n" + fingerprint.join("-"), - this.i18nService.t("fingerprintPhrase"), - this.i18nService.t("learnMore"), - this.i18nService.t("close") - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "fingerprintPhrase" }, + content: + this.i18nService.t("yourAccountsFingerprint") + ":\n" + fingerprint.join("-"), + acceptButtonText: { key: "learnMore" }, + cancelButtonText: { key: "close" }, + type: SimpleDialogType.INFO, + }); + if (result) { this.platformUtilsService.launchUri("https://bitwarden.com/help/fingerprint-phrase/"); } @@ -265,24 +270,24 @@ export class AppComponent implements OnInit, OnDestroy { }); break; case "premiumRequired": { - const premiumConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("premiumRequiredDesc"), - this.i18nService.t("premiumRequired"), - this.i18nService.t("learnMore"), - this.i18nService.t("cancel") - ); + const premiumConfirmed = await this.dialogService.openSimpleDialog({ + title: { key: "premiumRequired" }, + content: { key: "premiumRequiredDesc" }, + acceptButtonText: { key: "learnMore" }, + type: SimpleDialogType.SUCCESS, + }); if (premiumConfirmed) { await this.openModal(PremiumComponent, this.premiumRef); } break; } case "emailVerificationRequired": { - const emailVerificationConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("emailVerificationRequiredDesc"), - this.i18nService.t("emailVerificationRequired"), - this.i18nService.t("learnMore"), - this.i18nService.t("cancel") - ); + const emailVerificationConfirmed = await this.dialogService.openSimpleDialog({ + title: { key: "emailVerificationRequired" }, + content: { key: "emailVerificationRequiredDesc" }, + acceptButtonText: { key: "learnMore" }, + type: SimpleDialogType.INFO, + }); if (emailVerificationConfirmed) { this.platformUtilsService.launchUri( "https://bitwarden.com/help/create-bitwarden-account/" diff --git a/apps/desktop/src/app/app.module.ts b/apps/desktop/src/app/app.module.ts index 0dae52319a9..5e1cb5b9ca1 100644 --- a/apps/desktop/src/app/app.module.ts +++ b/apps/desktop/src/app/app.module.ts @@ -3,6 +3,7 @@ import "zone.js"; // Register the locales for the application import "./locales"; +import { DialogModule } from "@angular/cdk/dialog"; import { NgModule } from "@angular/core"; import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password-count.pipe"; @@ -56,7 +57,7 @@ import { EffluxDatesComponent as SendEffluxDatesComponent } from "./tools/send/e import { SendComponent } from "./tools/send/send.component"; @NgModule({ - imports: [SharedModule, AppRoutingModule, VaultFilterModule, LoginModule], + imports: [SharedModule, DialogModule, AppRoutingModule, VaultFilterModule, LoginModule], declarations: [ AccessibilityCookieComponent, AccountSwitcherComponent, diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts index 1f6ada8b0c0..d9d6377c179 100644 --- a/apps/desktop/src/app/services/services.module.ts +++ b/apps/desktop/src/app/services/services.module.ts @@ -1,5 +1,6 @@ import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { SECURE_STORAGE, STATE_FACTORY, @@ -43,6 +44,7 @@ import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@ import { LoginGuard } from "../../auth/guards/login.guard"; import { Account } from "../../models/account"; import { ElectronCryptoService } from "../../services/electron-crypto.service"; +import { ElectronDialogService } from "../../services/electron-dialog.service"; import { ElectronLogService } from "../../services/electron-log.service"; import { ElectronPlatformUtilsService } from "../../services/electron-platform-utils.service"; import { ElectronRendererMessagingService } from "../../services/electron-renderer-messaging.service"; @@ -176,6 +178,10 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK"); useClass: LoginService, deps: [StateServiceAbstraction], }, + { + provide: DialogServiceAbstraction, + useClass: ElectronDialogService, + }, { provide: CryptoServiceAbstraction, useClass: ElectronCryptoService, diff --git a/apps/desktop/src/app/tools/export/export.component.ts b/apps/desktop/src/app/tools/export/export.component.ts index 511710f0586..00991ed8ecc 100644 --- a/apps/desktop/src/app/tools/export/export.component.ts +++ b/apps/desktop/src/app/tools/export/export.component.ts @@ -3,6 +3,7 @@ import * as os from "os"; import { Component, OnInit } from "@angular/core"; import { UntypedFormBuilder } from "@angular/forms"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -33,7 +34,8 @@ export class ExportComponent extends BaseExportComponent implements OnInit { formBuilder: UntypedFormBuilder, private broadcasterService: BroadcasterService, logService: LogService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cryptoService, @@ -46,7 +48,8 @@ export class ExportComponent extends BaseExportComponent implements OnInit { logService, userVerificationService, formBuilder, - fileDownloadService + fileDownloadService, + dialogService ); } @@ -56,25 +59,23 @@ export class ExportComponent extends BaseExportComponent implements OnInit { async warningDialog() { if (this.encryptedFormat) { - return await this.platformUtilsService.showDialog( - this.i18nService.t("encExportKeyWarningDesc") + + return await this.dialogService.openSimpleDialog({ + title: { key: "confirmVaultExport" }, + content: + this.i18nService.t("encExportKeyWarningDesc") + os.EOL + os.EOL + this.i18nService.t("encExportAccountWarningDesc"), - this.i18nService.t("confirmVaultExport"), - this.i18nService.t("exportVault"), - this.i18nService.t("cancel"), - "warning", - true - ); + acceptButtonText: { key: "exportVault" }, + type: SimpleDialogType.WARNING, + }); } else { - return await this.platformUtilsService.showDialog( - this.i18nService.t("exportWarningDesc"), - this.i18nService.t("confirmVaultExport"), - this.i18nService.t("exportVault"), - this.i18nService.t("cancel"), - "warning" - ); + return await this.dialogService.openSimpleDialog({ + title: { key: "confirmVaultExport" }, + content: { key: "exportWarningDesc" }, + acceptButtonText: { key: "exportVault" }, + type: SimpleDialogType.WARNING, + }); } } } diff --git a/apps/desktop/src/app/tools/send/add-edit.component.ts b/apps/desktop/src/app/tools/send/add-edit.component.ts index 49d66799e66..3fa766daf7f 100644 --- a/apps/desktop/src/app/tools/send/add-edit.component.ts +++ b/apps/desktop/src/app/tools/send/add-edit.component.ts @@ -1,6 +1,7 @@ import { DatePipe } from "@angular/common"; import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -27,7 +28,8 @@ export class AddEditComponent extends BaseAddEditComponent { messagingService: MessagingService, policyService: PolicyService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -39,7 +41,8 @@ export class AddEditComponent extends BaseAddEditComponent { policyService, logService, stateService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/desktop/src/app/tools/send/send.component.ts b/apps/desktop/src/app/tools/send/send.component.ts index 3999d7cd13a..7ac254190e0 100644 --- a/apps/desktop/src/app/tools/send/send.component.ts +++ b/apps/desktop/src/app/tools/send/send.component.ts @@ -1,5 +1,6 @@ import { Component, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { SendComponent as BaseSendComponent } from "@bitwarden/angular/tools/send/send.component"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; @@ -46,7 +47,8 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro policyService: PolicyService, private searchBarService: SearchBarService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( sendService, @@ -57,7 +59,8 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro searchService, policyService, logService, - sendApiService + sendApiService, + dialogService ); // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.searchBarService.searchText$.subscribe((searchText) => { diff --git a/apps/desktop/src/auth/lock.component.ts b/apps/desktop/src/auth/lock.component.ts index f15021683b2..b7ccedb8487 100644 --- a/apps/desktop/src/auth/lock.component.ts +++ b/apps/desktop/src/auth/lock.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { ipcRenderer } from "electron"; import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -50,7 +51,8 @@ export class LockComponent extends BaseLockComponent { policyService: InternalPolicyService, passwordGenerationService: PasswordGenerationServiceAbstraction, logService: LogService, - keyConnectorService: KeyConnectorService + keyConnectorService: KeyConnectorService, + dialogService: DialogServiceAbstraction ) { super( router, @@ -68,7 +70,8 @@ export class LockComponent extends BaseLockComponent { ngZone, policyApiService, policyService, - passwordGenerationService + passwordGenerationService, + dialogService ); } @@ -149,12 +152,11 @@ export class LockComponent extends BaseLockComponent { } if (await this.stateService.getBiometricUnlock()) { - const response = await this.platformUtilsService.showDialog( - this.i18nService.t("windowsBiometricUpdateWarning"), - this.i18nService.t("windowsBiometricUpdateWarningTitle"), - this.i18nService.t("yes"), - this.i18nService.t("no") - ); + const response = await this.dialogService.openSimpleDialog({ + title: { key: "windowsBiometricUpdateWarningTitle" }, + content: { key: "windowsBiometricUpdateWarning" }, + type: SimpleDialogType.WARNING, + }); await this.stateService.setBiometricRequirePasswordOnStart(response); if (response) { diff --git a/apps/desktop/src/auth/register.component.ts b/apps/desktop/src/auth/register.component.ts index bb036d36090..5e6b0b16778 100644 --- a/apps/desktop/src/auth/register.component.ts +++ b/apps/desktop/src/auth/register.component.ts @@ -3,6 +3,7 @@ import { UntypedFormBuilder } from "@angular/forms"; import { Router } from "@angular/router"; import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; @@ -38,7 +39,8 @@ export class RegisterComponent extends BaseRegisterComponent implements OnInit, private broadcasterService: BroadcasterService, private ngZone: NgZone, logService: LogService, - auditService: AuditService + auditService: AuditService, + dialogService: DialogServiceAbstraction ) { super( formValidationErrorService, @@ -53,7 +55,8 @@ export class RegisterComponent extends BaseRegisterComponent implements OnInit, passwordGenerationService, environmentService, logService, - auditService + auditService, + dialogService ); } diff --git a/apps/desktop/src/auth/set-password.component.ts b/apps/desktop/src/auth/set-password.component.ts index d4f904d83cd..d7a7c8d699d 100644 --- a/apps/desktop/src/auth/set-password.component.ts +++ b/apps/desktop/src/auth/set-password.component.ts @@ -2,6 +2,7 @@ import { Component, NgZone, OnDestroy } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -39,7 +40,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On private ngZone: NgZone, stateService: StateService, organizationApiService: OrganizationApiServiceAbstraction, - organizationUserService: OrganizationUserService + organizationUserService: OrganizationUserService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -55,7 +57,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On route, stateService, organizationApiService, - organizationUserService + organizationUserService, + dialogService ); } diff --git a/apps/desktop/src/services/electron-dialog.service.ts b/apps/desktop/src/services/electron-dialog.service.ts new file mode 100644 index 00000000000..e49e39e811b --- /dev/null +++ b/apps/desktop/src/services/electron-dialog.service.ts @@ -0,0 +1,62 @@ +import { ipcRenderer } from "electron"; + +import { + DialogService, + SimpleDialogOptions, + SimpleDialogType, +} from "@bitwarden/angular/services/dialog"; + +// Electron supports a limited set of dialog types +// https://www.electronjs.org/docs/latest/api/dialog#dialogshowmessageboxbrowserwindow-options +const electronTypeMap: Record = { + [SimpleDialogType.PRIMARY]: "info", + [SimpleDialogType.SUCCESS]: "info", + [SimpleDialogType.INFO]: "info", + [SimpleDialogType.WARNING]: "warning", + [SimpleDialogType.DANGER]: "error", +}; + +export class ElectronDialogService extends DialogService { + async openSimpleDialog(options: SimpleDialogOptions) { + const defaultCancel = + options.cancelButtonText === undefined + ? options.acceptButtonText == null + ? "no" + : "cancel" + : null; + + return this.legacyShowDialog( + this.translate(options.content), + this.translate(options.title), + this.translate(options.acceptButtonText, "yes"), + this.translate(options.cancelButtonText, defaultCancel), + options.type + ); + } + + private async legacyShowDialog( + body: string, + title?: string, + confirmText?: string, + cancelText?: string, + type?: SimpleDialogType + ) { + const buttons = [confirmText == null ? this.i18nService.t("ok") : confirmText]; + if (cancelText != null) { + buttons.push(cancelText); + } + + const result = await ipcRenderer.invoke("showMessageBox", { + type: electronTypeMap[type] ?? "none", + title: title, + message: title, + detail: body, + buttons: buttons, + cancelId: buttons.length === 2 ? 1 : null, + defaultId: 0, + noLink: true, + }); + + return Promise.resolve(result.response === 0); + } +} diff --git a/apps/desktop/src/services/electron-platform-utils.service.ts b/apps/desktop/src/services/electron-platform-utils.service.ts index d80b403980f..4a646033043 100644 --- a/apps/desktop/src/services/electron-platform-utils.service.ts +++ b/apps/desktop/src/services/electron-platform-utils.service.ts @@ -115,32 +115,6 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService { }); } - async showDialog( - text: string, - title?: string, - confirmText?: string, - cancelText?: string, - type?: string - ): Promise { - const buttons = [confirmText == null ? this.i18nService.t("ok") : confirmText]; - if (cancelText != null) { - buttons.push(cancelText); - } - - const result = await ipcRenderer.invoke("showMessageBox", { - type: type, - title: title, - message: title, - detail: text, - buttons: buttons, - cancelId: buttons.length === 2 ? 1 : null, - defaultId: 0, - noLink: true, - }); - - return Promise.resolve(result.response === 0); - } - isDev(): boolean { return isDev(); } diff --git a/apps/desktop/src/vault/app/accounts/premium.component.ts b/apps/desktop/src/vault/app/accounts/premium.component.ts index c8c4710006e..70650661e77 100644 --- a/apps/desktop/src/vault/app/accounts/premium.component.ts +++ b/apps/desktop/src/vault/app/accounts/premium.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { PremiumComponent as BasePremiumComponent } from "@bitwarden/angular/vault/components/premium.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -17,8 +18,9 @@ export class PremiumComponent extends BasePremiumComponent { platformUtilsService: PlatformUtilsService, apiService: ApiService, logService: LogService, - stateService: StateService + stateService: StateService, + dialogService: DialogServiceAbstraction ) { - super(i18nService, platformUtilsService, apiService, logService, stateService); + super(i18nService, platformUtilsService, apiService, logService, stateService, dialogService); } } diff --git a/apps/desktop/src/vault/app/vault/add-edit.component.ts b/apps/desktop/src/vault/app/vault/add-edit.component.ts index 1ee951b888b..8718f171d1d 100644 --- a/apps/desktop/src/vault/app/vault/add-edit.component.ts +++ b/apps/desktop/src/vault/app/vault/add-edit.component.ts @@ -1,6 +1,7 @@ import { Component, NgZone, OnChanges, OnDestroy, ViewChild } from "@angular/core"; import { NgForm } from "@angular/forms"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/vault/components/add-edit.component"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; @@ -43,7 +44,8 @@ export class AddEditComponent extends BaseAddEditComponent implements OnChanges, private ngZone: NgZone, logService: LogService, organizationService: OrganizationService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -59,7 +61,8 @@ export class AddEditComponent extends BaseAddEditComponent implements OnChanges, logService, passwordRepromptService, organizationService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/desktop/src/vault/app/vault/attachments.component.ts b/apps/desktop/src/vault/app/vault/attachments.component.ts index 6f6e5467670..bd327951a1a 100644 --- a/apps/desktop/src/vault/app/vault/attachments.component.ts +++ b/apps/desktop/src/vault/app/vault/attachments.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -23,7 +24,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { apiService: ApiService, logService: LogService, stateService: StateService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -34,7 +36,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { window, logService, stateService, - fileDownloadService + fileDownloadService, + dialogService ); } } diff --git a/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts b/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts index 08863c9ecfa..6b7321e634a 100644 --- a/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts +++ b/apps/desktop/src/vault/app/vault/folder-add-edit.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -17,8 +18,16 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { folderApiService: FolderApiServiceAbstraction, i18nService: I18nService, platformUtilsService: PlatformUtilsService, - logService: LogService + logService: LogService, + dialogService: DialogServiceAbstraction ) { - super(folderService, folderApiService, i18nService, platformUtilsService, logService); + super( + folderService, + folderApiService, + i18nService, + platformUtilsService, + logService, + dialogService + ); } } diff --git a/apps/desktop/src/vault/app/vault/vault.component.ts b/apps/desktop/src/vault/app/vault/vault.component.ts index 858c37971da..2290806e307 100644 --- a/apps/desktop/src/vault/app/vault/vault.component.ts +++ b/apps/desktop/src/vault/app/vault/vault.component.ts @@ -11,6 +11,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { first } from "rxjs/operators"; import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { VaultFilter } from "@bitwarden/angular/vault/vault-filter/models/vault-filter.model"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; @@ -100,7 +101,8 @@ export class VaultComponent implements OnInit, OnDestroy { private passwordRepromptService: PasswordRepromptService, private stateService: StateService, private searchBarService: SearchBarService, - private apiService: ApiService + private apiService: ApiService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -679,13 +681,11 @@ export class VaultComponent implements OnInit, OnDestroy { } private async wantsToSaveChanges(): Promise { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("unsavedChangesConfirmation"), - this.i18nService.t("unsavedChangesTitle"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "unsavedChangesTitle" }, + content: { key: "unsavedChangesConfirmation" }, + type: SimpleDialogType.WARNING, + }); return !confirmed; } diff --git a/apps/desktop/src/vault/app/vault/view.component.ts b/apps/desktop/src/vault/app/vault/view.component.ts index 84197026112..85b8930916b 100644 --- a/apps/desktop/src/vault/app/vault/view.component.ts +++ b/apps/desktop/src/vault/app/vault/view.component.ts @@ -7,6 +7,7 @@ import { Output, } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ViewComponent as BaseViewComponent } from "@bitwarden/angular/vault/components/view.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; @@ -53,7 +54,8 @@ export class ViewComponent extends BaseViewComponent implements OnChanges { passwordRepromptService: PasswordRepromptService, logService: LogService, stateService: StateService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -73,7 +75,8 @@ export class ViewComponent extends BaseViewComponent implements OnChanges { passwordRepromptService, logService, stateService, - fileDownloadService + fileDownloadService, + dialogService ); } ngOnInit() { diff --git a/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts b/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts index 79ad01eea94..8460568ea6e 100644 --- a/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts +++ b/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts @@ -1,9 +1,8 @@ import { Injectable } from "@angular/core"; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from "@angular/router"; -import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; -import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; @Injectable({ @@ -13,9 +12,8 @@ export class IsPaidOrgGuard implements CanActivate { constructor( private router: Router, private organizationService: OrganizationService, - private platformUtilsService: PlatformUtilsService, private messagingService: MessagingService, - private i18nService: I18nService + private dialogService: DialogServiceAbstraction ) {} async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { @@ -28,11 +26,13 @@ export class IsPaidOrgGuard implements CanActivate { if (org.isFreeOrg) { // Users without billing permission can't access billing if (!org.canEditSubscription) { - await this.platformUtilsService.showDialog( - this.i18nService.t("notAvailableForFreeOrganization"), - this.i18nService.t("upgradeOrganization"), - this.i18nService.t("ok") - ); + await this.dialogService.openSimpleDialog({ + title: { key: "upgradeOrganization" }, + content: { key: "notAvailableForFreeOrganization" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.INFO, + }); return false; } else { this.messagingService.send("upgradeOrganization", { organizationId: org.id }); diff --git a/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts b/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts index 6f918200221..d70cc061fd7 100644 --- a/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts @@ -3,6 +3,7 @@ import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from "@angula import { FormBuilder, Validators } from "@angular/forms"; import { catchError, combineLatest, from, map, of, Subject, switchMap, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -13,7 +14,6 @@ import { CollectionData } from "@bitwarden/common/admin-console/models/data/coll import { Collection } from "@bitwarden/common/admin-console/models/domain/collection"; import { CollectionDetailsResponse } from "@bitwarden/common/admin-console/models/response/collection.response"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; -import { DialogService } from "@bitwarden/components"; import { GroupService, GroupView } from "../core"; import { @@ -64,7 +64,7 @@ export enum GroupAddEditDialogResultType { * @param config Configuration for the dialog */ export const openGroupAddEditDialog = ( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) => { return dialogService.open( @@ -180,7 +180,8 @@ export class GroupAddEditComponent implements OnInit, OnDestroy { private platformUtilsService: PlatformUtilsService, private logService: LogService, private formBuilder: FormBuilder, - private changeDetectorRef: ChangeDetectorRef + private changeDetectorRef: ChangeDetectorRef, + private dialogService: DialogServiceAbstraction ) { this.tabIndex = params.initialTab ?? GroupAddEditTabType.Info; } @@ -269,15 +270,11 @@ export class GroupAddEditComponent implements OnInit, OnDestroy { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteGroupConfirmation"), - this.group.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - "app-group-add-edit .modal-content" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.group.name, + content: { key: "deleteGroupConfirmation" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; } diff --git a/apps/web/src/app/admin-console/organizations/manage/groups.component.ts b/apps/web/src/app/admin-console/organizations/manage/groups.component.ts index 118987de5db..79a8d3d86b3 100644 --- a/apps/web/src/app/admin-console/organizations/manage/groups.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/groups.component.ts @@ -15,6 +15,7 @@ import { import { first } from "rxjs/operators"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -31,7 +32,6 @@ import { import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view"; import { Utils } from "@bitwarden/common/misc/utils"; import { ListResponse } from "@bitwarden/common/models/response/list.response"; -import { DialogService } from "@bitwarden/components"; import { GroupService, GroupView } from "../core"; @@ -127,7 +127,7 @@ export class GroupsComponent implements OnInit, OnDestroy { private route: ActivatedRoute, private i18nService: I18nService, private modalService: ModalService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private platformUtilsService: PlatformUtilsService, private searchService: SearchService, private logService: LogService, @@ -233,13 +233,11 @@ export class GroupsComponent implements OnInit, OnDestroy { } async delete(groupRow: GroupDetailsRow) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteGroupConfirmation"), - groupRow.details.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: groupRow.details.name, + content: { key: "deleteGroupConfirmation" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; } @@ -265,13 +263,14 @@ export class GroupsComponent implements OnInit, OnDestroy { } const deleteMessage = groupsToDelete.map((g) => g.details.name).join(", "); - const confirmed = await this.platformUtilsService.showDialog( - deleteMessage, - this.i18nService.t("deleteMultipleGroupsConfirmation", groupsToDelete.length.toString()), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { + key: "deleteMultipleGroupsConfirmation", + placeholders: [groupsToDelete.length.toString()], + }, + content: deleteMessage, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; } diff --git a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts index 7b50cdf9e46..894eca5547b 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts @@ -3,6 +3,7 @@ import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { combineLatest, of, shareReplay, Subject, switchMap, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; @@ -14,7 +15,6 @@ import { import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view"; -import { DialogService } from "@bitwarden/components"; import { flagEnabled } from "../../../../../../utils/flags"; import { @@ -130,7 +130,8 @@ export class MemberDialogComponent implements OnInit, OnDestroy { private collectionAdminService: CollectionAdminService, private groupService: GroupService, private userService: UserAdminService, - private organizationUserService: OrganizationUserService + private organizationUserService: OrganizationUserService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -364,15 +365,13 @@ export class MemberDialogComponent implements OnInit, OnDestroy { const message = this.params.usesKeyConnector ? "removeUserConfirmationKeyConnector" : "removeOrgUserConfirmation"; - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t(message), - this.i18nService.t("removeUserIdAccess", this.params.name), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - "app-user-add-edit .modal-content" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "removeUserIdAccess", placeholders: [this.params.name] }, + content: { key: message }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -395,15 +394,13 @@ export class MemberDialogComponent implements OnInit, OnDestroy { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("revokeUserConfirmation"), - this.i18nService.t("revokeUserId", this.params.name), - this.i18nService.t("revokeAccess"), - this.i18nService.t("cancel"), - "warning", - false, - "app-user-add-edit .modal-content" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "revokeUserId", placeholders: [this.params.name] }, + content: { key: "revokeUserConfirmation" }, + acceptButtonText: { key: "revokeAccess" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -511,7 +508,7 @@ function mapToGroupAccessSelections(groups: string[]): AccessItemValue[] { * @param config Configuration for the dialog */ export function openUserAddEditDialog( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) { return dialogService.open(MemberDialogComponent, config); diff --git a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts index dfd85d353f6..cc15ccf8e30 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts @@ -10,6 +10,7 @@ import { import { Subject, takeUntil } from "rxjs"; import zxcvbn from "zxcvbn"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { PasswordStrengthComponent } from "@bitwarden/angular/shared/components/password-strength/password-strength.component"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -52,7 +53,8 @@ export class ResetPasswordComponent implements OnInit, OnDestroy { private policyService: PolicyService, private cryptoService: CryptoService, private logService: LogService, - private organizationUserService: OrganizationUserService + private organizationUserService: OrganizationUserService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -135,13 +137,12 @@ export class ResetPasswordComponent implements OnInit, OnDestroy { } if (this.passwordStrengthResult.score < 3) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakMasterPasswordDesc"), - this.i18nService.t("weakMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "weakMasterPassword" }, + content: { key: "weakMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return false; } diff --git a/apps/web/src/app/admin-console/organizations/members/people.component.ts b/apps/web/src/app/admin-console/organizations/members/people.component.ts index 0e922ba4ba5..aa42f488bdc 100644 --- a/apps/web/src/app/admin-console/organizations/members/people.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/people.component.ts @@ -15,6 +15,12 @@ import { import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe"; +import { + SimpleDialogType, + DialogServiceAbstraction, + SimpleDialogCloseType, + SimpleDialogOptions, +} from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -48,12 +54,6 @@ import { CollectionDetailsResponse } from "@bitwarden/common/admin-console/model import { ProductType } from "@bitwarden/common/enums"; import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { - DialogService, - SimpleDialogCloseType, - SimpleDialogOptions, - SimpleDialogType, -} from "@bitwarden/components"; import { EntityEventsComponent } from "../../../admin-console/organizations/manage/entity-events.component"; import { BasePeopleComponent } from "../../../common/base.people.component"; @@ -123,7 +123,7 @@ export class PeopleComponent private organizationService: OrganizationService, private organizationApiService: OrganizationApiServiceAbstraction, private organizationUserService: OrganizationUserService, - private dialogService: DialogService, + dialogService: DialogServiceAbstraction, private router: Router, private groupService: GroupService, private collectionService: CollectionService @@ -139,7 +139,8 @@ export class PeopleComponent logService, searchPipe, userNamePipe, - stateService + stateService, + dialogService ); } @@ -362,7 +363,7 @@ export class PeopleComponent orgUpgradeSimpleDialogOpts.cancelButtonText = null; // hide secondary btn } - const simpleDialog = this.dialogService.openSimpleDialog(orgUpgradeSimpleDialogOpts); + const simpleDialog = this.dialogService.openSimpleDialogRef(orgUpgradeSimpleDialogOpts); firstValueFrom(simpleDialog.closed).then((result: SimpleDialogCloseType | undefined) => { if (!result) { @@ -541,17 +542,18 @@ export class PeopleComponent } protected async removeUserConfirmationDialog(user: OrganizationUserView) { - const warningMessage = user.usesKeyConnector - ? this.i18nService.t("removeUserConfirmationKeyConnector") - : this.i18nService.t("removeOrgUserConfirmation"); + const content = user.usesKeyConnector + ? "removeUserConfirmationKeyConnector" + : "removeOrgUserConfirmation"; - return this.platformUtilsService.showDialog( - warningMessage, - this.i18nService.t("removeUserIdAccess", this.userNamePipe.transform(user)), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + return await this.dialogService.openSimpleDialog({ + title: { + key: "removeUserIdAccess", + placeholders: [this.userNamePipe.transform(user)], + }, + content: { key: content }, + type: SimpleDialogType.WARNING, + }); } private async showBulkStatus( diff --git a/apps/web/src/app/admin-console/organizations/shared/components/collection-dialog/collection-dialog.component.ts b/apps/web/src/app/admin-console/organizations/shared/components/collection-dialog/collection-dialog.component.ts index 35b57706383..817f8486e44 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/collection-dialog/collection-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/shared/components/collection-dialog/collection-dialog.component.ts @@ -3,6 +3,7 @@ import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { combineLatest, of, shareReplay, Subject, switchMap, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { OrganizationUserUserDetailsResponse } from "@bitwarden/common/abstractions/organization-user/responses"; @@ -10,7 +11,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { CollectionView } from "@bitwarden/common/admin-console/models/view/collection.view"; -import { BitValidators, DialogService } from "@bitwarden/components"; +import { BitValidators } from "@bitwarden/components"; import { CollectionAdminService, @@ -75,7 +76,8 @@ export class CollectionDialogComponent implements OnInit, OnDestroy { private collectionService: CollectionAdminService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private organizationUserService: OrganizationUserService + private organizationUserService: OrganizationUserService, + private dialogService: DialogServiceAbstraction ) { this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info; } @@ -200,13 +202,11 @@ export class CollectionDialogComponent implements OnInit, OnDestroy { }; protected delete = async () => { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteCollectionConfirmation"), - this.collection?.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.collection?.name, + content: { key: "deleteCollectionConfirmation" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed && this.params.collectionId) { return false; @@ -291,7 +291,7 @@ function mapToAccessSelections(collectionDetails: CollectionAdminView): AccessIt * @param config Configuration for the dialog */ export function openCollectionDialog( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) { return dialogService.open( diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts b/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts index 02dcec83e39..62605118111 100644 --- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { UntypedFormBuilder } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; @@ -34,7 +35,8 @@ export class OrganizationExportComponent extends ExportComponent { userVerificationService: UserVerificationService, formBuilder: UntypedFormBuilder, fileDownloadService: FileDownloadService, - modalService: ModalService + modalService: ModalService, + dialogService: DialogServiceAbstraction ) { super( cryptoService, @@ -47,7 +49,8 @@ export class OrganizationExportComponent extends ExportComponent { userVerificationService, formBuilder, fileDownloadService, - modalService + modalService, + dialogService ); } diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts b/apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts index 58027064064..e475be97aed 100644 --- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts @@ -1,6 +1,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -8,7 +9,6 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { DialogService } from "@bitwarden/components"; import { ImportServiceAbstraction } from "@bitwarden/importer"; import { ImportComponent } from "../../../../tools/import-export/import.component"; @@ -32,7 +32,7 @@ export class OrganizationImportComponent extends ImportComponent { logService: LogService, modalService: ModalService, syncService: SyncService, - dialogService: DialogService + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -59,13 +59,12 @@ export class OrganizationImportComponent extends ImportComponent { } async submit() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("importWarning", this.organizationName), - this.i18nService.t("warning"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "warning" }, + content: { key: "importWarning", placeholders: [this.organizationName] }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } diff --git a/apps/web/src/app/admin-console/settings/sponsoring-org-row.component.ts b/apps/web/src/app/admin-console/settings/sponsoring-org-row.component.ts index fd529ab1fb0..71f129831b7 100644 --- a/apps/web/src/app/admin-console/settings/sponsoring-org-row.component.ts +++ b/apps/web/src/app/admin-console/settings/sponsoring-org-row.component.ts @@ -2,6 +2,7 @@ import { formatDate } from "@angular/common"; import { Component, EventEmitter, Input, Output, OnInit } from "@angular/core"; import { firstValueFrom } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -30,7 +31,8 @@ export class SponsoringOrgRowComponent implements OnInit { private apiService: ApiService, private i18nService: I18nService, private logService: LogService, - private platformUtilsService: PlatformUtilsService + private platformUtilsService: PlatformUtilsService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -67,15 +69,14 @@ export class SponsoringOrgRowComponent implements OnInit { } private async doRevokeSponsorship() { - const isConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("revokeSponsorshipConfirmation"), - `${this.i18nService.t("remove")} ${this.sponsoringOrg.familySponsorshipFriendlyName}?`, - this.i18nService.t("remove"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: `${this.i18nService.t("remove")} ${this.sponsoringOrg.familySponsorshipFriendlyName}?`, + content: { key: "revokeSponsorshipConfirmation" }, + acceptButtonText: { key: "remove" }, + type: SimpleDialogType.WARNING, + }); - if (!isConfirmed) { + if (!confirmed) { return; } diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index 05ae0287b25..e3e93840e15 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -7,6 +7,7 @@ import { IndividualConfig, ToastrService } from "ngx-toastr"; import { Subject, takeUntil } from "rxjs"; import Swal from "sweetalert2"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -79,7 +80,8 @@ export class AppComponent implements OnDestroy, OnInit { private policyService: InternalPolicyService, protected policyListService: PolicyListService, private keyConnectorService: KeyConnectorService, - private configService: ConfigServiceAbstraction + private configService: ConfigServiceAbstraction, + private dialogService: DialogServiceAbstraction ) {} ngOnInit() { @@ -132,12 +134,12 @@ export class AppComponent implements OnDestroy, OnInit { await this.configService.fetchServerConfig(); break; case "upgradeOrganization": { - const upgradeConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("upgradeOrganizationDesc"), - this.i18nService.t("upgradeOrganization"), - this.i18nService.t("upgradeOrganization"), - this.i18nService.t("cancel") - ); + const upgradeConfirmed = await this.dialogService.openSimpleDialog({ + title: { key: "upgradeOrganization" }, + content: { key: "upgradeOrganizationDesc" }, + acceptButtonText: { key: "upgradeOrganization" }, + type: SimpleDialogType.INFO, + }); if (upgradeConfirmed) { this.router.navigate([ "organizations", @@ -149,24 +151,24 @@ export class AppComponent implements OnDestroy, OnInit { break; } case "premiumRequired": { - const premiumConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("premiumRequiredDesc"), - this.i18nService.t("premiumRequired"), - this.i18nService.t("upgrade"), - this.i18nService.t("cancel") - ); + const premiumConfirmed = await this.dialogService.openSimpleDialog({ + title: { key: "premiumRequired" }, + content: { key: "premiumRequiredDesc" }, + acceptButtonText: { key: "upgrade" }, + type: SimpleDialogType.SUCCESS, + }); if (premiumConfirmed) { this.router.navigate(["settings/subscription/premium"]); } break; } case "emailVerificationRequired": { - const emailVerificationConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("emailVerificationRequiredDesc"), - this.i18nService.t("emailVerificationRequired"), - this.i18nService.t("learnMore"), - this.i18nService.t("cancel") - ); + const emailVerificationConfirmed = await this.dialogService.openSimpleDialog({ + title: { key: "emailVerificationRequired" }, + content: { key: "emailVerificationRequiredDesc" }, + acceptButtonText: { key: "learnMore" }, + type: SimpleDialogType.INFO, + }); if (emailVerificationConfirmed) { this.platformUtilsService.launchUri( "https://bitwarden.com/help/create-bitwarden-account/" diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts index 3ee9d99b2a3..af24c8a9ebf 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts @@ -2,6 +2,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { concatMap, Subject, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalConfig, ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -46,7 +47,8 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy private modalService: ModalService, private organizationService: OrganizationService, private organizationApiService: OrganizationApiServiceAbstraction, - private route: ActivatedRoute + private route: ActivatedRoute, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -203,13 +205,12 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("cancelConfirmation"), - this.i18nService.t("cancelSubscription"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "cancelSubscription" }, + content: { key: "cancelConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } @@ -232,12 +233,12 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("reinstateConfirmation"), - this.i18nService.t("reinstateSubscription"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "reinstateSubscription" }, + content: { key: "reinstateConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } @@ -303,15 +304,14 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy } removeSponsorship = async () => { - const isConfirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removeSponsorshipConfirmation"), - this.i18nService.t("removeSponsorship"), - this.i18nService.t("remove"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "removeSponsorship" }, + content: { key: "removeSponsorshipConfirmation" }, + acceptButtonText: { key: "remove" }, + type: SimpleDialogType.WARNING, + }); - if (!isConfirmed) { + if (!confirmed) { return; } diff --git a/apps/web/src/app/billing/settings/payment-method.component.ts b/apps/web/src/app/billing/settings/payment-method.component.ts index e28375a14de..0ea51eb4fca 100644 --- a/apps/web/src/app/billing/settings/payment-method.component.ts +++ b/apps/web/src/app/billing/settings/payment-method.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, FormControl, Validators } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -55,7 +56,8 @@ export class PaymentMethodComponent implements OnInit { private router: Router, private logService: LogService, private route: ActivatedRoute, - private formBuilder: FormBuilder + private formBuilder: FormBuilder, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -93,13 +95,14 @@ export class PaymentMethodComponent implements OnInit { addCredit() { if (this.paymentSourceInApp) { - this.platformUtilsService.showDialog( - this.i18nService.t("cannotPerformInAppPurchase"), - this.i18nService.t("addCredit"), - null, - null, - "warning" - ); + this.dialogService.openSimpleDialog({ + title: { key: "addCredit" }, + content: { key: "cannotPerformInAppPurchase" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); + return; } this.showAddCredit = true; @@ -114,13 +117,14 @@ export class PaymentMethodComponent implements OnInit { changePayment() { if (this.paymentSourceInApp) { - this.platformUtilsService.showDialog( - this.i18nService.t("cannotPerformInAppPurchase"), - this.i18nService.t("changePaymentMethod"), - null, - null, - "warning" - ); + this.dialogService.openSimpleDialog({ + title: { key: "changePaymentMethod" }, + content: { key: "cannotPerformInAppPurchase" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); + return; } this.showAdjustPayment = true; diff --git a/apps/web/src/app/billing/settings/user-subscription.component.ts b/apps/web/src/app/billing/settings/user-subscription.component.ts index fcf210f658a..6f78a420604 100644 --- a/apps/web/src/app/billing/settings/user-subscription.component.ts +++ b/apps/web/src/app/billing/settings/user-subscription.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { Router } from "@angular/router"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -32,7 +33,8 @@ export class UserSubscriptionComponent implements OnInit { private i18nService: I18nService, private router: Router, private logService: LogService, - private fileDownloadService: FileDownloadService + private fileDownloadService: FileDownloadService, + private dialogService: DialogServiceAbstraction ) { this.selfHosted = platformUtilsService.isSelfHost(); } @@ -64,22 +66,23 @@ export class UserSubscriptionComponent implements OnInit { } if (this.usingInAppPurchase) { - this.platformUtilsService.showDialog( - this.i18nService.t("manageSubscriptionFromStore"), - this.i18nService.t("cancelSubscription"), - null, - null, - "warning" - ); + this.dialogService.openSimpleDialog({ + title: { key: "cancelSubscription" }, + content: { key: "manageSubscriptionFromStore" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); + return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("reinstateConfirmation"), - this.i18nService.t("reinstateSubscription"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "reinstateSubscription" }, + content: { key: "reinstateConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } @@ -100,23 +103,23 @@ export class UserSubscriptionComponent implements OnInit { } if (this.usingInAppPurchase) { - this.platformUtilsService.showDialog( - this.i18nService.t("manageSubscriptionFromStore"), - this.i18nService.t("cancelSubscription"), - null, - null, - "warning" - ); + this.dialogService.openSimpleDialog({ + title: { key: "cancelSubscription" }, + content: { key: "manageSubscriptionFromStore" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); + return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("cancelConfirmation"), - this.i18nService.t("cancelSubscription"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "cancelSubscription" }, + content: { key: "cancelConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } @@ -163,13 +166,14 @@ export class UserSubscriptionComponent implements OnInit { adjustStorage(add: boolean) { if (this.usingInAppPurchase) { - this.platformUtilsService.showDialog( - this.i18nService.t("cannotPerformInAppPurchase"), - this.i18nService.t(add ? "addStorage" : "removeStorage"), - null, - null, - "warning" - ); + this.dialogService.openSimpleDialog({ + title: { key: add ? "addStorage" : "removeStorage" }, + content: { key: "cannotPerformInAppPurchase" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.WARNING, + }); + return; } this.adjustStorageAdd = add; diff --git a/apps/web/src/app/common/base.people.component.ts b/apps/web/src/app/common/base.people.component.ts index 8225b73ed9c..46d9c03a81b 100644 --- a/apps/web/src/app/common/base.people.component.ts +++ b/apps/web/src/app/common/base.people.component.ts @@ -2,6 +2,7 @@ import { Directive, ViewChild, ViewContainerRef } from "@angular/core"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -108,7 +109,8 @@ export abstract class BasePeopleComponent< private logService: LogService, private searchPipe: SearchPipe, protected userNamePipe: UserNamePipe, - protected stateService: StateService + protected stateService: StateService, + protected dialogService: DialogServiceAbstraction ) {} abstract edit(user: UserType): void; @@ -217,13 +219,11 @@ export abstract class BasePeopleComponent< } protected async removeUserConfirmationDialog(user: UserType) { - return this.platformUtilsService.showDialog( - this.i18nService.t("removeUserConfirmation"), - this.userNamePipe.transform(user), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + return this.dialogService.openSimpleDialog({ + title: this.userNamePipe.transform(user), + content: { key: "removeUserConfirmation" }, + type: SimpleDialogType.WARNING, + }); } async remove(user: UserType) { @@ -248,13 +248,12 @@ export abstract class BasePeopleComponent< } async revoke(user: UserType) { - const confirmed = await this.platformUtilsService.showDialog( - this.revokeWarningMessage(), - this.i18nService.t("revokeUserId", this.userNamePipe.transform(user)), - this.i18nService.t("revokeAccess"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "revokeAccess", placeholders: [this.userNamePipe.transform(user)] }, + content: this.revokeWarningMessage(), + acceptButtonText: { key: "revokeAccess" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; diff --git a/apps/web/src/app/core/web-platform-utils.service.ts b/apps/web/src/app/core/web-platform-utils.service.ts index 302d0302171..7b9a7b94770 100644 --- a/apps/web/src/app/core/web-platform-utils.service.ts +++ b/apps/web/src/app/core/web-platform-utils.service.ts @@ -1,5 +1,4 @@ import { Injectable } from "@angular/core"; -import Swal, { SweetAlertIcon } from "sweetalert2"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -133,66 +132,6 @@ export class WebPlatformUtilsService implements PlatformUtilsService { }); } - async showDialog( - body: string, - title?: string, - confirmText?: string, - cancelText?: string, - type?: string, - bodyIsHtml = false, - target?: string - ) { - let iconClasses: string = null; - if (type != null) { - // If you add custom types to this part, the type to SweetAlertIcon cast below needs to be changed. - switch (type) { - case "success": - iconClasses = "bwi-check text-success"; - break; - case "warning": - iconClasses = "bwi-exclamation-triangle text-warning"; - break; - case "error": - iconClasses = "bwi-error text-danger"; - break; - case "info": - iconClasses = "bwi-info-circle text-info"; - break; - default: - break; - } - } - - const bootstrapModal = document.querySelector("div.modal"); - if (bootstrapModal != null) { - bootstrapModal.removeAttribute("tabindex"); - } - - const iconHtmlStr = - iconClasses != null ? `` : undefined; - const confirmed = await Swal.fire({ - heightAuto: false, - buttonsStyling: false, - icon: type as SweetAlertIcon, // required to be any of the SweetAlertIcons to output the iconHtml. - iconHtml: iconHtmlStr, - text: bodyIsHtml ? null : body, - html: bodyIsHtml ? body : null, - titleText: title, - showCancelButton: cancelText != null, - cancelButtonText: cancelText, - showConfirmButton: true, - confirmButtonText: confirmText == null ? this.i18nService.t("ok") : confirmText, - target: target != null ? target : "body", - onOpen: () => Swal.getConfirmButton().focus(), - }); - - if (bootstrapModal != null) { - bootstrapModal.setAttribute("tabindex", "-1"); - } - - return confirmed.value; - } - isDev(): boolean { return process.env.NODE_ENV === "development"; } diff --git a/apps/web/src/app/settings/change-kdf/change-kdf.component.ts b/apps/web/src/app/settings/change-kdf/change-kdf.component.ts index 9c9abec15e6..ae599bca6b3 100644 --- a/apps/web/src/app/settings/change-kdf/change-kdf.component.ts +++ b/apps/web/src/app/settings/change-kdf/change-kdf.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { StateService } from "@bitwarden/common/abstractions/state.service"; import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config"; import { @@ -10,7 +11,6 @@ import { DEFAULT_ARGON2_PARALLELISM, KdfType, } from "@bitwarden/common/enums"; -import { DialogService } from "@bitwarden/components"; import { ChangeKdfConfirmationComponent } from "./change-kdf-confirmation.component"; @@ -25,7 +25,7 @@ export class ChangeKdfComponent implements OnInit { kdfOptions: any[] = []; recommendedPbkdf2Iterations = DEFAULT_PBKDF2_ITERATIONS; - constructor(private stateService: StateService, private dialogService: DialogService) { + constructor(private stateService: StateService, private dialogService: DialogServiceAbstraction) { this.kdfOptions = [ { name: "PBKDF2 SHA-256", value: KdfType.PBKDF2_SHA256 }, { name: "Argon2id", value: KdfType.Argon2id }, diff --git a/apps/web/src/app/settings/change-password.component.ts b/apps/web/src/app/settings/change-password.component.ts index 878c6c5d2bd..10b83e9ff77 100644 --- a/apps/web/src/app/settings/change-password.component.ts +++ b/apps/web/src/app/settings/change-password.component.ts @@ -3,6 +3,7 @@ import { Router } from "@angular/router"; import { firstValueFrom } from "rxjs"; import { ChangePasswordComponent as BaseChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -61,7 +62,8 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { private keyConnectorService: KeyConnectorService, private router: Router, private organizationApiService: OrganizationApiServiceAbstraction, - private organizationUserService: OrganizationUserService + private organizationUserService: OrganizationUserService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -70,7 +72,8 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { passwordGenerationService, platformUtilsService, policyService, - stateService + stateService, + dialogService ); } @@ -99,13 +102,14 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { } if (hasOldAttachments) { - const learnMore = await this.platformUtilsService.showDialog( - this.i18nService.t("oldAttachmentsNeedFixDesc"), - null, - this.i18nService.t("learnMore"), - this.i18nService.t("close"), - "warning" - ); + const learnMore = await this.dialogService.openSimpleDialog({ + title: { key: "warning" }, + content: { key: "oldAttachmentsNeedFixDesc" }, + acceptButtonText: { key: "learnMore" }, + cancelButtonText: { key: "close" }, + type: SimpleDialogType.WARNING, + }); + if (learnMore) { this.platformUtilsService.launchUri( "https://bitwarden.com/help/attachments/#add-storage-space" @@ -115,17 +119,17 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { return; } - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("updateEncryptionKeyWarning") + + const result = await this.dialogService.openSimpleDialog({ + title: { key: "rotateEncKeyTitle" }, + content: + this.i18nService.t("updateEncryptionKeyWarning") + " " + this.i18nService.t("updateEncryptionKeyExportWarning") + " " + this.i18nService.t("rotateEncKeyConfirmation"), - this.i18nService.t("rotateEncKeyTitle"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + type: SimpleDialogType.WARNING, + }); + if (!result) { this.rotateEncKey = false; } diff --git a/apps/web/src/app/settings/preferences.component.ts b/apps/web/src/app/settings/preferences.component.ts index e7bd55dd083..5f9e156b099 100644 --- a/apps/web/src/app/settings/preferences.component.ts +++ b/apps/web/src/app/settings/preferences.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { concatMap, filter, map, Observable, Subject, takeUntil, tap } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; @@ -53,7 +54,8 @@ export class PreferencesComponent implements OnInit { private platformUtilsService: PlatformUtilsService, private messagingService: MessagingService, private themingService: AbstractThemingService, - private settingsService: SettingsService + private settingsService: SettingsService, + private dialogService: DialogServiceAbstraction ) { this.vaultTimeoutOptions = [ { name: i18nService.t("oneMinute"), value: 1 }, @@ -112,13 +114,12 @@ export class PreferencesComponent implements OnInit { .pipe( concatMap(async (action) => { if (action === VaultTimeoutAction.LogOut) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("vaultTimeoutLogOutConfirmation"), - this.i18nService.t("vaultTimeoutLogOutConfirmationTitle"), - this.i18nService.t("yes"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "vaultTimeoutLogOutConfirmationTitle" }, + content: { key: "vaultTimeoutLogOutConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { this.form.controls.vaultTimeoutAction.patchValue(VaultTimeoutAction.Lock, { emitEvent: false, diff --git a/apps/web/src/app/tools/import-export/export.component.ts b/apps/web/src/app/tools/import-export/export.component.ts index 2f7dce6d139..0b3982dcb7d 100644 --- a/apps/web/src/app/tools/import-export/export.component.ts +++ b/apps/web/src/app/tools/import-export/export.component.ts @@ -1,6 +1,7 @@ import { Component } from "@angular/core"; import { UntypedFormBuilder } from "@angular/forms"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -36,7 +37,8 @@ export class ExportComponent extends BaseExportComponent { userVerificationService: UserVerificationService, formBuilder: UntypedFormBuilder, fileDownloadService: FileDownloadService, - private modalService: ModalService + private modalService: ModalService, + dialogService: DialogServiceAbstraction ) { super( cryptoService, @@ -49,7 +51,8 @@ export class ExportComponent extends BaseExportComponent { logService, userVerificationService, formBuilder, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/web/src/app/tools/import-export/import.component.ts b/apps/web/src/app/tools/import-export/import.component.ts index 1121015521a..89104e2e339 100644 --- a/apps/web/src/app/tools/import-export/import.component.ts +++ b/apps/web/src/app/tools/import-export/import.component.ts @@ -4,6 +4,7 @@ import * as JSZip from "jszip"; import { firstValueFrom } from "rxjs"; import Swal, { SweetAlertIcon } from "sweetalert2"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -11,7 +12,6 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { DialogService } from "@bitwarden/components"; import { ImportOption, ImportType, @@ -46,7 +46,7 @@ export class ImportComponent implements OnInit { private logService: LogService, protected modalService: ModalService, protected syncService: SyncService, - protected dialogService: DialogService + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { diff --git a/apps/web/src/app/tools/send/add-edit.component.ts b/apps/web/src/app/tools/send/add-edit.component.ts index ff602b0bb58..627b5f4e314 100644 --- a/apps/web/src/app/tools/send/add-edit.component.ts +++ b/apps/web/src/app/tools/send/add-edit.component.ts @@ -1,6 +1,7 @@ import { DatePipe } from "@angular/common"; import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -29,7 +30,8 @@ export class AddEditComponent extends BaseAddEditComponent { messagingService: MessagingService, policyService: PolicyService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -41,7 +43,8 @@ export class AddEditComponent extends BaseAddEditComponent { policyService, logService, stateService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/web/src/app/tools/send/send.component.ts b/apps/web/src/app/tools/send/send.component.ts index 725bd1d56f0..9d67dbbc5f0 100644 --- a/apps/web/src/app/tools/send/send.component.ts +++ b/apps/web/src/app/tools/send/send.component.ts @@ -1,5 +1,6 @@ import { Component, NgZone, ViewChild, ViewContainerRef } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { SendComponent as BaseSendComponent } from "@bitwarden/angular/tools/send/send.component"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; @@ -38,7 +39,8 @@ export class SendComponent extends BaseSendComponent { private modalService: ModalService, private broadcasterService: BroadcasterService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( sendService, @@ -49,7 +51,8 @@ export class SendComponent extends BaseSendComponent { searchService, policyService, logService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/web/src/app/vault/individual-vault/add-edit.component.ts b/apps/web/src/app/vault/individual-vault/add-edit.component.ts index b938a8948f8..6d6c474b106 100644 --- a/apps/web/src/app/vault/individual-vault/add-edit.component.ts +++ b/apps/web/src/app/vault/individual-vault/add-edit.component.ts @@ -1,5 +1,6 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/vault/components/add-edit.component"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; @@ -57,7 +58,8 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On organizationService: OrganizationService, logService: LogService, passwordRepromptService: PasswordRepromptService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -73,7 +75,8 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On logService, passwordRepromptService, organizationService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/web/src/app/vault/individual-vault/attachments.component.ts b/apps/web/src/app/vault/individual-vault/attachments.component.ts index 82930f819d5..cd28b82277f 100644 --- a/apps/web/src/app/vault/individual-vault/attachments.component.ts +++ b/apps/web/src/app/vault/individual-vault/attachments.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -27,7 +28,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { platformUtilsService: PlatformUtilsService, apiService: ApiService, logService: LogService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -38,7 +40,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { window, logService, stateService, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-delete-dialog/bulk-delete-dialog.component.ts b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-delete-dialog/bulk-delete-dialog.component.ts index 479083820bc..1d85ec3e82f 100644 --- a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-delete-dialog/bulk-delete-dialog.component.ts +++ b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-delete-dialog/bulk-delete-dialog.component.ts @@ -1,6 +1,7 @@ import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; @@ -8,7 +9,6 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { CollectionBulkDeleteRequest } from "@bitwarden/common/models/request/collection-bulk-delete.request"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherBulkDeleteRequest } from "@bitwarden/common/vault/models/request/cipher-bulk-delete.request"; -import { DialogService } from "@bitwarden/components"; export interface BulkDeleteDialogParams { cipherIds?: string[]; @@ -28,7 +28,7 @@ export enum BulkDeleteDialogResult { * @param config Configuration for the dialog */ export const openBulkDeleteDialog = ( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) => { return dialogService.open( diff --git a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-move-dialog/bulk-move-dialog.component.ts b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-move-dialog/bulk-move-dialog.component.ts index 3775bb9362c..a2ba7b5a26b 100644 --- a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-move-dialog/bulk-move-dialog.component.ts +++ b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-move-dialog/bulk-move-dialog.component.ts @@ -3,12 +3,12 @@ import { Component, Inject, OnInit } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { firstValueFrom, Observable } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; -import { DialogService } from "@bitwarden/components"; export interface BulkMoveDialogParams { cipherIds?: string[]; @@ -25,7 +25,7 @@ export enum BulkMoveDialogResult { * @param config Configuration for the dialog */ export const openBulkMoveDialog = ( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) => { return dialogService.open( diff --git a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-restore-dialog/bulk-restore-dialog.component.ts b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-restore-dialog/bulk-restore-dialog.component.ts index 470a6affe53..08e0801dc5e 100644 --- a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-restore-dialog/bulk-restore-dialog.component.ts +++ b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-restore-dialog/bulk-restore-dialog.component.ts @@ -1,10 +1,10 @@ import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { DialogService } from "@bitwarden/components"; export interface BulkRestoreDialogParams { cipherIds: string[]; @@ -21,7 +21,7 @@ export enum BulkRestoreDialogResult { * @param config Configuration for the dialog */ export const openBulkRestoreDialog = ( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) => { return dialogService.open( diff --git a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-share-dialog/bulk-share-dialog.component.ts b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-share-dialog/bulk-share-dialog.component.ts index 592a704786f..8a60f929ce4 100644 --- a/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-share-dialog/bulk-share-dialog.component.ts +++ b/apps/web/src/app/vault/individual-vault/bulk-action-dialogs/bulk-share-dialog/bulk-share-dialog.component.ts @@ -1,6 +1,7 @@ import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject, OnInit } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; @@ -11,7 +12,6 @@ import { CollectionView } from "@bitwarden/common/admin-console/models/view/coll import { Checkable, isChecked } from "@bitwarden/common/types/checkable"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; -import { DialogService } from "@bitwarden/components"; export interface BulkShareDialogParams { ciphers: CipherView[]; @@ -29,7 +29,7 @@ export enum BulkShareDialogResult { * @param config Configuration for the dialog */ export const openBulkShareDialog = ( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, config: DialogConfig ) => { return dialogService.open( diff --git a/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts b/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts index bb3c03f750d..4f593bf7d75 100644 --- a/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts +++ b/apps/web/src/app/vault/individual-vault/folder-add-edit.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -18,8 +19,16 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent { folderApiService: FolderApiServiceAbstraction, i18nService: I18nService, platformUtilsService: PlatformUtilsService, - logService: LogService + logService: LogService, + dialogService: DialogServiceAbstraction ) { - super(folderService, folderApiService, i18nService, platformUtilsService, logService); + super( + folderService, + folderApiService, + i18nService, + platformUtilsService, + logService, + dialogService + ); } } diff --git a/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts b/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts index 8bb6fcbb91f..d661c307535 100644 --- a/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-filter/components/organization-options.component.ts @@ -1,6 +1,7 @@ import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { map, Subject, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -40,7 +41,8 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy { private modalService: ModalService, private logService: LogService, private organizationApiService: OrganizationApiServiceAbstraction, - private organizationUserService: OrganizationUserService + private organizationUserService: OrganizationUserService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -80,13 +82,12 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy { } async unlinkSso(org: Organization) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("unlinkSsoConfirmation"), - org.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: org.name, + content: { key: "unlinkSsoConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -103,13 +104,12 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy { } async leave(org: Organization) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("leaveOrganizationConfirmation"), - org.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: org.name, + content: { key: "leaveOrganizationConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts index 9ecf6a5247b..7bd8cba33f9 100644 --- a/apps/web/src/app/vault/individual-vault/vault.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault.component.ts @@ -29,6 +29,7 @@ import { } from "rxjs/operators"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -54,7 +55,7 @@ import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/pa import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; -import { DialogService, Icons } from "@bitwarden/components"; +import { Icons } from "@bitwarden/components"; import { UpdateKeyComponent } from "../../settings/update-key.component"; import { VaultItemEvent } from "../components/vault-items/vault-item-event"; @@ -151,7 +152,7 @@ export class VaultComponent implements OnInit, OnDestroy { private changeDetectorRef: ChangeDetectorRef, private i18nService: I18nService, private modalService: ModalService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private tokenService: TokenService, private cryptoService: CryptoService, private messagingService: MessagingService, @@ -650,13 +651,13 @@ export class VaultComponent implements OnInit, OnDestroy { if (!c.isDeleted) { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("restoreItemConfirmation"), - this.i18nService.t("restoreItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "restoreItemConfirmation" }, + content: { key: "restoreItem" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -701,15 +702,13 @@ export class VaultComponent implements OnInit, OnDestroy { } const permanent = c.isDeleted; - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t( - permanent ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" - ), - this.i18nService.t(permanent ? "permanentlyDeleteItem" : "deleteItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: permanent ? "permanentlyDeleteItem" : "deleteItem" }, + content: { key: permanent ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/apps/web/src/app/vault/org-vault/add-edit.component.ts b/apps/web/src/app/vault/org-vault/add-edit.component.ts index f97edd013bf..02bc3899b89 100644 --- a/apps/web/src/app/vault/org-vault/add-edit.component.ts +++ b/apps/web/src/app/vault/org-vault/add-edit.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; @@ -49,7 +50,8 @@ export class AddEditComponent extends BaseAddEditComponent { logService: LogService, passwordRepromptService: PasswordRepromptService, organizationService: OrganizationService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -67,7 +69,8 @@ export class AddEditComponent extends BaseAddEditComponent { organizationService, logService, passwordRepromptService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/web/src/app/vault/org-vault/attachments.component.ts b/apps/web/src/app/vault/org-vault/attachments.component.ts index 3b2f140b45d..7ccdb3931a7 100644 --- a/apps/web/src/app/vault/org-vault/attachments.component.ts +++ b/apps/web/src/app/vault/org-vault/attachments.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service"; @@ -31,7 +32,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { platformUtilsService: PlatformUtilsService, apiService: ApiService, logService: LogService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -41,7 +43,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent { platformUtilsService, apiService, logService, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts index 385b1986387..997b7ee795d 100644 --- a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts +++ b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts @@ -2,17 +2,17 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; import { Router } from "@angular/router"; import { firstValueFrom } from "rxjs"; +import { + SimpleDialogType, + DialogServiceAbstraction, + SimpleDialogCloseType, + SimpleDialogOptions, +} from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { ProductType } from "@bitwarden/common/enums"; import { TreeNode } from "@bitwarden/common/models/domain/tree-node"; -import { - DialogService, - SimpleDialogCloseType, - SimpleDialogOptions, - SimpleDialogType, -} from "@bitwarden/components"; import { CollectionAdminService, @@ -66,7 +66,7 @@ export class VaultHeaderComponent { constructor( private organizationService: OrganizationService, private i18nService: I18nService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private collectionAdminService: CollectionAdminService, private router: Router ) {} @@ -126,7 +126,7 @@ export class VaultHeaderComponent { orgUpgradeSimpleDialogOpts.cancelButtonText = null; // hide secondary btn } - const simpleDialog = this.dialogService.openSimpleDialog(orgUpgradeSimpleDialogOpts); + const simpleDialog = this.dialogService.openSimpleDialogRef(orgUpgradeSimpleDialogOpts); firstValueFrom(simpleDialog.closed).then((result: SimpleDialogCloseType | undefined) => { if (!result) { diff --git a/apps/web/src/app/vault/org-vault/vault.component.ts b/apps/web/src/app/vault/org-vault/vault.component.ts index 5db6d25f874..1867b157d1a 100644 --- a/apps/web/src/app/vault/org-vault/vault.component.ts +++ b/apps/web/src/app/vault/org-vault/vault.component.ts @@ -30,6 +30,7 @@ import { } from "rxjs/operators"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service"; @@ -52,7 +53,7 @@ import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/pa import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; -import { DialogService, Icons } from "@bitwarden/components"; +import { Icons } from "@bitwarden/components"; import { CollectionAdminService, @@ -147,7 +148,7 @@ export class VaultComponent implements OnInit, OnDestroy { private syncService: SyncService, private i18nService: I18nService, private modalService: ModalService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private messagingService: MessagingService, private broadcasterService: BroadcasterService, private ngZone: NgZone, @@ -662,13 +663,13 @@ export class VaultComponent implements OnInit, OnDestroy { if (!c.isDeleted) { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("restoreItemConfirmation"), - this.i18nService.t("restoreItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "restoreItem" }, + content: { key: "restoreItemConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -714,15 +715,13 @@ export class VaultComponent implements OnInit, OnDestroy { } const permanent = c.isDeleted; - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t( - permanent ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" - ), - this.i18nService.t(permanent ? "permanentlyDeleteItem" : "deleteItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: permanent ? "permanentlyDeleteItem" : "deleteItem" }, + content: { key: permanent ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -752,13 +751,12 @@ export class VaultComponent implements OnInit, OnDestroy { ); return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteCollectionConfirmation"), - collection.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: collection.name, + content: { key: "deleteCollectionConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } diff --git a/apps/web/src/auth/lock.component.ts b/apps/web/src/auth/lock.component.ts index 31816bde207..ac68e7ae66d 100644 --- a/apps/web/src/auth/lock.component.ts +++ b/apps/web/src/auth/lock.component.ts @@ -2,6 +2,7 @@ import { Component, NgZone } from "@angular/core"; import { Router } from "@angular/router"; import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; @@ -41,7 +42,8 @@ export class LockComponent extends BaseLockComponent { ngZone: NgZone, policyApiService: PolicyApiServiceAbstraction, policyService: InternalPolicyService, - passwordGenerationService: PasswordGenerationServiceAbstraction + passwordGenerationService: PasswordGenerationServiceAbstraction, + dialogService: DialogServiceAbstraction ) { super( router, @@ -59,7 +61,8 @@ export class LockComponent extends BaseLockComponent { ngZone, policyApiService, policyService, - passwordGenerationService + passwordGenerationService, + dialogService ); } diff --git a/apps/web/src/auth/register-form/register-form.component.ts b/apps/web/src/auth/register-form/register-form.component.ts index 6b14a518b1e..0c9631a970f 100644 --- a/apps/web/src/auth/register-form/register-form.component.ts +++ b/apps/web/src/auth/register-form/register-form.component.ts @@ -3,6 +3,7 @@ import { UntypedFormBuilder } from "@angular/forms"; import { Router } from "@angular/router"; import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -44,7 +45,8 @@ export class RegisterFormComponent extends BaseRegisterComponent { private policyService: PolicyService, environmentService: EnvironmentService, logService: LogService, - auditService: AuditService + auditService: AuditService, + dialogService: DialogServiceAbstraction ) { super( formValidationErrorService, @@ -59,7 +61,8 @@ export class RegisterFormComponent extends BaseRegisterComponent { passwordGenerationService, environmentService, logService, - auditService + auditService, + dialogService ); } diff --git a/apps/web/src/auth/set-password.component.ts b/apps/web/src/auth/set-password.component.ts index a5e62696cbb..ed8ca0d7453 100644 --- a/apps/web/src/auth/set-password.component.ts +++ b/apps/web/src/auth/set-password.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -34,7 +35,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { route: ActivatedRoute, stateService: StateService, organizationApiService: OrganizationApiServiceAbstraction, - organizationUserService: OrganizationUserService + organizationUserService: OrganizationUserService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -50,7 +52,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { route, stateService, organizationApiService, - organizationUserService + organizationUserService, + dialogService ); } } diff --git a/apps/web/src/auth/settings/emergency-access/emergency-access-attachments.component.ts b/apps/web/src/auth/settings/emergency-access/emergency-access-attachments.component.ts index 05c7b6c577c..82db35e6703 100644 --- a/apps/web/src/auth/settings/emergency-access/emergency-access-attachments.component.ts +++ b/apps/web/src/auth/settings/emergency-access/emergency-access-attachments.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -27,7 +28,8 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen platformUtilsService: PlatformUtilsService, apiService: ApiService, logService: LogService, - fileDownloadService: FileDownloadService + fileDownloadService: FileDownloadService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -38,7 +40,8 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen window, logService, stateService, - fileDownloadService + fileDownloadService, + dialogService ); } diff --git a/apps/web/src/auth/settings/emergency-access/emergency-access-takeover.component.ts b/apps/web/src/auth/settings/emergency-access/emergency-access-takeover.component.ts index 46486eb05f2..23a68315062 100644 --- a/apps/web/src/auth/settings/emergency-access/emergency-access-takeover.component.ts +++ b/apps/web/src/auth/settings/emergency-access/emergency-access-takeover.component.ts @@ -2,6 +2,7 @@ import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angu import { takeUntil } from "rxjs"; import { ChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -46,7 +47,8 @@ export class EmergencyAccessTakeoverComponent platformUtilsService: PlatformUtilsService, policyService: PolicyService, private apiService: ApiService, - private logService: LogService + private logService: LogService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -55,7 +57,8 @@ export class EmergencyAccessTakeoverComponent passwordGenerationService, platformUtilsService, policyService, - stateService + stateService, + dialogService ); } diff --git a/apps/web/src/auth/settings/emergency-access/emergency-access.component.ts b/apps/web/src/auth/settings/emergency-access/emergency-access.component.ts index daabe1288c9..a03c6822530 100644 --- a/apps/web/src/auth/settings/emergency-access/emergency-access.component.ts +++ b/apps/web/src/auth/settings/emergency-access/emergency-access.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core"; import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -54,7 +55,8 @@ export class EmergencyAccessComponent implements OnInit { private userNamePipe: UserNamePipe, private logService: LogService, private stateService: StateService, - private organizationService: OrganizationService + private organizationService: OrganizationService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -169,13 +171,12 @@ export class EmergencyAccessComponent implements OnInit { async remove( details: EmergencyAccessGranteeDetailsResponse | EmergencyAccessGrantorDetailsResponse ) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removeUserConfirmation"), - this.userNamePipe.transform(details), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.userNamePipe.transform(details), + content: { key: "removeUserConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -199,13 +200,15 @@ export class EmergencyAccessComponent implements OnInit { } async requestAccess(details: EmergencyAccessGrantorDetailsResponse) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("requestAccessConfirmation", details.waitTimeDays.toString()), - this.userNamePipe.transform(details), - this.i18nService.t("requestAccess"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.userNamePipe.transform(details), + content: { + key: "requestAccessConfirmation", + placeholders: [details.waitTimeDays.toString()], + }, + acceptButtonText: { key: "requestAccess" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; @@ -226,13 +229,15 @@ export class EmergencyAccessComponent implements OnInit { details.type === EmergencyAccessType.View ? "view" : "takeover" ); - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("approveAccessConfirmation", this.userNamePipe.transform(details), type), - this.userNamePipe.transform(details), - this.i18nService.t("approve"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.userNamePipe.transform(details), + content: { + key: "approveAccessConfirmation", + placeholders: [this.userNamePipe.transform(details), type], + }, + acceptButtonText: { key: "approve" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; diff --git a/apps/web/src/auth/settings/emergency-access/emergency-add-edit.component.ts b/apps/web/src/auth/settings/emergency-access/emergency-add-edit.component.ts index 48c6472b383..a7517b8ed88 100644 --- a/apps/web/src/auth/settings/emergency-access/emergency-add-edit.component.ts +++ b/apps/web/src/auth/settings/emergency-access/emergency-add-edit.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -45,7 +46,8 @@ export class EmergencyAddEditComponent extends BaseAddEditComponent { passwordRepromptService: PasswordRepromptService, organizationService: OrganizationService, logService: LogService, - sendApiService: SendApiService + sendApiService: SendApiService, + dialogService: DialogServiceAbstraction ) { super( cipherService, @@ -63,7 +65,8 @@ export class EmergencyAddEditComponent extends BaseAddEditComponent { organizationService, logService, passwordRepromptService, - sendApiService + sendApiService, + dialogService ); } diff --git a/apps/web/src/auth/settings/two-factor-authenticator.component.ts b/apps/web/src/auth/settings/two-factor-authenticator.component.ts index 55f18409015..a75d2ebd291 100644 --- a/apps/web/src/auth/settings/two-factor-authenticator.component.ts +++ b/apps/web/src/auth/settings/two-factor-authenticator.component.ts @@ -1,5 +1,6 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -50,9 +51,17 @@ export class TwoFactorAuthenticatorComponent userVerificationService: UserVerificationService, platformUtilsService: PlatformUtilsService, logService: LogService, - private stateService: StateService + private stateService: StateService, + dialogService: DialogServiceAbstraction ) { - super(apiService, i18nService, platformUtilsService, logService, userVerificationService); + super( + apiService, + i18nService, + platformUtilsService, + logService, + userVerificationService, + dialogService + ); this.qrScript = window.document.createElement("script"); this.qrScript.src = "scripts/qrious.min.js"; this.qrScript.async = true; diff --git a/apps/web/src/auth/settings/two-factor-base.component.ts b/apps/web/src/auth/settings/two-factor-base.component.ts index 116950d2679..fb832eddc26 100644 --- a/apps/web/src/auth/settings/two-factor-base.component.ts +++ b/apps/web/src/auth/settings/two-factor-base.component.ts @@ -1,5 +1,6 @@ import { Directive, EventEmitter, Output } from "@angular/core"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -30,7 +31,8 @@ export abstract class TwoFactorBaseComponent { protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected logService: LogService, - protected userVerificationService: UserVerificationService + protected userVerificationService: UserVerificationService, + protected dialogService: DialogServiceAbstraction ) {} protected auth(authResponse: AuthResponseBase) { @@ -49,15 +51,12 @@ export abstract class TwoFactorBaseComponent { } protected async disable(promise: Promise) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("twoStepDisableDesc"), - this.i18nService.t("disable"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - this.componentName != "" ? this.componentName + " .modal-content" : null - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "disable" }, + content: { key: "twoStepDisableDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } diff --git a/apps/web/src/auth/settings/two-factor-duo.component.ts b/apps/web/src/auth/settings/two-factor-duo.component.ts index c14725da87f..23a297c494c 100644 --- a/apps/web/src/auth/settings/two-factor-duo.component.ts +++ b/apps/web/src/auth/settings/two-factor-duo.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -30,9 +31,17 @@ export class TwoFactorDuoComponent extends TwoFactorBaseComponent { i18nService: I18nService, platformUtilsService: PlatformUtilsService, logService: LogService, - userVerificationService: UserVerificationService + userVerificationService: UserVerificationService, + dialogService: DialogServiceAbstraction ) { - super(apiService, i18nService, platformUtilsService, logService, userVerificationService); + super( + apiService, + i18nService, + platformUtilsService, + logService, + userVerificationService, + dialogService + ); } auth(authResponse: AuthResponse) { diff --git a/apps/web/src/auth/settings/two-factor-email.component.ts b/apps/web/src/auth/settings/two-factor-email.component.ts index 087946ccc5d..34cbadaf50e 100644 --- a/apps/web/src/auth/settings/two-factor-email.component.ts +++ b/apps/web/src/auth/settings/two-factor-email.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -34,9 +35,17 @@ export class TwoFactorEmailComponent extends TwoFactorBaseComponent { platformUtilsService: PlatformUtilsService, logService: LogService, userVerificationService: UserVerificationService, - private stateService: StateService + private stateService: StateService, + dialogService: DialogServiceAbstraction ) { - super(apiService, i18nService, platformUtilsService, logService, userVerificationService); + super( + apiService, + i18nService, + platformUtilsService, + logService, + userVerificationService, + dialogService + ); } auth(authResponse: AuthResponse) { diff --git a/apps/web/src/auth/settings/two-factor-webauthn.component.ts b/apps/web/src/auth/settings/two-factor-webauthn.component.ts index 0110ae59f56..de1a7fde7b9 100644 --- a/apps/web/src/auth/settings/two-factor-webauthn.component.ts +++ b/apps/web/src/auth/settings/two-factor-webauthn.component.ts @@ -1,5 +1,6 @@ import { Component, NgZone } from "@angular/core"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -49,9 +50,17 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent { platformUtilsService: PlatformUtilsService, private ngZone: NgZone, logService: LogService, - userVerificationService: UserVerificationService + userVerificationService: UserVerificationService, + dialogService: DialogServiceAbstraction ) { - super(apiService, i18nService, platformUtilsService, logService, userVerificationService); + super( + apiService, + i18nService, + platformUtilsService, + logService, + userVerificationService, + dialogService + ); } auth(authResponse: AuthResponse) { @@ -85,13 +94,13 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent { return; } const name = key.name != null ? key.name : this.i18nService.t("webAuthnkeyX", key.id as any); - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removeU2fConfirmation"), - name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: name, + content: { key: "removeU2fConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } diff --git a/apps/web/src/auth/settings/two-factor-yubikey.component.ts b/apps/web/src/auth/settings/two-factor-yubikey.component.ts index 6c417400945..cc8da3962ed 100644 --- a/apps/web/src/auth/settings/two-factor-yubikey.component.ts +++ b/apps/web/src/auth/settings/two-factor-yubikey.component.ts @@ -1,5 +1,6 @@ import { Component } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -36,9 +37,17 @@ export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent { i18nService: I18nService, platformUtilsService: PlatformUtilsService, logService: LogService, - userVerificationService: UserVerificationService + userVerificationService: UserVerificationService, + dialogService: DialogServiceAbstraction ) { - super(apiService, i18nService, platformUtilsService, logService, userVerificationService); + super( + apiService, + i18nService, + platformUtilsService, + logService, + userVerificationService, + dialogService + ); } auth(authResponse: AuthResponse) { diff --git a/apps/web/src/auth/update-password.component.ts b/apps/web/src/auth/update-password.component.ts index 0e9cf28c352..403120a3e59 100644 --- a/apps/web/src/auth/update-password.component.ts +++ b/apps/web/src/auth/update-password.component.ts @@ -2,6 +2,7 @@ import { Component } from "@angular/core"; import { Router } from "@angular/router"; import { UpdatePasswordComponent as BaseUpdatePasswordComponent } from "@bitwarden/angular/auth/components/update-password.component"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -29,7 +30,8 @@ export class UpdatePasswordComponent extends BaseUpdatePasswordComponent { apiService: ApiService, logService: LogService, stateService: StateService, - userVerificationService: UserVerificationService + userVerificationService: UserVerificationService, + dialogService: DialogServiceAbstraction ) { super( router, @@ -42,7 +44,8 @@ export class UpdatePasswordComponent extends BaseUpdatePasswordComponent { apiService, stateService, userVerificationService, - logService + logService, + dialogService ); } } diff --git a/apps/web/src/scss/tailwind.css b/apps/web/src/scss/tailwind.css index c1875f53e41..4289917cfb4 100644 --- a/apps/web/src/scss/tailwind.css +++ b/apps/web/src/scss/tailwind.css @@ -28,3 +28,16 @@ summary.tw-list-none::-webkit-details-marker { .tw-text-unset { text-align: unset; } + +/** + * Bootstrap uses z-index: 1050 for modals, dialogs should appear above them. + * Remove once bootstrap is removed from our codebase. + * CL-XYZ + */ +.cdk-overlay-container, +.cdk-global-overlay-wrapper, +.cdk-overlay-connected-position-bounding-box, +.cdk-overlay-backdrop, +.cdk-overlay-pane { + z-index: 2000 !important; +} diff --git a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-add-edit-dialog/domain-add-edit-dialog.component.ts b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-add-edit-dialog/domain-add-edit-dialog.component.ts index d9598c93d80..94990daea05 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-add-edit-dialog/domain-add-edit-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-add-edit-dialog/domain-add-edit-dialog.component.ts @@ -3,6 +3,7 @@ import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from "@angular/forms"; import { Subject, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/abstractions/organization-domain/org-domain-api.service.abstraction"; @@ -64,7 +65,8 @@ export class DomainAddEditDialogComponent implements OnInit, OnDestroy { private i18nService: I18nService, private orgDomainApiService: OrgDomainApiServiceAbstraction, private orgDomainService: OrgDomainServiceAbstraction, - private validationService: ValidationService + private validationService: ValidationService, + private dialogService: DialogServiceAbstraction ) {} //#region Angular Method Implementations @@ -248,13 +250,12 @@ export class DomainAddEditDialogComponent implements OnInit, OnDestroy { } deleteDomain = async (): Promise => { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removeDomainWarning"), - this.i18nService.t("removeDomain"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "removeDomain" }, + content: { key: "removeDomainWarning" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } diff --git a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-verification.component.ts b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-verification.component.ts index e6495af942c..f650db766f9 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-verification.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/domain-verification/domain-verification.component.ts @@ -2,6 +2,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute, Params } from "@angular/router"; import { concatMap, Observable, Subject, take, takeUntil } from "rxjs"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/abstractions/organization-domain/org-domain-api.service.abstraction"; import { OrgDomainServiceAbstraction } from "@bitwarden/common/abstractions/organization-domain/org-domain.service.abstraction"; @@ -10,7 +11,6 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti import { ValidationService } from "@bitwarden/common/abstractions/validation.service"; import { HttpStatusCode } from "@bitwarden/common/enums"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; -import { DialogService } from "@bitwarden/components"; import { DomainAddEditDialogComponent, @@ -35,7 +35,7 @@ export class DomainVerificationComponent implements OnInit, OnDestroy { private i18nService: I18nService, private orgDomainApiService: OrgDomainApiServiceAbstraction, private orgDomainService: OrgDomainServiceAbstraction, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private validationService: ValidationService ) {} @@ -154,13 +154,12 @@ export class DomainVerificationComponent implements OnInit, OnDestroy { } async deleteDomain(orgDomainId: string): Promise { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removeDomainWarning"), - this.i18nService.t("removeDomain"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "removeDomain" }, + content: { key: "removeDomainWarning" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } diff --git a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/scim.component.ts b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/scim.component.ts index 074e6988d59..1e1e9eb58c1 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/scim.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/organizations/manage/scim.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { UntypedFormBuilder, FormControl } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -45,7 +46,8 @@ export class ScimComponent implements OnInit { private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, private environmentService: EnvironmentService, - private organizationApiService: OrganizationApiServiceAbstraction + private organizationApiService: OrganizationApiServiceAbstraction, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -84,13 +86,13 @@ export class ScimComponent implements OnInit { } async rotateScimKey() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("rotateScimKeyWarning"), - this.i18nService.t("rotateScimKey"), - this.i18nService.t("rotateKey"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "rotateScimKey" }, + content: { key: "rotateScimKeyWarning" }, + acceptButtonText: { key: "rotateKey" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/clients/add-organization.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/clients/add-organization.component.ts index 74d44b8b10f..36207decbd9 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/clients/add-organization.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/clients/add-organization.component.ts @@ -1,5 +1,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { ValidationService } from "@bitwarden/common/abstractions/validation.service"; @@ -27,7 +28,8 @@ export class AddOrganizationComponent implements OnInit { private webProviderService: WebProviderService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private validationService: ValidationService + private validationService: ValidationService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -49,13 +51,14 @@ export class AddOrganizationComponent implements OnInit { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("addOrganizationConfirmation", organization.name, this.provider.name), - organization.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: organization.name, + content: { + key: "addOrganizationConfirmation", + placeholders: [organization.name, this.provider.name], + }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/clients/clients.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/clients/clients.component.ts index dcbde5bdc18..69e5dcf063f 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/clients/clients.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/clients/clients.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { first } from "rxjs/operators"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -61,7 +62,8 @@ export class ClientsComponent implements OnInit { private logService: LogService, private modalService: ModalService, private organizationService: OrganizationService, - private organizationApiService: OrganizationApiServiceAbstraction + private organizationApiService: OrganizationApiServiceAbstraction, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -153,13 +155,11 @@ export class ClientsComponent implements OnInit { } async remove(organization: ProviderOrganizationOrganizationDetailsResponse) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("detachOrganizationConfirmation"), - organization.organizationName, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: organization.organizationName, + content: { key: "detachOrganizationConfirmation" }, + type: SimpleDialogType.WARNING, + }); if (!confirmed) { return false; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts index 034fe06a109..69f965901bc 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts @@ -4,6 +4,7 @@ import { first } from "rxjs/operators"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; @@ -68,7 +69,8 @@ export class PeopleComponent searchPipe: SearchPipe, userNamePipe: UserNamePipe, stateService: StateService, - private providerService: ProviderService + private providerService: ProviderService, + dialogService: DialogServiceAbstraction ) { super( apiService, @@ -81,7 +83,8 @@ export class PeopleComponent logService, searchPipe, userNamePipe, - stateService + stateService, + dialogService ); } diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/user-add-edit.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/user-add-edit.component.ts index 8c94d7a445a..7a83cab7493 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/user-add-edit.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/user-add-edit.component.ts @@ -1,5 +1,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; @@ -36,7 +37,8 @@ export class UserAddEditComponent implements OnInit { private apiService: ApiService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private logService: LogService + private logService: LogService, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -91,13 +93,12 @@ export class UserAddEditComponent implements OnInit { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removeUserConfirmation"), - this.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.name, + content: { key: "removeUserConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts index 64ee4a0b737..8b345402565 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts @@ -13,11 +13,11 @@ import { share, } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { StateService } from "@bitwarden/common/abstractions/state.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; -import { DialogService } from "@bitwarden/components"; import { ProjectListView } from "../models/view/project-list.view"; import { SecretListView } from "../models/view/secret-list.view"; @@ -84,7 +84,7 @@ export class OverviewComponent implements OnInit, OnDestroy { private projectService: ProjectService, private secretService: SecretService, private serviceAccountService: ServiceAccountService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private organizationService: OrganizationService, private stateService: StateService, private platformUtilsService: PlatformUtilsService, diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/dialog/project-delete-dialog.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/dialog/project-delete-dialog.component.ts index 22bbe389919..5a6d9084e15 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/dialog/project-delete-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/dialog/project-delete-dialog.component.ts @@ -8,9 +8,9 @@ import { AbstractControl, } from "@angular/forms"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { DialogService } from "@bitwarden/components"; import { ProjectListView } from "../../models/view/project-list.view"; import { @@ -38,7 +38,7 @@ export class ProjectDeleteDialogComponent implements OnInit { private projectService: ProjectService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} ngOnInit(): void { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-people.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-people.component.ts index 5dda1a5a54c..d5129815bf3 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-people.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-people.component.ts @@ -2,8 +2,9 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { map, Observable, share, startWith, Subject, switchMap, takeUntil } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ValidationService } from "@bitwarden/common/abstractions/validation.service"; -import { DialogService, SelectItemView } from "@bitwarden/components"; +import { SelectItemView } from "@bitwarden/components"; import { GroupProjectAccessPolicyView, @@ -143,7 +144,7 @@ export class ProjectPeopleComponent implements OnInit, OnDestroy { constructor( private route: ActivatedRoute, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private validationService: ValidationService, private accessPolicyService: AccessPolicyService ) {} diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts index 2cac1cc451d..905b68cf037 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts @@ -2,9 +2,9 @@ import { Component } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { combineLatest, combineLatestWith, filter, Observable, startWith, switchMap } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { DialogService } from "@bitwarden/components"; import { ProjectView } from "../../models/view/project.view"; import { SecretListView } from "../../models/view/secret-list.view"; @@ -36,7 +36,7 @@ export class ProjectSecretsComponent { private route: ActivatedRoute, private projectService: ProjectService, private secretService: SecretService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private platformUtilsService: PlatformUtilsService, private i18nService: I18nService ) {} diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts index 035332889c7..7c4e7357af0 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts @@ -11,7 +11,7 @@ import { takeUntil, } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ProjectView } from "../../models/view/project.view"; import { @@ -36,8 +36,8 @@ export class ProjectComponent implements OnInit, OnDestroy { constructor( private route: ActivatedRoute, private projectService: ProjectService, - private dialogService: DialogService, - private router: Router + private router: Router, + private dialogService: DialogServiceAbstraction ) {} ngOnInit(): void { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts index 7128e26a3d8..fe202b31229 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { combineLatest, lastValueFrom, Observable, startWith, switchMap } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ProjectListView } from "../../models/view/project-list.view"; import { AccessPolicyService } from "../../shared/access-policies/access-policy.service"; @@ -37,7 +37,7 @@ export class ProjectsComponent implements OnInit { private route: ActivatedRoute, private projectService: ProjectService, private accessPolicyService: AccessPolicyService, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} ngOnInit() { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-delete.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-delete.component.ts index decf9f2edb3..de06e6c926a 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-delete.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-delete.component.ts @@ -1,9 +1,9 @@ import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { DialogService } from "@bitwarden/components"; import { SecretListView } from "../../models/view/secret-list.view"; import { @@ -27,7 +27,7 @@ export class SecretDeleteDialogComponent { private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, @Inject(DIALOG_DATA) private data: SecretDeleteOperation, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} showSoftDeleteSecretWarning = this.data.secrets.length === 1; diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts index aa53d30aff8..0e374719708 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts @@ -3,11 +3,11 @@ import { Component, Inject, OnInit } from "@angular/core"; import { FormControl, FormGroup, Validators } from "@angular/forms"; import { lastValueFrom, Subject, takeUntil } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Utils } from "@bitwarden/common/misc/utils"; -import { DialogService } from "@bitwarden/components"; import { ProjectListView } from "../../models/view/project-list.view"; import { ProjectView } from "../../models/view/project.view"; @@ -56,7 +56,7 @@ export class SecretDialogComponent implements OnInit { private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, private projectService: ProjectService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private organizationService: OrganizationService ) {} diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts index 5db22ad87b1..940823ea62c 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts @@ -2,9 +2,9 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { combineLatestWith, Observable, startWith, switchMap } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { DialogService } from "@bitwarden/components"; import { SecretListView } from "../models/view/secret-list.view"; import { SecretsListComponent } from "../shared/secrets-list.component"; @@ -33,7 +33,7 @@ export class SecretsComponent implements OnInit { constructor( private route: ActivatedRoute, private secretService: SecretService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private platformUtilsService: PlatformUtilsService, private i18nService: I18nService ) {} diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts index ee6cae35cec..b9a8a88b539 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/access-tokens.component.ts @@ -2,9 +2,9 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { combineLatestWith, Observable, startWith, switchMap } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { DialogService } from "@bitwarden/components"; import { UserVerificationPromptComponent } from "@bitwarden/web-vault/app/components/user-verification-prompt.component"; import { AccessTokenView } from "../models/view/access-token.view"; @@ -25,7 +25,7 @@ export class AccessTokenComponent implements OnInit { constructor( private route: ActivatedRoute, private accessService: AccessService, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private modalService: ModalService, private platformUtilsService: PlatformUtilsService ) {} diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/dialogs/access-token-create-dialog.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/dialogs/access-token-create-dialog.component.ts index db7b822d42a..5a5e29f06bc 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/dialogs/access-token-create-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/access/dialogs/access-token-create-dialog.component.ts @@ -2,7 +2,7 @@ import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject, OnInit } from "@angular/core"; import { FormControl, FormGroup, Validators } from "@angular/forms"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ServiceAccountView } from "../../../models/view/service-account.view"; import { AccessTokenView } from "../../models/view/access-token.view"; @@ -30,7 +30,7 @@ export class AccessTokenCreateDialogComponent implements OnInit { constructor( public dialogRef: DialogRef, @Inject(DIALOG_DATA) public data: AccessTokenOperation, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private accessService: AccessService ) {} @@ -83,7 +83,7 @@ export class AccessTokenCreateDialogComponent implements OnInit { } static openNewAccessTokenDialog( - dialogService: DialogService, + dialogService: DialogServiceAbstraction, serviceAccountId: string, organizationId: string ) { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/dialog/service-account-delete-dialog.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/dialog/service-account-delete-dialog.component.ts index c9f52295f67..da75b61c7aa 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/dialog/service-account-delete-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/dialog/service-account-delete-dialog.component.ts @@ -8,9 +8,9 @@ import { AbstractControl, } from "@angular/forms"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; -import { DialogService } from "@bitwarden/components"; import { ServiceAccountView } from "../../models/view/service-account.view"; import { @@ -38,7 +38,7 @@ export class ServiceAccountDeleteDialogComponent { private serviceAccountService: ServiceAccountService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} get title() { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts index e539e0bf083..e346d25871e 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts @@ -11,9 +11,13 @@ import { takeUntil, } from "rxjs"; +import { + SimpleDialogType, + DialogServiceAbstraction, + SimpleDialogOptions, +} from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { ValidationService } from "@bitwarden/common/abstractions/validation.service"; -import { DialogService, SimpleDialogOptions, SimpleDialogType } from "@bitwarden/components"; import { SelectItemView } from "@bitwarden/components/src/multi-select/models/select-item-view"; import { @@ -131,10 +135,10 @@ export class ServiceAccountPeopleComponent { title: this.i18nService.t("saPeopleWarningTitle"), content: this.i18nService.t("saPeopleWarningMessage"), type: SimpleDialogType.WARNING, - acceptButtonText: this.i18nService.t("close"), + acceptButtonText: { key: "close" }, cancelButtonText: null, }; - this.dialogService.openSimpleDialog(simpleDialogOpts); + this.dialogService.openSimpleDialogRef(simpleDialogOpts); } catch (e) { this.validationService.showError(e); } @@ -142,7 +146,7 @@ export class ServiceAccountPeopleComponent { constructor( private route: ActivatedRoute, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private i18nService: I18nService, private validationService: ValidationService, private accessPolicyService: AccessPolicyService diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.ts index 7be88fc9a83..6d5dee2a9fa 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.ts @@ -2,7 +2,7 @@ import { Component } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { switchMap } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { AccessTokenCreateDialogComponent } from "./access/dialogs/access-token-create-dialog.component"; import { ServiceAccountService } from "./service-account.service"; @@ -32,7 +32,7 @@ export class ServiceAccountComponent { constructor( private route: ActivatedRoute, private serviceAccountService: ServiceAccountService, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} protected openNewAccessTokenDialog() { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts index 4d3f65c862a..9800a14fe5a 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { combineLatest, Observable, startWith, switchMap } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ServiceAccountView } from "../models/view/service-account.view"; import { AccessPolicyService } from "../shared/access-policies/access-policy.service"; @@ -30,7 +30,7 @@ export class ServiceAccountsComponent implements OnInit { constructor( private route: ActivatedRoute, - private dialogService: DialogService, + private dialogService: DialogServiceAbstraction, private accessPolicyService: AccessPolicyService, private serviceAccountService: ServiceAccountService ) {} diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-import.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-import.component.ts index 72899223f3f..0a9279b3301 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-import.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/settings/porting/sm-import.component.ts @@ -3,12 +3,12 @@ import { FormControl, FormGroup } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; import { Subject, takeUntil } from "rxjs"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; -import { DialogService } from "@bitwarden/components"; import { SecretsManagerImportErrorDialogComponent, @@ -37,7 +37,7 @@ export class SecretsManagerImportComponent implements OnInit, OnDestroy { protected fileDownloadService: FileDownloadService, private logService: LogService, private secretsManagerPortingApiService: SecretsManagerPortingApiService, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts index 7ecc2f917a4..ac0345c40e1 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { Subject, takeUntil } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { ProjectDialogComponent, @@ -26,7 +26,7 @@ export class NewMenuComponent implements OnInit, OnDestroy { private organizationId: string; private destroy$: Subject = new Subject(); - constructor(private route: ActivatedRoute, private dialogService: DialogService) {} + constructor(private route: ActivatedRoute, private dialogService: DialogServiceAbstraction) {} ngOnInit() { this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params: any) => { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/trash/trash.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/trash/trash.component.ts index 83f510ed569..8835049f82d 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/trash/trash.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/trash/trash.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { combineLatestWith, Observable, startWith, switchMap } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; import { SecretListView } from "../models/view/secret-list.view"; import { SecretService } from "../secrets/secret.service"; @@ -28,7 +28,7 @@ export class TrashComponent implements OnInit { constructor( private route: ActivatedRoute, private secretService: SecretService, - private dialogService: DialogService + private dialogService: DialogServiceAbstraction ) {} ngOnInit() { diff --git a/libs/angular/src/auth/components/change-password.component.ts b/libs/angular/src/auth/components/change-password.component.ts index ce40ba70540..18e98242b21 100644 --- a/libs/angular/src/auth/components/change-password.component.ts +++ b/libs/angular/src/auth/components/change-password.component.ts @@ -15,6 +15,7 @@ import { EncString } from "@bitwarden/common/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; import { PasswordColorText } from "../../shared/components/password-strength/password-strength.component"; @Directive() @@ -42,7 +43,8 @@ export class ChangePasswordComponent implements OnInit, OnDestroy { protected passwordGenerationService: PasswordGenerationServiceAbstraction, protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService, - protected stateService: StateService + protected stateService: StateService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -157,37 +159,34 @@ export class ChangePasswordComponent implements OnInit, OnDestroy { const weakPassword = strengthResult != null && strengthResult.score < 3; if (weakPassword && this.leakedPassword) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakAndBreachedMasterPasswordDesc"), - this.i18nService.t("weakAndExposedMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "weakAndExposedMasterPassword" }, + content: { key: "weakAndBreachedMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return false; } } else { if (weakPassword) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakMasterPasswordDesc"), - this.i18nService.t("weakMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "weakMasterPassword" }, + content: { key: "weakMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return false; } } if (this.leakedPassword) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("exposedMasterPasswordDesc"), - this.i18nService.t("exposedMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "exposedMasterPassword" }, + content: { key: "exposedMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return false; } @@ -198,12 +197,13 @@ export class ChangePasswordComponent implements OnInit, OnDestroy { } async logOut() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("logOutConfirmation"), - this.i18nService.t("logOut"), - this.i18nService.t("logOut"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "logOut" }, + content: { key: "logOutConfirmation" }, + acceptButtonText: { key: "logOut" }, + type: SimpleDialogType.WARNING, + }); + if (confirmed) { this.messagingService.send("logout"); } diff --git a/libs/angular/src/auth/components/lock.component.ts b/libs/angular/src/auth/components/lock.component.ts index f81bfecc86e..77957ff4fea 100644 --- a/libs/angular/src/auth/components/lock.component.ts +++ b/libs/angular/src/auth/components/lock.component.ts @@ -26,6 +26,8 @@ import { EncString } from "@bitwarden/common/models/domain/enc-string"; import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class LockComponent implements OnInit, OnDestroy { masterPassword = ""; @@ -67,7 +69,8 @@ export class LockComponent implements OnInit, OnDestroy { protected ngZone: NgZone, protected policyApiService: PolicyApiServiceAbstraction, protected policyService: InternalPolicyService, - protected passwordGenerationService: PasswordGenerationServiceAbstraction + protected passwordGenerationService: PasswordGenerationServiceAbstraction, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -95,12 +98,13 @@ export class LockComponent implements OnInit, OnDestroy { } async logOut() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("logOutConfirmation"), - this.i18nService.t("logOut"), - this.i18nService.t("logOut"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "logOut" }, + content: { key: "logOutConfirmation" }, + acceptButtonText: { key: "logOut" }, + type: SimpleDialogType.WARNING, + }); + if (confirmed) { this.messagingService.send("logout"); } diff --git a/libs/angular/src/auth/components/remove-password.component.ts b/libs/angular/src/auth/components/remove-password.component.ts index d904d2e0cad..c53196feaff 100644 --- a/libs/angular/src/auth/components/remove-password.component.ts +++ b/libs/angular/src/auth/components/remove-password.component.ts @@ -9,6 +9,8 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class RemovePasswordComponent implements OnInit { actionPromise: Promise; @@ -26,7 +28,8 @@ export class RemovePasswordComponent implements OnInit { private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, private keyConnectorService: KeyConnectorService, - private organizationApiService: OrganizationApiServiceAbstraction + private organizationApiService: OrganizationApiServiceAbstraction, + private dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -55,13 +58,12 @@ export class RemovePasswordComponent implements OnInit { } async leave() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("leaveOrganizationConfirmation"), - this.organization.name, - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: this.organization.name, + content: { key: "leaveOrganizationConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/libs/angular/src/auth/components/update-password.component.ts b/libs/angular/src/auth/components/update-password.component.ts index 97de355b1ca..f0389951787 100644 --- a/libs/angular/src/auth/components/update-password.component.ts +++ b/libs/angular/src/auth/components/update-password.component.ts @@ -18,6 +18,8 @@ import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-cr import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; import { Verification } from "@bitwarden/common/types/verification"; +import { DialogServiceAbstraction } from "../../services/dialog"; + import { ChangePasswordComponent as BaseChangePasswordComponent } from "./change-password.component"; @Directive() @@ -41,7 +43,8 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent { private apiService: ApiService, stateService: StateService, private userVerificationService: UserVerificationService, - private logService: LogService + private logService: LogService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -50,7 +53,8 @@ export class UpdatePasswordComponent extends BaseChangePasswordComponent { passwordGenerationService, platformUtilsService, policyService, - stateService + stateService, + dialogService ); } diff --git a/libs/angular/src/auth/components/update-temp-password.component.ts b/libs/angular/src/auth/components/update-temp-password.component.ts index c2a54ad79a2..9899b2db273 100644 --- a/libs/angular/src/auth/components/update-temp-password.component.ts +++ b/libs/angular/src/auth/components/update-temp-password.component.ts @@ -21,6 +21,8 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/ge import { Verification } from "@bitwarden/common/types/verification"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; +import { DialogServiceAbstraction } from "../../services/dialog"; + import { ChangePasswordComponent as BaseChangePasswordComponent } from "./change-password.component"; @Directive() @@ -53,7 +55,8 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent { private syncService: SyncService, private logService: LogService, private userVerificationService: UserVerificationService, - private router: Router + private router: Router, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -62,7 +65,8 @@ export class UpdateTempPasswordComponent extends BaseChangePasswordComponent { passwordGenerationService, platformUtilsService, policyService, - stateService + stateService, + dialogService ); } diff --git a/libs/angular/src/components/register.component.ts b/libs/angular/src/components/register.component.ts index 2eb6d500cea..cb5ba243d99 100644 --- a/libs/angular/src/components/register.component.ts +++ b/libs/angular/src/components/register.component.ts @@ -25,6 +25,7 @@ import { RegisterRequest } from "@bitwarden/common/models/request/register.reque import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; import { CaptchaProtectedComponent } from "../auth/components/captcha-protected.component"; +import { DialogServiceAbstraction, SimpleDialogType } from "../services/dialog"; import { PasswordColorText } from "../shared/components/password-strength/password-strength.component"; import { InputsFieldMatch } from "../validators/inputsFieldMatch.validator"; @@ -90,7 +91,8 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn protected passwordGenerationService: PasswordGenerationServiceAbstraction, environmentService: EnvironmentService, protected logService: LogService, - protected auditService: AuditService + protected auditService: AuditService, + protected dialogService: DialogServiceAbstraction ) { super(environmentService, i18nService, platformUtilsService); this.showTerms = !platformUtilsService.isSelfHost(); @@ -227,35 +229,32 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn (await this.auditService.passwordLeaked(this.formGroup.controls.masterPassword.value)) > 0; if (passwordWeak && passwordLeak) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakAndBreachedMasterPasswordDesc"), - this.i18nService.t("weakAndExposedMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "weakAndExposedMasterPassword" }, + content: { key: "weakAndBreachedMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return { isValid: false }; } } else if (passwordWeak) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakMasterPasswordDesc"), - this.i18nService.t("weakMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "weakMasterPassword" }, + content: { key: "weakMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return { isValid: false }; } } else if (passwordLeak) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("exposedMasterPasswordDesc"), - this.i18nService.t("exposedMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const result = await this.dialogService.openSimpleDialog({ + title: { key: "exposedMasterPassword" }, + content: { key: "exposedMasterPasswordDesc" }, + type: SimpleDialogType.WARNING, + }); + if (!result) { return { isValid: false }; } diff --git a/libs/angular/src/components/set-password.component.ts b/libs/angular/src/components/set-password.component.ts index fad1fba1be4..1a2b4a91522 100644 --- a/libs/angular/src/components/set-password.component.ts +++ b/libs/angular/src/components/set-password.component.ts @@ -23,6 +23,7 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/ge import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { ChangePasswordComponent as BaseChangePasswordComponent } from "../auth/components/change-password.component"; +import { DialogServiceAbstraction } from "../services/dialog"; @Directive() export class SetPasswordComponent extends BaseChangePasswordComponent { @@ -50,7 +51,8 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { private route: ActivatedRoute, stateService: StateService, private organizationApiService: OrganizationApiServiceAbstraction, - private organizationUserService: OrganizationUserService + private organizationUserService: OrganizationUserService, + dialogService: DialogServiceAbstraction ) { super( i18nService, @@ -59,7 +61,8 @@ export class SetPasswordComponent extends BaseChangePasswordComponent { passwordGenerationService, platformUtilsService, policyService, - stateService + stateService, + dialogService ); } diff --git a/libs/angular/src/services/dialog/dialog.service.abstraction.ts b/libs/angular/src/services/dialog/dialog.service.abstraction.ts new file mode 100644 index 00000000000..f940dd1fa50 --- /dev/null +++ b/libs/angular/src/services/dialog/dialog.service.abstraction.ts @@ -0,0 +1,26 @@ +import { Dialog, DialogRef } from "@angular/cdk/dialog"; + +import { SimpleDialogOptions } from "./simple-dialog-options"; + +export abstract class DialogServiceAbstraction extends Dialog { + /** + * Opens a simple dialog, returns true if the user accepted the dialog. + * + * @param {SimpleDialogOptions} simpleDialogOptions - An object containing options for the dialog. + * @returns `boolean` - True if the user accepted the dialog, false otherwise. + */ + openSimpleDialog: (simpleDialogOptions: SimpleDialogOptions) => Promise; + + /** + * Opens a simple dialog. + * + * @deprecated Use `openSimpleDialogAcceptedPromise` instead. If you find a use case for the `dialogRef` + * please let #wg-component-library know and we can un-deprecate this method. + * + * @param {SimpleDialogOptions} simpleDialogOptions - An object containing options for the dialog. + * @returns `DialogRef` - The reference to the opened dialog. + * Contains a closed observable which can be subscribed to for determining which button + * a user pressed (see `SimpleDialogCloseType`) + */ + openSimpleDialogRef: (simpleDialogOptions: SimpleDialogOptions) => DialogRef; +} diff --git a/libs/angular/src/services/dialog/dialog.service.ts b/libs/angular/src/services/dialog/dialog.service.ts new file mode 100644 index 00000000000..aaddf651e31 --- /dev/null +++ b/libs/angular/src/services/dialog/dialog.service.ts @@ -0,0 +1,65 @@ +import { + DialogRef, + DialogConfig, + Dialog, + DEFAULT_DIALOG_CONFIG, + DIALOG_SCROLL_STRATEGY, +} from "@angular/cdk/dialog"; +import { Overlay, OverlayContainer } from "@angular/cdk/overlay"; +import { ComponentType } from "@angular/cdk/portal"; +import { Inject, Injectable, Injector, Optional, SkipSelf, TemplateRef } from "@angular/core"; + +import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; + +import { DialogServiceAbstraction } from "./dialog.service.abstraction"; +import { SimpleDialogOptions } from "./simple-dialog-options"; +import { Translation } from "./translation"; + +// This is a temporary base class for Dialogs. It is intended to be removed once the Component Library is adopted by each app. +@Injectable() +export abstract class DialogService extends Dialog implements DialogServiceAbstraction { + constructor( + /** Parent class constructor */ + _overlay: Overlay, + _injector: Injector, + @Optional() @Inject(DEFAULT_DIALOG_CONFIG) _defaultOptions: DialogConfig, + @Optional() @SkipSelf() _parentDialog: Dialog, + _overlayContainer: OverlayContainer, + @Inject(DIALOG_SCROLL_STRATEGY) scrollStrategy: any, + protected i18nService: I18nService + ) { + super(_overlay, _injector, _defaultOptions, _parentDialog, _overlayContainer, scrollStrategy); + } + + async openSimpleDialog(options: SimpleDialogOptions): Promise { + throw new Error("Method not implemented."); + } + + openSimpleDialogRef(simpleDialogOptions: SimpleDialogOptions): DialogRef { + throw new Error("Method not implemented."); + } + + override open( + componentOrTemplateRef: ComponentType | TemplateRef, + config?: DialogConfig> + ): DialogRef { + throw new Error("Method not implemented."); + } + + protected translate(translation: string | Translation, defaultKey?: string): string { + if (translation == null && defaultKey == null) { + return null; + } + + if (translation == null) { + return this.i18nService.t(defaultKey); + } + + // Translation interface use implies we must localize. + if (typeof translation === "object") { + return this.i18nService.t(translation.key, ...(translation.placeholders ?? [])); + } + + return translation; + } +} diff --git a/libs/angular/src/services/dialog/index.ts b/libs/angular/src/services/dialog/index.ts new file mode 100644 index 00000000000..b664d179e08 --- /dev/null +++ b/libs/angular/src/services/dialog/index.ts @@ -0,0 +1,6 @@ +export * from "./dialog.service.abstraction"; +export * from "./simple-dialog-options"; +export * from "./simple-dialog-type.enum"; +export * from "./simple-dialog-close-type.enum"; +export * from "./dialog.service"; +export * from "./translation"; diff --git a/libs/components/src/dialog/simple-configurable-dialog/models/simple-dialog-close-type.enum.ts b/libs/angular/src/services/dialog/simple-dialog-close-type.enum.ts similarity index 100% rename from libs/components/src/dialog/simple-configurable-dialog/models/simple-dialog-close-type.enum.ts rename to libs/angular/src/services/dialog/simple-dialog-close-type.enum.ts diff --git a/libs/components/src/dialog/simple-configurable-dialog/models/simple-dialog-options.ts b/libs/angular/src/services/dialog/simple-dialog-options.ts similarity index 100% rename from libs/components/src/dialog/simple-configurable-dialog/models/simple-dialog-options.ts rename to libs/angular/src/services/dialog/simple-dialog-options.ts diff --git a/libs/components/src/dialog/simple-configurable-dialog/models/simple-dialog-type.enum.ts b/libs/angular/src/services/dialog/simple-dialog-type.enum.ts similarity index 100% rename from libs/components/src/dialog/simple-configurable-dialog/models/simple-dialog-type.enum.ts rename to libs/angular/src/services/dialog/simple-dialog-type.enum.ts diff --git a/libs/components/src/dialog/simple-configurable-dialog/models/translation.ts b/libs/angular/src/services/dialog/translation.ts similarity index 100% rename from libs/components/src/dialog/simple-configurable-dialog/models/translation.ts rename to libs/angular/src/services/dialog/translation.ts diff --git a/libs/angular/src/tools/export/components/export.component.ts b/libs/angular/src/tools/export/components/export.component.ts index c3c31c27f4e..a1a8b583b28 100644 --- a/libs/angular/src/tools/export/components/export.component.ts +++ b/libs/angular/src/tools/export/components/export.component.ts @@ -14,6 +14,8 @@ import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { EncryptedExportType, EventType } from "@bitwarden/common/enums"; import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../../services/dialog"; + @Directive() export class ExportComponent implements OnInit, OnDestroy { @Output() onSaved = new EventEmitter(); @@ -48,7 +50,8 @@ export class ExportComponent implements OnInit, OnDestroy { private logService: LogService, private userVerificationService: UserVerificationService, private formBuilder: UntypedFormBuilder, - protected fileDownloadService: FileDownloadService + protected fileDownloadService: FileDownloadService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -126,25 +129,22 @@ export class ExportComponent implements OnInit, OnDestroy { async warningDialog() { if (this.encryptedFormat) { - return await this.platformUtilsService.showDialog( - "

" + + return await this.dialogService.openSimpleDialog({ + title: { key: "confirmVaultExport" }, + content: this.i18nService.t("encExportKeyWarningDesc") + - "

" + + " " + this.i18nService.t("encExportAccountWarningDesc"), - this.i18nService.t("confirmVaultExport"), - this.i18nService.t("exportVault"), - this.i18nService.t("cancel"), - "warning", - true - ); + acceptButtonText: { key: "exportVault" }, + type: SimpleDialogType.WARNING, + }); } else { - return await this.platformUtilsService.showDialog( - this.i18nService.t("exportWarningDesc"), - this.i18nService.t("confirmVaultExport"), - this.i18nService.t("exportVault"), - this.i18nService.t("cancel"), - "warning" - ); + return await this.dialogService.openSimpleDialog({ + title: { key: "confirmVaultExport" }, + content: { key: "exportWarningDesc" }, + acceptButtonText: { key: "exportVault" }, + type: SimpleDialogType.WARNING, + }); } } diff --git a/libs/angular/src/tools/send/add-edit.component.ts b/libs/angular/src/tools/send/add-edit.component.ts index eb04c06dd7f..747df5780cb 100644 --- a/libs/angular/src/tools/send/add-edit.component.ts +++ b/libs/angular/src/tools/send/add-edit.component.ts @@ -19,6 +19,8 @@ import { SendView } from "@bitwarden/common/tools/send/models/view/send.view"; import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction"; import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class AddEditComponent implements OnInit, OnDestroy { @Input() sendId: string; @@ -60,7 +62,8 @@ export class AddEditComponent implements OnInit, OnDestroy { protected policyService: PolicyService, private logService: LogService, protected stateService: StateService, - protected sendApiService: SendApiService + protected sendApiService: SendApiService, + protected dialogService: DialogServiceAbstraction ) { this.typeOptions = [ { name: i18nService.t("sendTypeFile"), value: SendType.File }, @@ -229,15 +232,13 @@ export class AddEditComponent implements OnInit, OnDestroy { if (this.deletePromise != null) { return false; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteSendConfirmation"), - this.i18nService.t("deleteSend"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - this.componentName != "" ? this.componentName + " .modal-content" : null - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "deleteSend" }, + content: { key: "deleteSendConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -308,14 +309,14 @@ export class AddEditComponent implements OnInit, OnDestroy { this.i18nService.t(this.editMode ? "editedSend" : "createdSend") ); } else { - await this.platformUtilsService.showDialog( - this.i18nService.t(this.editMode ? "editedSend" : "createdSend"), - null, - this.i18nService.t("ok"), - null, - "success", - null - ); + await this.dialogService.openSimpleDialog({ + title: "", + content: { key: this.editMode ? "editedSend" : "createdSend" }, + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + type: SimpleDialogType.SUCCESS, + }); + await this.copyLinkToClipboard(this.link); } } diff --git a/libs/angular/src/tools/send/send.component.ts b/libs/angular/src/tools/send/send.component.ts index 3c197e73f71..bec82d7c69a 100644 --- a/libs/angular/src/tools/send/send.component.ts +++ b/libs/angular/src/tools/send/send.component.ts @@ -13,6 +13,8 @@ import { SendView } from "@bitwarden/common/tools/send/models/view/send.view"; import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction"; import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class SendComponent implements OnInit, OnDestroy { disableSend = false; @@ -49,7 +51,8 @@ export class SendComponent implements OnInit, OnDestroy { protected searchService: SearchService, protected policyService: PolicyService, private logService: LogService, - protected sendApiService: SendApiService + protected sendApiService: SendApiService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -125,13 +128,13 @@ export class SendComponent implements OnInit, OnDestroy { if (this.actionPromise != null || s.password == null) { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("removePasswordConfirmation"), - this.i18nService.t("removePassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "removePassword" }, + content: { key: "removePasswordConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -156,13 +159,13 @@ export class SendComponent implements OnInit, OnDestroy { if (this.actionPromise != null) { return false; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteSendConfirmation"), - this.i18nService.t("deleteSend"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "deleteSend" }, + content: { key: "deleteSendConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/libs/angular/src/vault/components/add-edit.component.ts b/libs/angular/src/vault/components/add-edit.component.ts index 54dccfd2e92..2d53d6a7d98 100644 --- a/libs/angular/src/vault/components/add-edit.component.ts +++ b/libs/angular/src/vault/components/add-edit.component.ts @@ -34,6 +34,8 @@ import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view import { LoginView } from "@bitwarden/common/vault/models/view/login.view"; import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note.view"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class AddEditComponent implements OnInit, OnDestroy { @Input() cloneMode = false; @@ -98,7 +100,8 @@ export class AddEditComponent implements OnInit, OnDestroy { private logService: LogService, protected passwordRepromptService: PasswordRepromptService, private organizationService: OrganizationService, - protected sendApiService: SendApiService + protected sendApiService: SendApiService, + protected dialogService: DialogServiceAbstraction ) { this.typeOptions = [ { name: i18nService.t("typeLogin"), value: CipherType.Login }, @@ -390,17 +393,14 @@ export class AddEditComponent implements OnInit, OnDestroy { } async delete(): Promise { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t( - this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" - ), - this.i18nService.t("deleteItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - this.componentName != "" ? this.componentName + " .modal-content" : null - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "deleteItem" }, + content: { + key: this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation", + }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -429,13 +429,12 @@ export class AddEditComponent implements OnInit, OnDestroy { return false; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("restoreItemConfirmation"), - this.i18nService.t("restoreItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "restoreItem" }, + content: { key: "restoreItemConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -455,12 +454,12 @@ export class AddEditComponent implements OnInit, OnDestroy { async generateUsername(): Promise { if (this.cipher.login?.username?.length) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("overwriteUsernameConfirmation"), - this.i18nService.t("overwriteUsername"), - this.i18nService.t("yes"), - this.i18nService.t("no") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "overwriteUsername" }, + content: { key: "overwriteUsernameConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -472,12 +471,12 @@ export class AddEditComponent implements OnInit, OnDestroy { async generatePassword(): Promise { if (this.cipher.login?.password?.length) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("overwritePasswordConfirmation"), - this.i18nService.t("overwritePassword"), - this.i18nService.t("yes"), - this.i18nService.t("no") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "overwritePassword" }, + content: { key: "overwritePasswordConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/libs/angular/src/vault/components/attachments.component.ts b/libs/angular/src/vault/components/attachments.component.ts index 0cbcf6cddf4..d137375b188 100644 --- a/libs/angular/src/vault/components/attachments.component.ts +++ b/libs/angular/src/vault/components/attachments.component.ts @@ -14,6 +14,8 @@ import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class AttachmentsComponent implements OnInit { @Input() cipherId: string; @@ -40,7 +42,8 @@ export class AttachmentsComponent implements OnInit { protected win: Window, protected logService: LogService, protected stateService: StateService, - protected fileDownloadService: FileDownloadService + protected fileDownloadService: FileDownloadService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -100,15 +103,12 @@ export class AttachmentsComponent implements OnInit { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteAttachmentConfirmation"), - this.i18nService.t("deleteAttachment"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - this.componentName != "" ? this.componentName + " .modal-content" : null - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "deleteAttachment" }, + content: { key: "deleteAttachmentConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return; } @@ -197,23 +197,24 @@ export class AttachmentsComponent implements OnInit { this.canAccessAttachments = canAccessPremium || this.cipher.organizationId != null; if (!this.canAccessAttachments) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("premiumRequiredDesc"), - this.i18nService.t("premiumRequired"), - this.i18nService.t("learnMore"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "premiumRequired" }, + content: { key: "premiumRequiredDesc" }, + acceptButtonText: { key: "learnMore" }, + type: SimpleDialogType.SUCCESS, + }); + if (confirmed) { this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=purchase"); } } else if (!this.hasUpdatedKey) { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("updateKey"), - this.i18nService.t("featureUnavailable"), - this.i18nService.t("learnMore"), - this.i18nService.t("cancel"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "featureUnavailable" }, + content: { key: "updateKey" }, + acceptButtonText: { key: "learnMore" }, + type: SimpleDialogType.WARNING, + }); + if (confirmed) { this.platformUtilsService.launchUri( "https://bitwarden.com/help/account-encryption-key/#rotate-your-encryption-key" diff --git a/libs/angular/src/vault/components/folder-add-edit.component.ts b/libs/angular/src/vault/components/folder-add-edit.component.ts index b3d5b9aa56f..768a2dc519e 100644 --- a/libs/angular/src/vault/components/folder-add-edit.component.ts +++ b/libs/angular/src/vault/components/folder-add-edit.component.ts @@ -7,6 +7,8 @@ import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstraction import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class FolderAddEditComponent implements OnInit { @Input() folderId: string; @@ -25,7 +27,8 @@ export class FolderAddEditComponent implements OnInit { protected folderApiService: FolderApiServiceAbstraction, protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, - private logService: LogService + private logService: LogService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -61,15 +64,12 @@ export class FolderAddEditComponent implements OnInit { } async delete(): Promise { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("deleteFolderConfirmation"), - this.i18nService.t("deleteFolder"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning", - false, - this.componentName != "" ? this.componentName + " .modal-content" : null - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "deleteFolder" }, + content: { key: "deleteFolderConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/libs/angular/src/vault/components/premium.component.ts b/libs/angular/src/vault/components/premium.component.ts index 17bb4bb1b14..a44c30187db 100644 --- a/libs/angular/src/vault/components/premium.component.ts +++ b/libs/angular/src/vault/components/premium.component.ts @@ -6,6 +6,8 @@ import { LogService } from "@bitwarden/common/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { StateService } from "@bitwarden/common/abstractions/state.service"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + @Directive() export class PremiumComponent implements OnInit { isPremium = false; @@ -17,7 +19,8 @@ export class PremiumComponent implements OnInit { protected platformUtilsService: PlatformUtilsService, protected apiService: ApiService, private logService: LogService, - protected stateService: StateService + protected stateService: StateService, + protected dialogService: DialogServiceAbstraction ) {} async ngOnInit() { @@ -36,24 +39,24 @@ export class PremiumComponent implements OnInit { } async purchase() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("premiumPurchaseAlert"), - this.i18nService.t("premiumPurchase"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "premiumPurchase" }, + content: { key: "premiumPurchaseAlert" }, + type: SimpleDialogType.INFO, + }); + if (confirmed) { this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=purchase"); } } async manage() { - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("premiumManageAlert"), - this.i18nService.t("premiumManage"), - this.i18nService.t("yes"), - this.i18nService.t("cancel") - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "premiumManage" }, + content: { key: "premiumManageAlert" }, + type: SimpleDialogType.INFO, + }); + if (confirmed) { this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=manage"); } diff --git a/libs/angular/src/vault/components/view.component.ts b/libs/angular/src/vault/components/view.component.ts index 093d0f40ff1..2dbb6d65e5a 100644 --- a/libs/angular/src/vault/components/view.component.ts +++ b/libs/angular/src/vault/components/view.component.ts @@ -35,6 +35,8 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view"; +import { DialogServiceAbstraction, SimpleDialogType } from "../../services/dialog"; + const BroadcasterSubscriptionId = "ViewComponent"; @Directive() @@ -84,7 +86,8 @@ export class ViewComponent implements OnDestroy, OnInit { protected passwordRepromptService: PasswordRepromptService, private logService: LogService, protected stateService: StateService, - protected fileDownloadService: FileDownloadService + protected fileDownloadService: FileDownloadService, + protected dialogService: DialogServiceAbstraction ) {} ngOnInit() { @@ -174,15 +177,14 @@ export class ViewComponent implements OnDestroy, OnInit { return; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t( - this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" - ), - this.i18nService.t("deleteItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "deleteItem" }, + content: { + key: this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation", + }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } @@ -207,13 +209,12 @@ export class ViewComponent implements OnDestroy, OnInit { return false; } - const confirmed = await this.platformUtilsService.showDialog( - this.i18nService.t("restoreItemConfirmation"), - this.i18nService.t("restoreItem"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "restoreItem" }, + content: { key: "restoreItemConfirmation" }, + type: SimpleDialogType.WARNING, + }); + if (!confirmed) { return false; } diff --git a/libs/common/src/abstractions/platformUtils.service.ts b/libs/common/src/abstractions/platformUtils.service.ts index 0ce932d5268..fd21d854335 100644 --- a/libs/common/src/abstractions/platformUtils.service.ts +++ b/libs/common/src/abstractions/platformUtils.service.ts @@ -27,15 +27,6 @@ export abstract class PlatformUtilsService { text: string | string[], options?: ToastOptions ) => void; - showDialog: ( - body: string, - title?: string, - confirmText?: string, - cancelText?: string, - type?: string, - bodyIsHtml?: boolean, - target?: string - ) => Promise; isDev: () => boolean; isSelfHost: () => boolean; copyToClipboard: (text: string, options?: any) => void | boolean; diff --git a/libs/components/src/dialog/dialog.module.ts b/libs/components/src/dialog/dialog.module.ts index 5fee9f551be..d02b4c06492 100644 --- a/libs/components/src/dialog/dialog.module.ts +++ b/libs/components/src/dialog/dialog.module.ts @@ -1,6 +1,8 @@ import { DialogModule as CdkDialogModule } from "@angular/cdk/dialog"; import { NgModule } from "@angular/core"; +import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog"; + import { ButtonModule } from "../button"; import { IconButtonModule } from "../icon-button"; import { SharedModule } from "../shared"; @@ -29,6 +31,11 @@ import { IconDirective, SimpleDialogComponent } from "./simple-dialog/simple-dia DialogCloseDirective, IconDirective, ], - providers: [DialogService], + providers: [ + { + provide: DialogServiceAbstraction, + useClass: DialogService, + }, + ], }) export class DialogModule {} diff --git a/libs/components/src/dialog/dialog.service.ts b/libs/components/src/dialog/dialog.service.ts index fdde775f66d..0f58c1c847f 100644 --- a/libs/components/src/dialog/dialog.service.ts +++ b/libs/components/src/dialog/dialog.service.ts @@ -16,26 +16,24 @@ import { TemplateRef, } from "@angular/core"; import { NavigationEnd, Router } from "@angular/router"; -import { filter, Subject, switchMap, takeUntil } from "rxjs"; +import { filter, firstValueFrom, Subject, switchMap, takeUntil } from "rxjs"; +import { + DialogServiceAbstraction, + SimpleDialogCloseType, +} from "@bitwarden/angular/services/dialog"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; -import { SimpleDialogOptions } from "./simple-configurable-dialog/models/simple-dialog-options"; +import { SimpleDialogOptions } from "../../../angular/src/services/dialog/simple-dialog-options"; + import { SimpleConfigurableDialogComponent } from "./simple-configurable-dialog/simple-configurable-dialog.component"; @Injectable() -export class DialogService extends Dialog implements OnDestroy { +export class DialogService extends Dialog implements OnDestroy, DialogServiceAbstraction { private _destroy$ = new Subject(); - private backDropClasses = [ - "tw-fixed", - "tw-bg-black", - "tw-bg-opacity-30", - "tw-inset-0", - // CDK dialog panels have a default z-index of 1000. Matching this allows us to easily stack dialogs. - "tw-z-[1000]", - ]; + private backDropClasses = ["tw-fixed", "tw-bg-black", "tw-bg-opacity-30", "tw-inset-0"]; constructor( /** Parent class constructor */ @@ -83,16 +81,33 @@ export class DialogService extends Dialog implements OnDestroy { return super.open(componentOrTemplateRef, config); } + /** + * Opens a simple dialog, returns true if the user accepted the dialog. + * + * @param {SimpleDialogOptions} simpleDialogOptions - An object containing options for the dialog. + * @returns `boolean` - True if the user accepted the dialog, false otherwise. + */ + async openSimpleDialog(simpleDialogOptions: SimpleDialogOptions): Promise { + const dialogRef = this.open(SimpleConfigurableDialogComponent, { + data: simpleDialogOptions, + disableClose: simpleDialogOptions.disableClose, + }); + + return (await firstValueFrom(dialogRef.closed)) == SimpleDialogCloseType.ACCEPT; + } + /** * Opens a simple dialog. * + * @deprecated Use `openSimpleDialog` instead. If you find a use case for the `dialogRef` + * please let #wg-component-library know and we can un-deprecate this method. + * * @param {SimpleDialogOptions} simpleDialogOptions - An object containing options for the dialog. * @returns `DialogRef` - The reference to the opened dialog. * Contains a closed observable which can be subscribed to for determining which button * a user pressed (see `SimpleDialogCloseType`) */ - openSimpleDialog(simpleDialogOptions: SimpleDialogOptions): DialogRef { - // Method needs to return dialog reference so devs can sub to closed and get results. + openSimpleDialogRef(simpleDialogOptions: SimpleDialogOptions): DialogRef { return this.open(SimpleConfigurableDialogComponent, { data: simpleDialogOptions, disableClose: simpleDialogOptions.disableClose, diff --git a/libs/components/src/dialog/index.ts b/libs/components/src/dialog/index.ts index 7ee586158fa..fa6585a3416 100644 --- a/libs/components/src/dialog/index.ts +++ b/libs/components/src/dialog/index.ts @@ -1,5 +1 @@ export * from "./dialog.module"; -export * from "./dialog.service"; -export * from "./simple-configurable-dialog/models/simple-dialog-options"; -export * from "./simple-configurable-dialog/models/simple-dialog-type.enum"; -export * from "./simple-configurable-dialog/models/simple-dialog-close-type.enum"; diff --git a/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.component.ts b/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.component.ts index 215bce0baea..3a627970dda 100644 --- a/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.component.ts +++ b/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.component.ts @@ -1,13 +1,14 @@ import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; +import { + SimpleDialogType, + SimpleDialogCloseType, + Translation, +} from "@bitwarden/angular/services/dialog"; +import { SimpleDialogOptions } from "@bitwarden/angular/services/dialog/simple-dialog-options"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; -import { SimpleDialogCloseType } from "./models/simple-dialog-close-type.enum"; -import { SimpleDialogOptions } from "./models/simple-dialog-options"; -import { SimpleDialogType } from "./models/simple-dialog-type.enum"; -import { Translation } from "./models/translation"; - const DEFAULT_ICON: Record = { [SimpleDialogType.PRIMARY]: "bwi-business", [SimpleDialogType.SUCCESS]: "bwi-star", @@ -70,7 +71,7 @@ export class SimpleConfigurableDialogComponent { private translate(translation: string | Translation, defaultKey?: string): string { // Translation interface use implies we must localize. if (typeof translation === "object") { - return this.i18nService.t(translation.key, ...translation.placeholders); + return this.i18nService.t(translation.key, ...(translation.placeholders ?? [])); } // Use string that is already translated or use default key post translate diff --git a/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.service.stories.ts b/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.service.stories.ts index 37e907a07c2..27c66538a0c 100644 --- a/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.service.stories.ts +++ b/libs/components/src/dialog/simple-configurable-dialog/simple-configurable-dialog.service.stories.ts @@ -1,8 +1,8 @@ -import { DialogModule, DialogRef } from "@angular/cdk/dialog"; +import { DialogModule } from "@angular/cdk/dialog"; import { Component } from "@angular/core"; import { Meta, moduleMetadata, Story } from "@storybook/angular"; -import { firstValueFrom } from "rxjs"; +import { SimpleDialogType, SimpleDialogOptions } from "@bitwarden/angular/services/dialog"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { ButtonModule } from "../../button"; @@ -15,10 +15,6 @@ import { DialogCloseDirective } from "../directives/dialog-close.directive"; import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive"; import { SimpleDialogComponent } from "../simple-dialog/simple-dialog.component"; -import { SimpleDialogCloseType } from "./models/simple-dialog-close-type.enum"; -import { SimpleDialogOptions } from "./models/simple-dialog-options"; -import { SimpleDialogType } from "./models/simple-dialog-type.enum"; - @Component({ template: `

Dialog Type Examples:

@@ -114,8 +110,7 @@ import { SimpleDialogType } from "./models/simple-dialog-type.enum"; - {{ dialogCloseResult }} - undefined + {{ dialogCloseResult }} `, }) @@ -189,22 +184,19 @@ class StoryDialogComponent { showCallout = false; calloutType = "info"; - dialogCloseResult: undefined | SimpleDialogCloseType; + dialogCloseResult: boolean; constructor(public dialogService: DialogService, private i18nService: I18nService) {} - openSimpleConfigurableDialog(opts: SimpleDialogOptions) { - const dialogReference: DialogRef = this.dialogService.openSimpleDialog(opts); + async openSimpleConfigurableDialog(opts: SimpleDialogOptions) { + this.dialogCloseResult = await this.dialogService.openSimpleDialog(opts); - firstValueFrom(dialogReference.closed).then((result: SimpleDialogCloseType | undefined) => { - this.showCallout = true; - this.dialogCloseResult = result; - if (result && result === SimpleDialogCloseType.ACCEPT) { - this.calloutType = "success"; - } else { - this.calloutType = "info"; - } - }); + this.showCallout = true; + if (this.dialogCloseResult) { + this.calloutType = "success"; + } else { + this.calloutType = "info"; + } } }