import { Injectable } from '@angular/core'; import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog'; import { ComponentType } from '@angular/cdk/portal'; import { mergeMap } from 'rxjs/operators'; import { from } from 'rxjs'; export const largeDialogConfig: MatDialogConfig = { width: '90vw', maxWidth: '90vw', maxHeight: '90vh', autoFocus: false, } as const; export const defaultDialogConfig: MatDialogConfig = { width: '662px', maxWidth: '90vw', maxHeight: '90vh', autoFocus: false, } as const; export type DialogConfig = { [key in T]: { component: ComponentType; dialogConfig?: MatDialogConfig; }; }; @Injectable() export abstract class DialogService { protected abstract readonly _config: DialogConfig; protected constructor(protected readonly _dialog: MatDialog) {} openDialog( type: T, $event: MouseEvent, data: unknown, cb?: (...params: unknown[]) => Promise | unknown, finallyCb?: (...params: unknown[]) => unknown | Promise, ): MatDialogRef { const config = this._config[type]; $event?.stopPropagation(); const ref = this._dialog.open(config.component, { ...defaultDialogConfig, ...(config.dialogConfig || {}), data, }); const fn = async result => { if (result && cb) { await cb(result); } if (finallyCb) { await finallyCb(result); } }; ref.afterClosed() .pipe(mergeMap(result => from(fn(result)))) .subscribe(); return ref; } }