src/app/core/common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component.ts
import {
  Component,
  inject,
  ChangeDetectionStrategy,
  signal,
  computed,
} from "@angular/core";
import {
  MAT_DIALOG_DATA,
  MatDialogModule,
  MatDialogRef,
} from "@angular/material/dialog";
import { DialogCloseComponent } from "../../dialog-close/dialog-close.component";
import { MatButtonModule } from "@angular/material/button";
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
import { MarkdownComponent } from "ngx-markdown";

/**
 * A configurable confirmation dialog box
 * used by the {@link ConfirmationDialogService}.
 */
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-confirmation-dialog",
  templateUrl: "./confirmation-dialog.component.html",
  styleUrl: "./confirmation-dialog.component.scss",
  imports: [
    DialogCloseComponent,
    MatDialogModule,
    MatButtonModule,
    MatFormFieldModule,
    MatInputModule,
    MarkdownComponent,
  ],
})
export class ConfirmationDialogComponent {
  dialogRef = inject<MatDialogRef<ConfirmationDialogComponent>>(MatDialogRef);
  data = inject<ConfirmationDialogConfig>(MAT_DIALOG_DATA);

  /** what the user has typed into the confirmation input (if a keyword is required) */
  typedConfirmation = signal("");

  /** whether the required keyword has been entered correctly */
  private readonly keywordEntered = computed(() => {
    const keyword = this.data.confirmationKeyword;
    return (
      !keyword ||
      this.typedConfirmation().trim().toLowerCase() === keyword.toLowerCase()
    );
  });

  /**
   * Confirming buttons stay disabled until the required keyword has been typed,
   * while buttons that abort the action (e.g. "Cancel") remain available.
   */
  isBlocked(button: ConfirmationDialogButton): boolean {
    return !!button.dialogResult && !this.keywordEntered();
  }
}

/**
 * Options to configure the {@link ConfirmationDialogComponent}.
 */
export interface ConfirmationDialogConfig {
  /** title of the dialog box */
  title: string;

  /** description text in the dialog box */
  text: string;

  /** The buttons that should be displayed */
  buttons: ConfirmationDialogButton[];

  /** Whether or not to specify a 'close' icon-button.
   * This button is on the top-right of the dialog and closes it with no result
   */
  closeButton?: boolean;

  /**
   * If set, the user has to type this keyword into an input field
   * before the confirming buttons become available.
   *
   * Use this as an additional safeguard for critical, irreversible actions.
   */
  confirmationKeyword?: string;
}

/**
 * The keyword a user has to type to confirm an action that deletes data irreversibly.
 */
export const DELETE_CONFIRMATION_KEYWORD = $localize`:Keyword to be typed by the user to confirm deleting data:delete`;

export interface ConfirmationDialogButton {
  text: string;
  dialogResult?: boolean | string | undefined;
  click();
}

export const OkButton: ConfirmationDialogButton[] = [
  {
    text: $localize`:Confirmation dialog OK:OK`,
    click() {
      // Intentionally blank
      // To react to emissions from this button, use the `MatDialogRef.beforeClosed()` hook
    },
    dialogResult: true,
  },
];

export const YesNoButtons: ConfirmationDialogButton[] = [
  {
    text: $localize`:Confirmation dialog Yes:Yes`,
    click() {
      // Intentionally blank
      // To react to emissions from this button, use the `MatDialogRef.beforeClosed()` hook
    },
    dialogResult: true,
  },
  {
    text: $localize`:Confirmation dialog No:No`,
    click() {
      // Intentionally blank
      // To react to emissions from this button, use the `MatDialogRef.beforeClosed()` hook
    },
    dialogResult: false,
  },
];

export const YesNoCancelButtons: ConfirmationDialogButton[] = [
  {
    text: $localize`:Confirmation dialog Yes:Yes`,
    click() {
      // Intentionally blank
      // To react to emissions from this button, use the `MatDialogRef.beforeClosed()` hook
    },
    dialogResult: true,
  },
  {
    text: $localize`:Confirmation dialog No:No`,
    click() {
      // Intentionally blank
      // To react to emissions from this button, use the `MatDialogRef.beforeClosed()` hook
    },
    dialogResult: false,
  },
  {
    text: $localize`:Confirmation dialog Cancel:Cancel`,
    click() {
      // Intentionally blank
      // To react to emissions from this button, use the `MatDialogRef.beforeClosed()` hook
    },
    dialogResult: undefined,
  },
];

export function CustomYesNoButtons(
  yesLabel: string,
  noLabel: string,
): ConfirmationDialogButton[] {
  return [
    { text: yesLabel, dialogResult: true, click() {} },
    { text: noLabel, dialogResult: false, click() {} },
  ];
}

results matching ""

    No results matching ""