import { ChangeDetectionStrategy, Component, HostListener, Inject, TemplateRef } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { TranslateService } from '@ngx-translate/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; export type TitleColor = 'default' | 'warn'; export enum TitleColors { DEFAULT = 'default', WARN = 'warn', } export enum ConfirmOptions { CONFIRM = 1, SECOND_CONFIRM = 2, DISCARD_CHANGES = 3, } interface CheckBox { value: boolean; label: string; extraContent?: TemplateRef; extraContentData?: Record; } export class ConfirmationDialogInput { title?: string; titleColor?: TitleColor; question?: string; details?: string; confirmationText?: string; alternativeConfirmationText?: string; discardChangesText?: string; requireInput?: boolean; disableConfirm?: boolean; denyText?: string; translateParams?: Record; checkboxes?: CheckBox[]; toastMessage?: string; constructor(options?: ConfirmationDialogInput) { this.title = options?.title || _('common.confirmation-dialog.title'); this.titleColor = options?.titleColor || TitleColors.DEFAULT; this.question = options?.question || _('common.confirmation-dialog.description'); this.details = options?.details || ''; this.confirmationText = options?.confirmationText || _('common.confirmation-dialog.confirm'); this.alternativeConfirmationText = options?.alternativeConfirmationText; this.discardChangesText = options?.discardChangesText; this.requireInput = options?.requireInput || false; this.disableConfirm = options?.disableConfirm || false; this.denyText = options?.denyText || _('common.confirmation-dialog.deny'); this.translateParams = options?.translateParams || {}; this.checkboxes = options?.checkboxes || []; this.toastMessage = options?.toastMessage; } } @Component({ templateUrl: './confirmation-dialog.component.html', styleUrls: ['./confirmation-dialog.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class ConfirmationDialogComponent { config: ConfirmationDialogInput; inputValue = ''; showToast = false; readonly inputLabel: string; readonly ConfirmOptions = ConfirmOptions; constructor( private readonly _dialogRef: MatDialogRef, private readonly _translateService: TranslateService, @Inject(MAT_DIALOG_DATA) private readonly _confirmationDialogInput: ConfirmationDialogInput, ) { this.config = _confirmationDialogInput ?? new ConfirmationDialogInput(); this.translate(this.config); this.inputLabel = `${this._translateService.instant('confirmation-dialog.input-label')} '${this.config.confirmationText || ''}'`; } get uncheckedBoxes(): boolean { return !!this.config.checkboxes?.some(c => !c.value); } get isDeleteAction(): boolean { return this.config?.titleColor === TitleColors.WARN; } @HostListener('window:keyup.enter') onKeyupEnter(): void { if (this.config.requireInput && !this.confirmationDoesNotMatch()) { this.confirm(1); } } confirmationDoesNotMatch(): boolean { return this.inputValue.toLowerCase() !== this.config.confirmationText?.toLowerCase(); } deny(): void { this._dialogRef.close(); } confirm(option: ConfirmOptions): void { if (this.uncheckedBoxes) { this.showToast = true; } else { this._dialogRef.close(option); } } translate(obj: ConfirmationDialogInput): void { const translateKeys: (keyof typeof obj)[] = [ 'title', 'question', 'details', 'confirmationText', 'alternativeConfirmationText', 'discardChangesText', 'denyText', ]; translateKeys .filter(key => !!obj[key]) .forEach(key => { Object.assign(obj, { [key]: this._translateService.instant(obj[key] as string, this.config.translateParams) as string, }); }); } }