[PM-4048] Update DeleteAccountComponent on Desktop (#6846)

* [PM-4048] Use dialog service instead of modal service. Change UI file to use bit-Dialog. Remove from app module into standalone.

* [PM-4048] Update app.module imports

* [PM-4048] Fix form.

* PM-4048 - Delete Account tweak - remove unncessary delete header per discussion with product

* PM-4048 - Per CL migration guide,

* PM-4048 - (1) Remove button module import from dialog module exports (2) Add CL imports to desktop app module for delete acct dialog comp (3) Update delete acct dialog comp to use bitSubmit

* PM-4048 - Remove deprecated data-dismiss as bitDialogClose replaced it in terms of functionality.

* PM-4048 - Desktop Delete Acct - update loading button logic to latest CL standards (thanks Will!)

* PM-4048 - Must manually show errors to get "User Verification failed" message when user inputs incorrect MP.

* PM-4048 - desktop - delete-account.component.html - per PR feedback, remove non-tailwind classes and address missing bitFormButton

* PM-4048 - DeleteAccountComponent - per PR feedback, import DialogService using proper import alias.

* PM-4048 - delete-account.component.html - per PR feedback, remove no longer needed #form

* PM-4048 - delete-account.component.html - remove missed non-tailwind class

* PM-4048 - DeleteAccountComponent - per PR feedback, remove try catch as it is unnecessary as the bitSubmit handles errors

* add bespoke border to fix color contrast issue

* convert delete-account.component and user-verification.component to standalone; revert app module CL imports

* run prettier

* run prettier again

---------

Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
Co-authored-by: Jared Snider <jsnider@bitwarden.com>
Co-authored-by: William Martin <contact@willmartian.com>
This commit is contained in:
André Bispo 2023-12-19 19:02:19 +00:00 committed by GitHub
parent 7dff870c93
commit a59eb8dec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 66 deletions

View File

@ -252,7 +252,7 @@ export class AppComponent implements OnInit, OnDestroy {
break;
}
case "deleteAccount":
this.modalService.open(DeleteAccountComponent, { replaceTopModal: true });
DeleteAccountComponent.open(this.dialogService);
break;
case "openPasswordHistory":
await this.openModal<PasswordGeneratorHistoryComponent>(

View File

@ -3,11 +3,11 @@ import "zone.js";
// Register the locales for the application
import "../platform/app/locales";
import { DialogModule } from "@angular/cdk/dialog";
import { NgModule } from "@angular/core";
import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password-count.pipe";
import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe";
import { DialogModule } from "@bitwarden/components";
import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.component";
import { SetPinComponent } from "../auth/components/set-pin.component";
@ -55,7 +55,15 @@ import { AddEditComponent as SendAddEditComponent } from "./tools/send/add-edit.
import { SendComponent } from "./tools/send/send.component";
@NgModule({
imports: [SharedModule, DialogModule, AppRoutingModule, VaultFilterModule, LoginModule],
imports: [
SharedModule,
AppRoutingModule,
VaultFilterModule,
LoginModule,
DialogModule,
DeleteAccountComponent,
UserVerificationComponent,
],
declarations: [
AccessibilityCookieComponent,
AccountSwitcherComponent,
@ -67,7 +75,6 @@ import { SendComponent } from "./tools/send/send.component";
CollectionsComponent,
ColorPasswordPipe,
ColorPasswordCountPipe,
DeleteAccountComponent,
EnvironmentComponent,
ExportComponent,
FolderAddEditComponent,
@ -92,7 +99,6 @@ import { SendComponent } from "./tools/send/send.component";
TwoFactorComponent,
TwoFactorOptionsComponent,
UpdateTempPasswordComponent,
UserVerificationComponent,
VaultComponent,
VaultTimeoutInputComponent,
ViewComponent,

View File

@ -1,11 +1,16 @@
import { animate, style, transition, trigger } from "@angular/animations";
import { CommonModule } from "@angular/common";
import { Component } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule } from "@angular/forms";
import { UserVerificationComponent as BaseComponent } from "@bitwarden/angular/auth/components/user-verification.component";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { FormFieldModule } from "@bitwarden/components";
@Component({
selector: "app-user-verification",
standalone: true,
imports: [CommonModule, JslibModule, ReactiveFormsModule, FormFieldModule, FormsModule],
templateUrl: "user-verification.component.html",
providers: [
{

View File

@ -1,43 +1,30 @@
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="deleteAccountTitle">
<div class="modal-dialog" role="document">
<form
class="modal-content"
#form
[appApiAction]="formPromise"
(ngSubmit)="submit()"
[formGroup]="deleteForm"
>
<div class="modal-body">
<p class="modal-text">{{ "deleteAccountDesc" | i18n }}</p>
<app-callout type="warning" title="{{ 'warning' | i18n }}">
{{ "deleteAccountWarning" | i18n }}
</app-callout>
<div class="box last">
<h1 class="box-header" id="deleteAccountTitle">
{{ "deleteAccount" | i18n }}
</h1>
<div class="box-content">
<app-user-verification
ngDefaultControl
formControlName="verification"
name="verification"
>
</app-user-verification>
</div>
<div id="confirmIdentityHelp" class="box-footer">
<p>{{ "confirmIdentity" | i18n }}</p>
</div>
</div>
<form [bitSubmit]="submit" [formGroup]="deleteForm">
<bit-dialog>
<div bitDialogTitle>{{ "deleteAccount" | i18n }}</div>
<div bitDialogContent>
<p>{{ "deleteAccountDesc" | i18n }}</p>
<bit-callout type="warning" title="{{ 'warning' | i18n }}">
{{ "deleteAccountWarning" | i18n }}
</bit-callout>
<!-- Temporary border styles. TODO: Remove when app-user-verification is migrated to the CL. -->
<div class="tw-mb-2 tw-rounded tw-border tw-border-solid tw-border-info-500/25">
<app-user-verification
ngDefaultControl
formControlName="verification"
name="verification"
></app-user-verification>
</div>
<div class="modal-footer">
<button type="submit" class="danger" [disabled]="form.loading || !secret">
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
<span [hidden]="form.loading">{{ "deleteAccount" | i18n }}</span>
</button>
<button type="button" data-dismiss="modal" [disabled]="form.loading">
{{ "cancel" | i18n }}
</button>
<div id="confirmIdentityHelp">
<p>{{ "confirmIdentity" | i18n }}</p>
</div>
</form>
</div>
</div>
</div>
<div bitDialogFooter>
<button bitButton bitFormButton type="submit" buttonType="danger" [disabled]="!secret">
{{ "deleteAccount" | i18n }}
</button>
<button bitButton type="button" buttonType="secondary" bitFormButton bitDialogClose>
{{ "cancel" | i18n }}
</button>
</div>
</bit-dialog>
</form>

View File

@ -1,19 +1,37 @@
import { DialogRef } from "@angular/cdk/dialog";
import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { FormBuilder, ReactiveFormsModule } from "@angular/forms";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service";
import { Verification } from "@bitwarden/common/auth/types/verification";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import {
AsyncActionsModule,
ButtonModule,
CalloutModule,
DialogModule,
DialogService,
} from "@bitwarden/components";
import { UserVerificationComponent } from "../app/components/user-verification.component";
@Component({
selector: "app-delete-account",
standalone: true,
templateUrl: "delete-account.component.html",
imports: [
JslibModule,
UserVerificationComponent,
ButtonModule,
CalloutModule,
AsyncActionsModule,
DialogModule,
ReactiveFormsModule,
],
})
export class DeleteAccountComponent {
formPromise: Promise<void>;
deleteForm = this.formBuilder.group({
verification: undefined as Verification | undefined,
});
@ -23,25 +41,23 @@ export class DeleteAccountComponent {
private platformUtilsService: PlatformUtilsService,
private formBuilder: FormBuilder,
private accountApiService: AccountApiService,
private logService: LogService,
) {}
static open(dialogService: DialogService): DialogRef<DeleteAccountComponent> {
return dialogService.open(DeleteAccountComponent);
}
get secret() {
return this.deleteForm.get("verification")?.value?.secret;
}
async submit() {
try {
const verification = this.deleteForm.get("verification").value;
this.formPromise = this.accountApiService.deleteAccount(verification);
await this.formPromise;
this.platformUtilsService.showToast(
"success",
this.i18nService.t("accountDeleted"),
this.i18nService.t("accountDeletedDesc"),
);
} catch (e) {
this.logService.error(e);
}
}
submit = async () => {
const verification = this.deleteForm.get("verification").value;
await this.accountApiService.deleteAccount(verification);
this.platformUtilsService.showToast(
"success",
this.i18nService.t("accountDeleted"),
this.i18nService.t("accountDeletedDesc"),
);
};
}