From 7bb4ea842f2bc99922c52efb79d0d35d55e2cf15 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 22 Jan 2024 10:36:42 +0100 Subject: [PATCH] [PM-3919] Remove deprecated Angular functionality from ModalService (#6285) Remove deprecated Angular functionality from ModalService so we can upgrade Angular. --- .../policies/policy-edit.component.ts | 5 +- .../user-verification-prompt.component.ts | 23 ++---- apps/web/src/app/core/modal.service.ts | 6 +- .../user-verification-prompt.component.ts | 15 ++-- .../modal/dynamic-modal.component.ts | 7 +- libs/angular/src/services/modal.service.ts | 80 +++---------------- 6 files changed, 29 insertions(+), 107 deletions(-) diff --git a/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts b/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts index 68a9f23ec0..2ec82ebaaf 100644 --- a/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts +++ b/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts @@ -1,7 +1,6 @@ import { ChangeDetectorRef, Component, - ComponentFactoryResolver, EventEmitter, Input, Output, @@ -45,7 +44,6 @@ export class PolicyEditComponent { private policyApiService: PolicyApiServiceAbstraction, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private componentFactoryResolver: ComponentFactoryResolver, private cdr: ChangeDetectorRef, private logService: LogService, ) {} @@ -54,8 +52,7 @@ export class PolicyEditComponent { await this.load(); this.loading = false; - const factory = this.componentFactoryResolver.resolveComponentFactory(this.policy.component); - this.policyComponent = this.policyFormRef.createComponent(factory) + this.policyComponent = this.policyFormRef.createComponent(this.policy.component) .instance as BasePolicyComponent; this.policyComponent.policy = this.policy; this.policyComponent.policyResponse = this.policyResponse; diff --git a/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts b/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts index c3cfff83dd..89b751b518 100644 --- a/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts +++ b/apps/web/src/app/auth/shared/components/user-verification/user-verification-prompt.component.ts @@ -2,19 +2,15 @@ import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; import { FormBuilder } from "@angular/forms"; -import { UserVerificationPromptComponent as BaseUserVerificationPrompt } from "@bitwarden/angular/auth/components/user-verification-prompt.component"; -import { ModalConfig } from "@bitwarden/angular/services/modal.service"; +import { + UserVerificationPromptComponent as BaseUserVerificationPrompt, + UserVerificationPromptParams, +} from "@bitwarden/angular/auth/components/user-verification-prompt.component"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { DialogService } from "@bitwarden/components"; -export interface UserVerificationPromptParams { - confirmDescription: string; - confirmButtonText: string; - modalTitle: string; -} - @Component({ templateUrl: "user-verification-prompt.component.html", }) @@ -27,16 +23,7 @@ export class UserVerificationPromptComponent extends BaseUserVerificationPrompt platformUtilsService: PlatformUtilsService, i18nService: I18nService, ) { - // TODO: Remove when BaseUserVerificationPrompt has support for CL - const modalConfig: ModalConfig = { data }; - super( - null, - modalConfig, - userVerificationService, - formBuilder, - platformUtilsService, - i18nService, - ); + super(null, data, userVerificationService, formBuilder, platformUtilsService, i18nService); } override close(success: boolean) { diff --git a/apps/web/src/app/core/modal.service.ts b/apps/web/src/app/core/modal.service.ts index 290addb4f5..14ea6044f3 100644 --- a/apps/web/src/app/core/modal.service.ts +++ b/apps/web/src/app/core/modal.service.ts @@ -1,4 +1,4 @@ -import { ApplicationRef, ComponentFactoryResolver, Injectable, Injector } from "@angular/core"; +import { Injectable, Injector } from "@angular/core"; import * as jq from "jquery"; import { first } from "rxjs/operators"; @@ -13,12 +13,10 @@ export class ModalService extends BaseModalService { modalOpen = false; constructor( - componentFactoryResolver: ComponentFactoryResolver, - applicationRef: ApplicationRef, injector: Injector, private messagingService: MessagingService, ) { - super(componentFactoryResolver, applicationRef, injector); + super(injector); } protected setupHandlers(modalRef: ModalRef) { diff --git a/libs/angular/src/auth/components/user-verification-prompt.component.ts b/libs/angular/src/auth/components/user-verification-prompt.component.ts index a35ef88fc7..4c0a49ddfc 100644 --- a/libs/angular/src/auth/components/user-verification-prompt.component.ts +++ b/libs/angular/src/auth/components/user-verification-prompt.component.ts @@ -7,16 +7,21 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { ModalRef } from "../../components/modal/modal.ref"; -import { ModalConfig } from "../../services/modal.service"; + +export interface UserVerificationPromptParams { + confirmDescription: string; + confirmButtonText: string; + modalTitle: string; +} /** * Used to verify the user's identity (using their master password or email-based OTP for Key Connector users). You can customize all of the text in the modal. */ @Directive() export class UserVerificationPromptComponent { - confirmDescription = this.config.data.confirmDescription; - confirmButtonText = this.config.data.confirmButtonText; - modalTitle = this.config.data.modalTitle; + confirmDescription = this.config.confirmDescription; + confirmButtonText = this.config.confirmButtonText; + modalTitle = this.config.modalTitle; formGroup = this.formBuilder.group({ secret: this.formBuilder.control(null), @@ -26,7 +31,7 @@ export class UserVerificationPromptComponent { constructor( private modalRef: ModalRef, - protected config: ModalConfig, + protected config: UserVerificationPromptParams, protected userVerificationService: UserVerificationService, private formBuilder: FormBuilder, private platformUtilsService: PlatformUtilsService, diff --git a/libs/angular/src/components/modal/dynamic-modal.component.ts b/libs/angular/src/components/modal/dynamic-modal.component.ts index c44cf33318..8131572da9 100644 --- a/libs/angular/src/components/modal/dynamic-modal.component.ts +++ b/libs/angular/src/components/modal/dynamic-modal.component.ts @@ -11,8 +11,6 @@ import { ViewContainerRef, } from "@angular/core"; -import { ModalService } from "../../services/modal.service"; - import { ModalRef } from "./modal.ref"; @Component({ @@ -31,7 +29,6 @@ export class DynamicModalComponent implements AfterViewInit, OnDestroy { private focusTrap: ConfigurableFocusTrap; constructor( - private modalService: ModalService, private cd: ChangeDetectorRef, private el: ElementRef, private focusTrapFactory: ConfigurableFocusTrapFactory, @@ -55,10 +52,8 @@ export class DynamicModalComponent implements AfterViewInit, OnDestroy { } loadChildComponent(componentType: Type) { - const componentFactory = this.modalService.resolveComponentFactory(componentType); - this.modalContentRef.clear(); - this.componentRef = this.modalContentRef.createComponent(componentFactory); + this.componentRef = this.modalContentRef.createComponent(componentType); } ngOnDestroy() { diff --git a/libs/angular/src/services/modal.service.ts b/libs/angular/src/services/modal.service.ts index c96cb2f8d3..250fb941f4 100644 --- a/libs/angular/src/services/modal.service.ts +++ b/libs/angular/src/services/modal.service.ts @@ -1,26 +1,10 @@ -import { - ApplicationRef, - ComponentFactory, - ComponentFactoryResolver, - ComponentRef, - EmbeddedViewRef, - Injectable, - Injector, - Type, - ViewContainerRef, -} from "@angular/core"; +import { ComponentRef, Injectable, Injector, Type, ViewContainerRef } from "@angular/core"; import { first } from "rxjs/operators"; import { DynamicModalComponent } from "../components/modal/dynamic-modal.component"; import { ModalInjector } from "../components/modal/modal-injector"; import { ModalRef } from "../components/modal/modal.ref"; -export class ModalConfig { - data?: D; - allowMultipleModals?: boolean; - replaceTopModal?: boolean; -} - /** * @deprecated Use the Component Library's `DialogService` instead. */ @@ -28,15 +12,7 @@ export class ModalConfig { export class ModalService { protected modalList: ComponentRef[] = []; - // Lazy loaded modules are not available in componentFactoryResolver, - // therefore modules needs to manually initialize their resolvers. - private factoryResolvers: Map, ComponentFactoryResolver> = new Map(); - - constructor( - private componentFactoryResolver: ComponentFactoryResolver, - private applicationRef: ApplicationRef, - private injector: Injector, - ) { + constructor(private injector: Injector) { document.addEventListener("keyup", (event) => { if (event.key === "Escape" && this.modalCount > 0) { this.topModal.instance.close(); @@ -62,7 +38,7 @@ export class ModalService { viewContainerRef: ViewContainerRef, setComponentParameters: (component: T) => void = null, ): Promise<[ModalRef, T]> { - const [modalRef, modalComponentRef] = this.openInternal(componentType, null, false); + const [modalRef, modalComponentRef] = this.openInternal(viewContainerRef, componentType); modalComponentRef.instance.setComponentParameters = setComponentParameters; viewContainerRef.insert(modalComponentRef.hostView); @@ -72,52 +48,18 @@ export class ModalService { return [modalRef, modalComponentRef.instance.componentRef.instance]; } - open(componentType: Type, config: ModalConfig = {}) { - const { replaceTopModal = false, allowMultipleModals = false } = config; - - if (this.modalCount > 0 && replaceTopModal) { - this.topModal.instance.close(); - } - - if (this.modalCount > 0 && !allowMultipleModals) { - return; - } - - const [modalRef] = this.openInternal(componentType, config, true); - - return modalRef; - } - - resolveComponentFactory(componentType: Type): ComponentFactory { - if (this.factoryResolvers.has(componentType)) { - return this.factoryResolvers.get(componentType).resolveComponentFactory(componentType); - } - - return this.componentFactoryResolver.resolveComponentFactory(componentType); - } - closeAll(): void { this.modalList.forEach((modal) => modal.instance.close()); } protected openInternal( + viewContainerRef: ViewContainerRef, componentType: Type, - config?: ModalConfig, - attachToDom?: boolean, - ): [ModalRef, ComponentRef] { - const [modalRef, componentRef] = this.createModalComponent(config); + ): [ModalRef, ComponentRef] { + const [modalRef, componentRef] = this.createModalComponent(viewContainerRef); componentRef.instance.childComponentType = componentType; - if (attachToDom) { - this.applicationRef.attachView(componentRef.hostView); - const domElem = (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement; - document.body.appendChild(domElem); - } - modalRef.onClosed.pipe(first()).subscribe(() => { - if (attachToDom) { - this.applicationRef.detachView(componentRef.hostView); - } componentRef.destroy(); this.modalList.pop(); @@ -174,17 +116,15 @@ export class ModalService { } protected createModalComponent( - config: ModalConfig, - ): [ModalRef, ComponentRef] { + viewContainerRef: ViewContainerRef, + ): [ModalRef, ComponentRef] { const modalRef = new ModalRef(); const map = new WeakMap(); - map.set(ModalConfig, config); map.set(ModalRef, modalRef); - const componentFactory = - this.componentFactoryResolver.resolveComponentFactory(DynamicModalComponent); - const componentRef = componentFactory.create(new ModalInjector(this.injector, map)); + const injector = new ModalInjector(this.injector, map); + const componentRef = viewContainerRef.createComponent(DynamicModalComponent, { injector }); return [modalRef, componentRef]; }