From 6995e8d75933caeb01c32816856c77707c58bce6 Mon Sep 17 00:00:00 2001 From: Patrick Pimentel Date: Thu, 30 Jan 2025 15:56:50 -0500 Subject: [PATCH] fix(misc-refactors-and-fixes): [PM-16783] Tech Debt and Toast Fixes - Initial changes being brought over from other branch. --- apps/browser/src/auth/popup/home.component.ts | 8 ++-- .../src/auth/popup/login-v1.component.html | 2 +- .../src/auth/popup/login-v1.component.ts | 10 +---- .../login/desktop-login-component.service.ts | 2 +- .../src/auth/login/login-v1.component.ts | 6 +-- .../accept-family-sponsorship.component.ts | 4 -- ...families-for-enterprise-setup.component.ts | 9 +---- .../accept/accept-emergency.component.ts | 19 ++++----- .../app/auth/login/login-v1.component.html | 2 +- .../src/app/auth/login/login-v1.component.ts | 2 +- .../accept-organization.component.ts | 21 +++++----- .../organization-invite.ts | 24 +++++------- .../src/app/common/base.accept.component.ts | 18 +++++---- .../src/app/tools/send/access.component.ts | 2 - .../manage/accept-provider.component.ts | 18 ++++----- .../src/auth/components/login-v1.component.ts | 39 +++++++++++-------- .../auth/components/two-factor.component.ts | 2 +- .../auth/src/angular/login/login.component.ts | 2 +- libs/components/src/toast/toast.component.ts | 2 +- libs/components/src/toast/toast.service.ts | 9 +++++ 20 files changed, 95 insertions(+), 106 deletions(-) diff --git a/apps/browser/src/auth/popup/home.component.ts b/apps/browser/src/auth/popup/home.component.ts index dbdcf7d5aa8..b8b724c4b60 100644 --- a/apps/browser/src/auth/popup/home.component.ts +++ b/apps/browser/src/auth/popup/home.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; @@ -10,6 +8,7 @@ import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; 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 { ToastService } from "@bitwarden/components"; @@ -25,7 +24,7 @@ export class HomeComponent implements OnInit, OnDestroy { private destroyed$: Subject = new Subject(); loginInitiated = false; - formGroup = this.formBuilder.group({ + formGroup = this.formBuilder.nonNullable.group({ email: ["", [Validators.required, Validators.email]], rememberEmail: [false], }); @@ -40,6 +39,7 @@ export class HomeComponent implements OnInit, OnDestroy { private toastService: ToastService, private configService: ConfigService, private route: ActivatedRoute, + private logService: LogService, ) {} async ngOnInit(): Promise { @@ -107,7 +107,7 @@ export class HomeComponent implements OnInit, OnDestroy { if (this.formGroup.invalid) { this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("invalidEmail"), }); return; diff --git a/apps/browser/src/auth/popup/login-v1.component.html b/apps/browser/src/auth/popup/login-v1.component.html index 145a9cbc754..e5112b68060 100644 --- a/apps/browser/src/auth/popup/login-v1.component.html +++ b/apps/browser/src/auth/popup/login-v1.component.html @@ -1,4 +1,4 @@ -
+

{{ "logIn" | i18n }} diff --git a/apps/browser/src/auth/popup/login-v1.component.ts b/apps/browser/src/auth/popup/login-v1.component.ts index b2c52f248c6..f4222918aa5 100644 --- a/apps/browser/src/auth/popup/login-v1.component.ts +++ b/apps/browser/src/auth/popup/login-v1.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component, NgZone, OnInit } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; @@ -82,15 +80,9 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit { await this.validateEmail(); } - settings() { - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.router.navigate(["environment"]); - } - async launchSsoBrowser() { // Save off email for SSO - await this.ssoLoginService.setSsoEmail(this.formGroup.value.email); + await this.ssoLoginService.setSsoEmail(this.formGroup.controls.email.value); // Generate necessary sso params const passwordOptions: any = { diff --git a/apps/desktop/src/auth/login/desktop-login-component.service.ts b/apps/desktop/src/auth/login/desktop-login-component.service.ts index dbf689e801c..cb7bdc47bb7 100644 --- a/apps/desktop/src/auth/login/desktop-login-component.service.ts +++ b/apps/desktop/src/auth/login/desktop-login-component.service.ts @@ -70,7 +70,7 @@ export class DesktopLoginComponentService } catch (err) { this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("ssoError"), }); } diff --git a/apps/desktop/src/auth/login/login-v1.component.ts b/apps/desktop/src/auth/login/login-v1.component.ts index f78bee7323d..57d032cbaba 100644 --- a/apps/desktop/src/auth/login/login-v1.component.ts +++ b/apps/desktop/src/auth/login/login-v1.component.ts @@ -50,7 +50,7 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit, OnDe private deferFocus: boolean = null; get loggedEmail() { - return this.formGroup.value.email; + return this.formGroup.controls.email.value; } constructor( @@ -191,7 +191,7 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit, OnDe if (!this.formGroup.controls.email.valid) { this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("invalidEmail"), }); return; @@ -249,7 +249,7 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit, OnDe } catch (err) { this.platformUtilsService.showToast( "error", - this.i18nService.t("errorOccured"), + this.i18nService.t("errorOccurred"), this.i18nService.t("ssoError"), ); } diff --git a/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts b/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts index bef0589df83..503144d6c01 100644 --- a/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts +++ b/apps/web/src/app/admin-console/organizations/sponsorships/accept-family-sponsorship.component.ts @@ -1,10 +1,7 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component, inject } from "@angular/core"; import { Params } from "@angular/router"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; -import { OrganizationSponsorshipResponse } from "@bitwarden/common/admin-console/models/response/organization-sponsorship.response"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ToastService } from "@bitwarden/components"; @@ -25,7 +22,6 @@ export class AcceptFamilySponsorshipComponent extends BaseAcceptComponent { requiredParameters = ["email", "token"]; - policyResponse!: OrganizationSponsorshipResponse; policyApiService = inject(PolicyApiServiceAbstraction); configService = inject(ConfigService); toastService = inject(ToastService); diff --git a/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts b/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts index fdad689d982..eaa92dc32b8 100644 --- a/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts +++ b/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; @@ -16,7 +14,6 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { PlanSponsorshipType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { DialogService, ToastService } from "@bitwarden/components"; @@ -64,7 +61,6 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy { constructor( private router: Router, - private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, private route: ActivatedRoute, private apiService: ApiService, @@ -87,7 +83,6 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy { variant: "error", title: null, message: this.i18nService.t("sponsoredFamiliesAcceptFailed"), - timeout: 10000, }); // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -105,7 +100,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy { if (this.preValidateSponsorshipResponse.isFreeFamilyPolicyEnabled) { this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("offerNoLongerValid"), }); @@ -137,7 +132,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy { } }); this.formGroup.valueChanges.pipe(takeUntil(this._destroy)).subscribe((val) => { - this.selectedFamilyOrganizationId = val.selectedFamilyOrganizationId; + this.selectedFamilyOrganizationId = val.selectedFamilyOrganizationId ?? ""; }); } diff --git a/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.ts b/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.ts index b3f635aee92..dfaf7cf9d44 100644 --- a/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.ts +++ b/apps/web/src/app/auth/emergency-access/accept/accept-emergency.component.ts @@ -1,11 +1,9 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component } from "@angular/core"; import { ActivatedRoute, Params, Router } from "@angular/router"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { ToastService } from "@bitwarden/components"; import { BaseAcceptComponent } from "../../../common/base.accept.component"; import { SharedModule } from "../../../shared"; @@ -28,24 +26,23 @@ export class AcceptEmergencyComponent extends BaseAcceptComponent { constructor( router: Router, - platformUtilsService: PlatformUtilsService, i18nService: I18nService, route: ActivatedRoute, authService: AuthService, + toastService: ToastService, private emergencyAccessService: EmergencyAccessService, ) { - super(router, platformUtilsService, i18nService, route, authService); + super(router, i18nService, route, authService, toastService); } async authedHandler(qParams: Params): Promise { this.actionPromise = this.emergencyAccessService.accept(qParams.id, qParams.token); await this.actionPromise; - this.platformUtilService.showToast( - "success", - this.i18nService.t("inviteAccepted"), - this.i18nService.t("emergencyInviteAcceptedDesc"), - { timeout: 10000 }, - ); + this.toastService.showToast({ + variant: "success", + title: this.i18nService.t("inviteAccepted"), + message: this.i18nService.t("emergencyInviteAcceptedDesc"), + }); // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // eslint-disable-next-line @typescript-eslint/no-floating-promises this.router.navigate(["/vault"]); diff --git a/apps/web/src/app/auth/login/login-v1.component.html b/apps/web/src/app/auth/login/login-v1.component.html index b41e55a03b0..e9b7fe07ef4 100644 --- a/apps/web/src/app/auth/login/login-v1.component.html +++ b/apps/web/src/app/auth/login/login-v1.component.html @@ -122,7 +122,7 @@
-

{{ "loggingInAs" | i18n }} {{ loggedEmail }}

+

{{ "loggingInAs" | i18n }} {{ this.formGroup.controls.email.value }}

{{ "notYou" | i18n }}
diff --git a/apps/web/src/app/auth/login/login-v1.component.ts b/apps/web/src/app/auth/login/login-v1.component.ts index a3099d991d9..5a3387e2815 100644 --- a/apps/web/src/app/auth/login/login-v1.component.ts +++ b/apps/web/src/app/auth/login/login-v1.component.ts @@ -136,7 +136,7 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit { } async goAfterLogIn(userId: UserId) { - const masterPassword = this.formGroup.value.masterPassword; + const masterPassword = this.formGroup.controls.masterPassword.value; // Check master password against policy if (this.enforcedPasswordPolicyOptions != null) { diff --git a/apps/web/src/app/auth/organization-invite/accept-organization.component.ts b/apps/web/src/app/auth/organization-invite/accept-organization.component.ts index 197b4031998..1ad678a62ac 100644 --- a/apps/web/src/app/auth/organization-invite/accept-organization.component.ts +++ b/apps/web/src/app/auth/organization-invite/accept-organization.component.ts @@ -1,11 +1,10 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component } from "@angular/core"; import { ActivatedRoute, Params, Router } from "@angular/router"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { ToastService } from "@bitwarden/components"; import { BaseAcceptComponent } from "../../common/base.accept.component"; @@ -21,13 +20,14 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent { constructor( router: Router, - platformUtilsService: PlatformUtilsService, i18nService: I18nService, route: ActivatedRoute, authService: AuthService, + private toastService: ToastService, private acceptOrganizationInviteService: AcceptOrganizationInviteService, + private logService: LogService, ) { - super(router, platformUtilsService, i18nService, route, authService); + super(router, i18nService, route, authService, toastService); } async authedHandler(qParams: Params): Promise { @@ -38,14 +38,13 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent { return; } - this.platformUtilService.showToast( - "success", - this.i18nService.t("inviteAccepted"), - invite.initOrganization + this.toastService.showToast({ + variant: "success", + title: this.i18nService.t("inviteAccepted"), + message: invite.initOrganization ? this.i18nService.t("inviteInitAcceptedDesc") : this.i18nService.t("inviteAcceptedDesc"), - { timeout: 10000 }, - ); + }); await this.router.navigate(["/vault"]); } diff --git a/apps/web/src/app/auth/organization-invite/organization-invite.ts b/apps/web/src/app/auth/organization-invite/organization-invite.ts index 65414113e74..94f1376000f 100644 --- a/apps/web/src/app/auth/organization-invite/organization-invite.ts +++ b/apps/web/src/app/auth/organization-invite/organization-invite.ts @@ -1,17 +1,15 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Params } from "@angular/router"; import { Jsonify } from "type-fest"; export class OrganizationInvite { - email: string; - initOrganization: boolean; - orgSsoIdentifier: string; - orgUserHasExistingUser: boolean; - organizationId: string; - organizationName: string; - organizationUserId: string; - token: string; + email!: string; + initOrganization!: boolean; + orgSsoIdentifier!: string; + orgUserHasExistingUser!: boolean; + organizationId!: string; + organizationName!: string; + organizationUserId!: string; + token!: string; static fromJSON(json: Jsonify): OrganizationInvite | null { if (json == null) { @@ -21,11 +19,7 @@ export class OrganizationInvite { return Object.assign(new OrganizationInvite(), json); } - static fromParams(params: Params): OrganizationInvite | null { - if (params == null) { - return null; - } - + static fromParams(params: Params): OrganizationInvite { return Object.assign(new OrganizationInvite(), { email: params.email, initOrganization: params.initOrganization?.toLocaleLowerCase() === "true", diff --git a/apps/web/src/app/common/base.accept.component.ts b/apps/web/src/app/common/base.accept.component.ts index 82a192ab0cf..64223e3ad6e 100644 --- a/apps/web/src/app/common/base.accept.component.ts +++ b/apps/web/src/app/common/base.accept.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Directive, OnInit } from "@angular/core"; import { ActivatedRoute, Params, Router } from "@angular/router"; import { Subject, firstValueFrom } from "rxjs"; @@ -8,7 +6,7 @@ import { first, switchMap, takeUntil } from "rxjs/operators"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { ToastService } from "@bitwarden/components"; @Directive() export abstract class BaseAcceptComponent implements OnInit { @@ -25,10 +23,10 @@ export abstract class BaseAcceptComponent implements OnInit { constructor( protected router: Router, - protected platformUtilService: PlatformUtilsService, protected i18nService: I18nService, protected route: ActivatedRoute, protected authService: AuthService, + protected toastService: ToastService, ) {} abstract authedHandler(qParams: Params): Promise; @@ -43,7 +41,7 @@ export abstract class BaseAcceptComponent implements OnInit { let error = this.requiredParameters.some( (e) => qParams?.[e] == null || qParams[e] === "", ); - let errorMessage: string = null; + let errorMessage: string | null = null; if (!error) { this.email = qParams.email; @@ -51,7 +49,7 @@ export abstract class BaseAcceptComponent implements OnInit { if (status !== AuthenticationStatus.LoggedOut) { try { await this.authedHandler(qParams); - } catch (e) { + } catch (e: { message: string } | any) { error = true; errorMessage = e.message; } @@ -65,7 +63,13 @@ export abstract class BaseAcceptComponent implements OnInit { errorMessage != null ? this.i18nService.t(this.failedShortMessage, errorMessage) : this.i18nService.t(this.failedMessage); - this.platformUtilService.showToast("error", null, message, { timeout: 10000 }); + + this.toastService.showToast({ + variant: "error", + title: null, + message, + }); + // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // eslint-disable-next-line @typescript-eslint/no-floating-promises this.router.navigate(["/"]); diff --git a/apps/web/src/app/tools/send/access.component.ts b/apps/web/src/app/tools/send/access.component.ts index ccfecdd197e..b76c3853d52 100644 --- a/apps/web/src/app/tools/send/access.component.ts +++ b/apps/web/src/app/tools/send/access.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component, OnInit } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts index 56584b67f02..46bd369c0e9 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/accept-provider.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Component } from "@angular/core"; import { ActivatedRoute, Params, Router } from "@angular/router"; @@ -8,6 +6,7 @@ import { ProviderUserAcceptRequest } from "@bitwarden/common/admin-console/model import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { ToastService } from "@bitwarden/components"; import { BaseAcceptComponent } from "@bitwarden/web-vault/app/common/base.accept.component"; @Component({ @@ -30,9 +29,10 @@ export class AcceptProviderComponent extends BaseAcceptComponent { route: ActivatedRoute, authService: AuthService, private apiService: ApiService, + toastService: ToastService, platformUtilService: PlatformUtilsService, ) { - super(router, platformUtilService, i18nService, route, authService); + super(router, platformUtilService, i18nService, route, authService, toastService); } async authedHandler(qParams: Params) { @@ -45,12 +45,12 @@ export class AcceptProviderComponent extends BaseAcceptComponent { request, ); - this.platformUtilService.showToast( - "success", - this.i18nService.t("inviteAccepted"), - this.i18nService.t("providerInviteAcceptedDesc"), - { timeout: 10000 }, - ); + this.toastService.showToast({ + variant: "success", + title: this.i18nService.t("inviteAccepted"), + message: this.i18nService.t("providerInviteAcceptedDesc"), + }); + this.router.navigate(["/vault"]); } diff --git a/libs/angular/src/auth/components/login-v1.component.ts b/libs/angular/src/auth/components/login-v1.component.ts index 3416901da97..1e35839beda 100644 --- a/libs/angular/src/auth/components/login-v1.component.ts +++ b/libs/angular/src/auth/components/login-v1.component.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Directive, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { ActivatedRoute, NavigationSkipped, Router } from "@angular/router"; @@ -223,12 +221,16 @@ export class LoginComponentV1 extends CaptchaProtectedComponent implements OnIni togglePassword() { this.showPassword = !this.showPassword; - if (this.ngZone.isStable) { - document.getElementById("masterPassword").focus(); + const masterPasswordElement = document.getElementById("masterPassword"); + + if (masterPasswordElement) { + if (this.ngZone.isStable) { + masterPasswordElement.focus(); + } else { + this.ngZone.onStable.pipe(take(1)).subscribe(() => masterPasswordElement.focus()); + } } else { - this.ngZone.onStable - .pipe(take(1)) - .subscribe(() => document.getElementById("masterPassword").focus()); + this.logService.warning("Element with ID 'masterPassword' not found."); } } @@ -246,7 +248,7 @@ export class LoginComponentV1 extends CaptchaProtectedComponent implements OnIni async launchSsoBrowser(clientId: string, ssoRedirectUri: string) { // Save off email for SSO - await this.ssoLoginService.setSsoEmail(this.formGroup.value.email); + await this.ssoLoginService.setSsoEmail(this.formGroup.controls.email.value); // Generate necessary sso params const passwordOptions: any = { @@ -288,11 +290,11 @@ export class LoginComponentV1 extends CaptchaProtectedComponent implements OnIni async validateEmail() { this.formGroup.controls.email.markAsTouched(); - const emailValid = this.formGroup.get("email").valid; + const emailValid = this.formGroup.controls.email.valid; if (emailValid) { this.toggleValidateEmail(true); - await this.getLoginWithDevice(this.loggedEmail); + await this.getLoginWithDevice(this.formGroup.controls.email.value); } } @@ -339,8 +341,8 @@ export class LoginComponentV1 extends CaptchaProtectedComponent implements OnIni } protected async saveEmailSettings() { - this.loginEmailService.setLoginEmail(this.formGroup.value.email); - this.loginEmailService.setRememberEmail(this.formGroup.value.rememberEmail); + this.loginEmailService.setLoginEmail(this.formGroup.controls.email.value); + this.loginEmailService.setRememberEmail(this.formGroup.controls.rememberEmail.value); await this.loginEmailService.saveEmailSettings(); } @@ -352,14 +354,14 @@ export class LoginComponentV1 extends CaptchaProtectedComponent implements OnIni this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("encryptionKeyMigrationRequired"), }); return true; } - private getErrorToastMessage() { - const error: AllValidationErrors = this.formValidationErrorService + private getErrorToastMessage(): string { + const error: AllValidationErrors | undefined = this.formValidationErrorService .getFormValidationErrors(this.formGroup.controls) .shift(); @@ -372,9 +374,12 @@ export class LoginComponentV1 extends CaptchaProtectedComponent implements OnIni default: return this.i18nService.t(this.errorTag(error)); } + } else { + this.logService.warning( + "formValidationErrorService produced no errors even when the form is invalid.", + ); + return this.i18nService.t("errorOccurred"); } - - return; } private errorTag(error: AllValidationErrors): string { diff --git a/libs/angular/src/auth/components/two-factor.component.ts b/libs/angular/src/auth/components/two-factor.component.ts index 3b3459f42fb..fd5cae506ec 100644 --- a/libs/angular/src/auth/components/two-factor.component.ts +++ b/libs/angular/src/auth/components/two-factor.component.ts @@ -268,7 +268,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("encryptionKeyMigrationRequired"), }); return true; diff --git a/libs/auth/src/angular/login/login.component.ts b/libs/auth/src/angular/login/login.component.ts index 66fe2503508..c0fc3a77450 100644 --- a/libs/auth/src/angular/login/login.component.ts +++ b/libs/auth/src/angular/login/login.component.ts @@ -263,7 +263,7 @@ export class LoginComponent implements OnInit, OnDestroy { } else { this.toastService.showToast({ variant: "error", - title: this.i18nService.t("errorOccured"), + title: this.i18nService.t("errorOccurred"), message: this.i18nService.t("encryptionKeyMigrationRequired"), }); } diff --git a/libs/components/src/toast/toast.component.ts b/libs/components/src/toast/toast.component.ts index 14fd5a7c62c..603a595e680 100644 --- a/libs/components/src/toast/toast.component.ts +++ b/libs/components/src/toast/toast.component.ts @@ -45,7 +45,7 @@ export class ToastComponent { message: string | string[]; /** An optional title to display over the message. */ - @Input() title: string; + @Input() title: string | null; /** * The percent width of the progress bar, from 0-100 diff --git a/libs/components/src/toast/toast.service.ts b/libs/components/src/toast/toast.service.ts index 00c32f9b1b3..0e250270827 100644 --- a/libs/components/src/toast/toast.service.ts +++ b/libs/components/src/toast/toast.service.ts @@ -20,6 +20,15 @@ export type ToastOptions = { export class ToastService { constructor(private toastrService: ToastrService) {} + /** + * This will present the toast to a user. + * + * Note: The toast will be displayed for a minimum of 5 seconds if no timeout is provided in + * the options. + * + * @param options Options for toasts. If no timeout is specified an appropriate duration will be + * calculated on the size of the message being displayed. + */ showToast(options: ToastOptions): void { const toastrConfig: Partial = { payload: {