import { ApplicationRef, ChangeDetectorRef, Component, ComponentFactoryResolver, Directive, ElementRef, Inject, Injectable, Injector, Input, OnDestroy, Type, ViewContainerRef } from "@angular/core"; import {DialogComponent} from "./dialog.component"; import {isTargetChildOf} from "../../core/utils"; import {eachPair} from "@marcj/estdlib"; import {DuiDialogProgress, ProgressDialogState} from "./progress-dialog.component"; import {DOCUMENT} from "@angular/common"; import {WindowRegistry} from "../window/window-state"; @Component({ template: `

{{title || 'No title'}}

{{content}}
Cancel OK ` }) export class DuiDialogConfirm { @Input() title: string = 'Confirm'; @Input() content: string = ''; static dialogDefaults = { maxWidth: '700px' } } @Component({ template: `

{{title || 'No title'}}

{{content}}
OK ` }) export class DuiDialogAlert { @Input() title: string = 'Alert'; @Input() content: string = ''; static dialogDefaults = { maxWidth: '700px' } } @Component({ template: `

{{title || 'No title'}}

{{content}}
Cancel OK ` }) export class DuiDialogPrompt { @Input() title: string = 'Alert'; @Input() content: string = ''; @Input() value: string = ''; static dialogDefaults = { maxWidth: '700px' }; constructor(public dialog: DialogComponent) { } } @Injectable() export class DuiDialog { constructor( protected resolver: ComponentFactoryResolver, protected app: ApplicationRef, protected injector: Injector, protected registry: WindowRegistry, ) { } public open( component: Type, inputs: { [name in keyof T]?: any } = {}, dialogInputs: { [name: string]: any } = {}, viewContainerRef: ViewContainerRef | null = null, ): { dialog: DialogComponent, component: T } { if (!viewContainerRef) { viewContainerRef = this.registry.getCurrentViewContainerRef(); } const factory = this.resolver.resolveComponentFactory(DialogComponent); const comp = viewContainerRef.createComponent(factory); comp.instance.visible = true; comp.instance.component = component; comp.instance.componentInputs = inputs; if ((component as any).dialogDefaults) { for (const [i, v] of eachPair((component as any).dialogDefaults)) { (comp.instance as any)[i] = v; } } for (const [i, v] of eachPair(dialogInputs)) { (comp.instance as any)[i] = v; } comp.instance.show(); comp.changeDetectorRef.detectChanges(); comp.instance.closed.subscribe(() => { comp.destroy(); }); return { dialog: comp.instance, component: comp.instance.wrapperComponentRef!.instance!.renderComponentDirective!.component!.instance, }; } public async alert(title: string, content?: string, dialodInputs: { [name: string]: any } = {}): Promise { const {dialog} = this.open(DuiDialogAlert, {title, content}, dialodInputs); return dialog.toPromise(); } public async confirm(title: string, content?: string, dialodInputs: { [name: string]: any } = {}): Promise { const {dialog} = this.open(DuiDialogConfirm, {title, content}, dialodInputs); return dialog.toPromise(); } public async prompt(title: string, value: string, content?: string, dialodInputs: { [name: string]: any } = {}): Promise { const {dialog} = this.open(DuiDialogPrompt, {title, value, content}, dialodInputs); return dialog.toPromise(); } public progress(): ProgressDialogState { const state$ = new ProgressDialogState; this.open(DuiDialogProgress, {state$}); return state$; } } @Directive({ selector: '[confirm]', }) export class DuiDialogConfirmDirective implements OnDestroy { @Input() confirm!: string; ignoreNextClick = false; callback = async (event: MouseEvent) => { if (isTargetChildOf(event.target, this.element.nativeElement)) { if (this.ignoreNextClick) { this.ignoreNextClick = false; return; } event.stopPropagation(); event.preventDefault(); const [title, text] = this.confirm.split('\n'); const a = await this.dialog.confirm(title, text, {}); if (a) { this.ignoreNextClick = true; this.element.nativeElement.dispatchEvent(event); } this.cd.detectChanges(); } }; constructor( protected element: ElementRef, protected dialog: DuiDialog, protected cd: ChangeDetectorRef, @Inject(DOCUMENT) protected document: any, ) { this.document.body!.addEventListener('click', this.callback, true); } ngOnDestroy() { this.document.body!.removeEventListener('click', this.callback, true); } }