common-ui/src/lib/misc/confirmation-dialog/confirmation-dialog.component.ts
2022-06-21 11:36:21 +03:00

131 lines
4.3 KiB
TypeScript

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<unknown>;
extraContentData?: Record<string, unknown>;
}
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<string, unknown>;
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<ConfirmationDialogComponent>,
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,
});
});
}
}