RED-9578: added support for custom component and reversing buttons.

This commit is contained in:
Nicoleta Panaghiu 2024-09-19 14:52:04 +03:00
parent c644eaeba2
commit c71a4995a6
3 changed files with 76 additions and 26 deletions

View File

@ -16,6 +16,10 @@
<p [innerHTML]="config.details" class="mt-0"></p> <p [innerHTML]="config.details" class="mt-0"></p>
} }
@if (config.component) {
<ng-container #detailsComponent></ng-container>
}
@if (config.requireInput) { @if (config.requireInput) {
<div class="iqser-input-group required w-300 mt-24"> <div class="iqser-input-group required w-300 mt-24">
<label>{{ inputLabel }}</label> <label>{{ inputLabel }}</label>
@ -35,14 +39,20 @@
} }
</div> </div>
<div class="dialog-actions"> <div class="dialog-actions" [class.reverse]="config.cancelButtonPrimary">
<iqser-icon-button @if (!config.cancelButtonPrimary) {
(action)="confirm(confirmOption)" <iqser-icon-button
[disabled]="(config.requireInput && confirmationDoesNotMatch()) || config.disableConfirm" (action)="confirm(confirmOption)"
[label]="config.confirmationText" [disabled]="(config.requireInput && confirmationDoesNotMatch()) || config.disableConfirm"
[type]="iconButtonTypes.primary" [label]="config.confirmationText"
buttonId="confirm" [type]="iconButtonTypes.primary"
></iqser-icon-button> buttonId="confirm"
></iqser-icon-button>
} @else {
<div (click)="confirm(confirmOption)" class="all-caps-label cancel no-uppercase" id="confirm">
{{ config.confirmationText }}
</div>
}
@if (config.alternativeConfirmationText) { @if (config.alternativeConfirmationText) {
<iqser-icon-button <iqser-icon-button
@ -60,9 +70,13 @@
} }
@if (!config.discardChangesText) { @if (!config.discardChangesText) {
<div (click)="deny()" class="all-caps-label cancel"> @if (config.cancelButtonPrimary) {
{{ config.denyText }} <iqser-icon-button (click)="deny()" [label]="config.denyText" [type]="iconButtonTypes.primary"></iqser-icon-button>
</div> } @else {
<div (click)="deny()" class="all-caps-label cancel">
{{ config.denyText }}
</div>
}
} }
</div> </div>

View File

@ -6,3 +6,12 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.reverse {
flex-direction: row-reverse;
justify-content: flex-end;
}
.no-uppercase {
text-transform: unset;
}

View File

@ -1,15 +1,24 @@
import { NgTemplateOutlet } from '@angular/common'; import { NgClass, NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, HostListener, inject, TemplateRef } from '@angular/core'; import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
HostListener,
inject,
TemplateRef,
Type,
viewChild,
ViewContainerRef,
} from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatCheckboxModule } from '@angular/material/checkbox';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { CircleButtonComponent } from '../../buttons/circle-button/circle-button.component'; import { CircleButtonComponent, IconButtonTypes } from '../../buttons';
import { IconButtonComponent } from '../../buttons/icon-button/icon-button.component'; import { IconButtonComponent } from '../../buttons';
import { IconButtonTypes } from '../../buttons/types/icon-button.type'; import { ValuesOf } from '../../utils';
import { ValuesOf } from '../../utils/types/utility-types';
export const TitleColors = { export const TitleColors = {
DEFAULT: 'default', DEFAULT: 'default',
@ -48,6 +57,9 @@ interface InternalConfirmationDialogData {
readonly checkboxes: CheckBox[]; readonly checkboxes: CheckBox[];
readonly checkboxesValidation: boolean; readonly checkboxesValidation: boolean;
readonly toastMessage?: string; readonly toastMessage?: string;
readonly component?: Type<unknown>;
readonly componentInputs?: { [key: string]: unknown };
readonly cancelButtonPrimary?: boolean;
} }
export type IConfirmationDialogData = Partial<InternalConfirmationDialogData>; export type IConfirmationDialogData = Partial<InternalConfirmationDialogData>;
@ -65,6 +77,9 @@ function getConfig(options?: IConfirmationDialogData): InternalConfirmationDialo
denyText: options?.denyText ?? _('common.confirmation-dialog.deny'), denyText: options?.denyText ?? _('common.confirmation-dialog.deny'),
checkboxes: options?.checkboxes ?? [], checkboxes: options?.checkboxes ?? [],
checkboxesValidation: typeof options?.checkboxesValidation === 'boolean' ? options.checkboxesValidation : true, checkboxesValidation: typeof options?.checkboxesValidation === 'boolean' ? options.checkboxesValidation : true,
component: options?.component,
componentInputs: options?.componentInputs,
cancelButtonPrimary: options?.cancelButtonPrimary ?? false,
}; };
} }
@ -82,15 +97,17 @@ function getConfig(options?: IConfirmationDialogData): InternalConfirmationDialo
IconButtonComponent, IconButtonComponent,
CircleButtonComponent, CircleButtonComponent,
MatDialogModule, MatDialogModule,
NgClass,
], ],
}) })
export class ConfirmationDialogComponent { export class ConfirmationDialogComponent implements AfterViewInit {
readonly config = getConfig(inject(MAT_DIALOG_DATA)); readonly config = getConfig(inject(MAT_DIALOG_DATA));
inputValue = ''; inputValue = '';
showToast = false; showToast = false;
readonly inputLabel: string; readonly inputLabel: string;
readonly confirmOptions = ConfirmOptions; readonly confirmOptions = ConfirmOptions;
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
readonly detailsComponentRef = viewChild.required('detailsComponent', { read: ViewContainerRef });
constructor( constructor(
private readonly _dialogRef: MatDialogRef<ConfirmationDialogComponent, ConfirmOption>, private readonly _dialogRef: MatDialogRef<ConfirmationDialogComponent, ConfirmOption>,
@ -115,13 +132,19 @@ export class ConfirmationDialogComponent {
return ConfirmOptions.CONFIRM; return ConfirmOptions.CONFIRM;
} }
@HostListener('window:keyup.enter') @HostListener('window:keyup.enter', ['$event'])
onKeyupEnter(): void { onKeyupEnter(event: KeyboardEvent): void {
if (this.config.requireInput && !this.confirmationDoesNotMatch()) { event?.stopImmediatePropagation();
this.confirm(ConfirmOptions.CONFIRM); if (!this.config.requireInput || !this.confirmationDoesNotMatch()) {
if (!this.config.cancelButtonPrimary) this.confirm(ConfirmOptions.CONFIRM);
else this.deny();
} }
} }
ngAfterViewInit() {
this.#initializeDetailsComponent();
}
confirmationDoesNotMatch(): boolean { confirmationDoesNotMatch(): boolean {
return this.inputValue.toLowerCase() !== this.config.confirmationText.toLowerCase(); return this.inputValue.toLowerCase() !== this.config.confirmationText.toLowerCase();
} }
@ -156,9 +179,13 @@ export class ConfirmationDialogComponent {
}); });
} }
@HostListener('window:keydown.Enter', ['$event']) #initializeDetailsComponent() {
onEnter(event: KeyboardEvent): void { if (!this.config.component) return;
event?.stopImmediatePropagation(); const component = this.detailsComponentRef().createComponent(this.config.component);
this.confirm(ConfirmOptions.CONFIRM); if (this.config.componentInputs) {
for (const [key, value] of Object.entries(this.config.componentInputs)) {
(component.instance as any)[key] = value;
}
}
} }
} }