96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
import { Directive, HostListener, inject, OnDestroy } from '@angular/core';
|
|
import { MatLegacyDialog as MatDialog, MatLegacyDialogRef as MatDialogRef } from '@angular/material/legacy-dialog';
|
|
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
|
import { hasFormChanged, IqserEventTarget } from '../utils';
|
|
import { ConfirmOptions } from '.';
|
|
import { ConfirmationDialogService } from './confirmation-dialog.service';
|
|
import { firstValueFrom } from 'rxjs';
|
|
import { LoadingService } from '../loading';
|
|
import { Toaster } from '../services';
|
|
import { IconButtonTypes } from '../buttons';
|
|
|
|
const TARGET_NODE = 'mat-dialog-container';
|
|
|
|
export interface SaveOptions {
|
|
closeAfterSave?: boolean;
|
|
addMembers?: boolean;
|
|
}
|
|
|
|
@Directive()
|
|
export abstract class BaseDialogComponent implements OnDestroy {
|
|
readonly iconButtonTypes = IconButtonTypes;
|
|
form?: UntypedFormGroup;
|
|
initialFormValue!: Record<string, string>;
|
|
protected readonly _formBuilder = inject(UntypedFormBuilder);
|
|
protected readonly _loadingService = inject(LoadingService);
|
|
protected readonly _toaster = inject(Toaster);
|
|
readonly #confirmationDialogService = inject(ConfirmationDialogService);
|
|
readonly #dialog = inject(MatDialog);
|
|
#hasErrors = false;
|
|
#backdropClickSubscription = this._dialogRef.backdropClick().subscribe(() => {
|
|
this.close();
|
|
});
|
|
|
|
protected constructor(protected readonly _dialogRef: MatDialogRef<BaseDialogComponent>, private readonly _isInEditMode?: boolean) {}
|
|
|
|
get valid(): boolean {
|
|
return !this.form || this.form.valid;
|
|
}
|
|
|
|
get changed(): boolean {
|
|
return !this.form || hasFormChanged(this.form, this.initialFormValue);
|
|
}
|
|
|
|
get disabled(): boolean {
|
|
return !this.valid || !this.changed || this.#hasErrors;
|
|
}
|
|
|
|
abstract save(options?: SaveOptions): void;
|
|
|
|
ngOnDestroy(): void {
|
|
this.#backdropClickSubscription.unsubscribe();
|
|
}
|
|
|
|
close(): void {
|
|
if (this._isInEditMode && this.changed) {
|
|
this._openConfirmDialog().then(result => {
|
|
if (result in ConfirmOptions) {
|
|
if (result === ConfirmOptions.CONFIRM) {
|
|
this.save({ closeAfterSave: true });
|
|
} else {
|
|
this._dialogRef.close();
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
this._dialogRef.close();
|
|
}
|
|
}
|
|
|
|
@HostListener('window:keydown.Enter', ['$event'])
|
|
onEnter(event: KeyboardEvent): void {
|
|
event?.stopImmediatePropagation();
|
|
const node = (event.target as IqserEventTarget).localName?.trim()?.toLowerCase();
|
|
if (this.valid && !this.disabled && this.changed && node === TARGET_NODE) {
|
|
this.save();
|
|
}
|
|
}
|
|
|
|
@HostListener('window:keydown.Escape', ['$event'])
|
|
onEscape(): void {
|
|
if (this.#dialog.openDialogs.length === 1) {
|
|
this.close();
|
|
}
|
|
}
|
|
|
|
@HostListener('window:keyup', ['$event'])
|
|
onKeyUp(): void {
|
|
this.#hasErrors = !!document.getElementsByClassName('ng-invalid')[0];
|
|
}
|
|
|
|
protected _openConfirmDialog() {
|
|
const dialogRef = this.#confirmationDialogService.openDialog({ disableConfirm: !this.valid });
|
|
return firstValueFrom(dialogRef.afterClosed());
|
|
}
|
|
}
|