@masterteam/delegations 0.0.26 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as i2 from '@angular/common';
2
2
  import { CommonModule, Location } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { input, computed, Component, inject, Injectable, ChangeDetectionStrategy, viewChild, signal, model, effect, untracked, linkedSignal } from '@angular/core';
4
+ import { input, computed, Component, inject, Injectable, ChangeDetectionStrategy, viewChild, signal, effect, model, untracked, linkedSignal } from '@angular/core';
5
5
  import { RouterLink, ActivatedRoute, Router, NavigationEnd, RouterOutlet } from '@angular/router';
6
6
  import { TranslocoDirective, TranslocoService } from '@jsverse/transloco';
7
7
  import { Avatar } from '@masterteam/components/avatar';
@@ -484,6 +484,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
484
484
  args: [{ selector: 'mt-start-session-dialog', standalone: true, imports: [CommonModule, Avatar, Button, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col gap-4 p-2\">\n <div class=\"flex items-start gap-3\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-12! h-12! text-lg! bg-surface-200!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0\">\n <div class=\"text-base font-medium text-gray-900 truncate\">\n {{ delegation().delegator.displayName }}\n </div>\n @if (delegation().scopeSummary) {\n <div class=\"text-xs text-gray-500 mt-1\">\n {{ t(\"delegations.column.scopeSummary\") }}:\n {{ formatScopeSummary(delegation().scopeSummary) }}\n </div>\n }\n </div>\n </div>\n\n <p class=\"text-sm text-gray-600 leading-relaxed\">\n {{ t(bodyKey()) }}\n </p>\n\n <div class=\"flex justify-end gap-2 pt-2 border-t border-gray-200\">\n <mt-button\n variant=\"outlined\"\n color=\"secondary\"\n [label]=\"t('delegations.common.cancel')\"\n [disabled]=\"isBusy()\"\n (click)=\"cancel()\"\n ></mt-button>\n <mt-button\n color=\"primary\"\n icon=\"user.users-check\"\n [label]=\"t(confirmLabelKey())\"\n [loading]=\"isBusy()\"\n (click)=\"confirm()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n" }]
485
485
  }], propDecorators: { delegation: [{ type: i0.Input, args: [{ isSignal: true, alias: "delegation", required: true }] }], intent: [{ type: i0.Input, args: [{ isSignal: true, alias: "intent", required: false }] }] } });
486
486
 
487
+ /**
488
+ * Post-login candidate prompt. It intentionally only lets the user choose a
489
+ * delegation; the existing StartSessionDialog still performs explicit consent.
490
+ */
491
+ class DelegationCandidatesPromptDialog {
492
+ candidates = input.required(...(ngDevMode ? [{ debugName: "candidates" }] : /* istanbul ignore next */ []));
493
+ ref = inject(ModalRef);
494
+ transloco = inject(TranslocoService);
495
+ formatScopeSummary(summary) {
496
+ return formatDelegationScopeSummary(summary, this.transloco.getActiveLang());
497
+ }
498
+ select(row) {
499
+ this.ref.close(row);
500
+ }
501
+ close() {
502
+ this.ref.close(null);
503
+ }
504
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationCandidatesPromptDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
505
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationCandidatesPromptDialog, isStandalone: true, selector: "mt-delegation-candidates-prompt-dialog", inputs: { candidates: { classPropertyName: "candidates", publicName: "candidates", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col gap-4 p-2\">\n <p class=\"text-sm leading-relaxed text-gray-600\">\n {{ t(\"delegations.session.promptBody\") }}\n </p>\n\n <div class=\"flex max-h-80 flex-col gap-2 overflow-y-auto pr-1\">\n @for (cand of candidates(); track cand.delegationId) {\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center justify-between gap-3 rounded-2xl border border-surface-200 bg-surface-0 px-3 py-3 text-start transition-colors hover:border-primary-200 hover:bg-primary-50/50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n [attr.aria-label]=\"\n t('delegations.session.promptStartAria', {\n delegatorName: cand.delegator.displayName,\n })\n \"\n (click)=\"select(cand)\"\n >\n <span class=\"flex min-w-0 items-center gap-3\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-10! h-10! text-base! bg-surface-200!\"\n ></mt-avatar>\n <span class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm font-medium text-gray-900\">\n {{ cand.delegator.displayName }}\n </span>\n @if (cand.scopeSummary) {\n @let summary = formatScopeSummary(cand.scopeSummary);\n <span\n class=\"truncate text-xs text-gray-500\"\n [title]=\"summary\"\n >\n {{ summary }}\n </span>\n }\n </span>\n </span>\n <span class=\"inline-flex items-center gap-2 text-sm text-primary\">\n {{ t(\"delegations.action.startSession\") }}\n <mt-icon icon=\"arrow.arrow-right\" class=\"text-base\"></mt-icon>\n </span>\n </button>\n }\n </div>\n\n <div class=\"flex justify-end border-t border-gray-200 pt-3\">\n <mt-button\n variant=\"outlined\"\n color=\"secondary\"\n [label]=\"t('delegations.common.close')\"\n (click)=\"close()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
506
+ }
507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationCandidatesPromptDialog, decorators: [{
508
+ type: Component,
509
+ args: [{ selector: 'mt-delegation-candidates-prompt-dialog', imports: [CommonModule, Avatar, Button, Icon, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col gap-4 p-2\">\n <p class=\"text-sm leading-relaxed text-gray-600\">\n {{ t(\"delegations.session.promptBody\") }}\n </p>\n\n <div class=\"flex max-h-80 flex-col gap-2 overflow-y-auto pr-1\">\n @for (cand of candidates(); track cand.delegationId) {\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center justify-between gap-3 rounded-2xl border border-surface-200 bg-surface-0 px-3 py-3 text-start transition-colors hover:border-primary-200 hover:bg-primary-50/50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n [attr.aria-label]=\"\n t('delegations.session.promptStartAria', {\n delegatorName: cand.delegator.displayName,\n })\n \"\n (click)=\"select(cand)\"\n >\n <span class=\"flex min-w-0 items-center gap-3\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-10! h-10! text-base! bg-surface-200!\"\n ></mt-avatar>\n <span class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm font-medium text-gray-900\">\n {{ cand.delegator.displayName }}\n </span>\n @if (cand.scopeSummary) {\n @let summary = formatScopeSummary(cand.scopeSummary);\n <span\n class=\"truncate text-xs text-gray-500\"\n [title]=\"summary\"\n >\n {{ summary }}\n </span>\n }\n </span>\n </span>\n <span class=\"inline-flex items-center gap-2 text-sm text-primary\">\n {{ t(\"delegations.action.startSession\") }}\n <mt-icon icon=\"arrow.arrow-right\" class=\"text-base\"></mt-icon>\n </span>\n </button>\n }\n </div>\n\n <div class=\"flex justify-end border-t border-gray-200 pt-3\">\n <mt-button\n variant=\"outlined\"\n color=\"secondary\"\n [label]=\"t('delegations.common.close')\"\n (click)=\"close()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n" }]
510
+ }], propDecorators: { candidates: [{ type: i0.Input, args: [{ isSignal: true, alias: "candidates", required: true }] }] } });
511
+
487
512
  /**
488
513
  * Topbar surface for the delegation runtime (doc 05, 09).
489
514
  *
@@ -497,6 +522,7 @@ class TopbarDelegationMenu {
497
522
  managePath = input('/delegations', ...(ngDevMode ? [{ debugName: "managePath" }] : /* istanbul ignore next */ []));
498
523
  compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
499
524
  showManageLink = input(true, ...(ngDevMode ? [{ debugName: "showManageLink" }] : /* istanbul ignore next */ []));
525
+ promptOnCandidates = input(true, ...(ngDevMode ? [{ debugName: "promptOnCandidates" }] : /* istanbul ignore next */ []));
500
526
  facade = inject(DelegationSessionFacade);
501
527
  modal = inject(ModalService);
502
528
  transloco = inject(TranslocoService);
@@ -506,6 +532,7 @@ class TopbarDelegationMenu {
506
532
  hasCandidates = this.facade.hasCandidates;
507
533
  onBehalfOf = this.facade.onBehalfOf;
508
534
  executedBy = this.facade.executedBy;
535
+ promptShown = signal(false, ...(ngDevMode ? [{ debugName: "promptShown" }] : /* istanbul ignore next */ []));
509
536
  mode = computed(() => {
510
537
  if (this.active())
511
538
  return 'active';
@@ -513,6 +540,20 @@ class TopbarDelegationMenu {
513
540
  return 'candidates';
514
541
  return 'hidden';
515
542
  }, ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
543
+ constructor() {
544
+ effect(() => {
545
+ const candidates = this.candidates();
546
+ const shouldPrompt = this.promptOnCandidates() &&
547
+ !this.promptShown() &&
548
+ !this.active() &&
549
+ candidates.length > 0;
550
+ if (!shouldPrompt) {
551
+ return;
552
+ }
553
+ this.promptShown.set(true);
554
+ queueMicrotask(() => this.openCandidatesPrompt(candidates));
555
+ });
556
+ }
516
557
  ngOnInit() {
517
558
  this.facade.loadCandidates();
518
559
  }
@@ -548,8 +589,22 @@ class TopbarDelegationMenu {
548
589
  inputValues: { delegation: row, intent },
549
590
  });
550
591
  }
592
+ openCandidatesPrompt(candidates) {
593
+ const ref = this.modal.openModal(DelegationCandidatesPromptDialog, 'dialog', {
594
+ header: this.transloco.translate('delegations.session.availableTitle'),
595
+ styleClass: '!w-[min(96vw,34rem)] !max-w-[96vw]',
596
+ dismissableMask: true,
597
+ dismissible: true,
598
+ inputValues: { candidates },
599
+ });
600
+ ref.onClose.subscribe((row) => {
601
+ if (row) {
602
+ this.openConfirm(row, 'start');
603
+ }
604
+ });
605
+ }
551
606
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TopbarDelegationMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
552
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TopbarDelegationMenu, isStandalone: true, selector: "mt-topbar-delegation-menu", inputs: { managePath: { classPropertyName: "managePath", publicName: "managePath", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, showManageLink: { classPropertyName: "showManageLink", publicName: "showManageLink", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n @if (mode() !== \"hidden\") {\n @if (mode() === \"active\") {\n <span class=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}.\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </span>\n }\n <div class=\"mt-delegation-trigger flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"mt-delegation-trigger__button flex min-w-0 max-w-full items-center gap-2 rounded-full px-2 py-1 hover:bg-surface-100 cursor-pointer\"\n [class.mt-delegation-trigger__button--active]=\"mode() === 'active'\"\n [attr.aria-label]=\"\n mode() === 'active'\n ? t('delegations.session.banner', {\n delegatorName: onBehalfOf()?.displayName,\n }) +\n '. ' +\n t('delegations.session.executedBy', {\n actualUserName: executedBy()?.displayName,\n })\n : t('delegations.session.availableTitle')\n \"\n [attr.title]=\"\n mode() === 'active'\n ? t('delegations.session.banner', {\n delegatorName: onBehalfOf()?.displayName,\n })\n : null\n \"\n (click)=\"togglePopover($event)\"\n >\n @if (mode() === \"active\") {\n <mt-icon\n icon=\"user.users-check\"\n styleClass=\"text-lg text-primary\"\n ></mt-icon>\n @if (!compact()) {\n <span\n class=\"mt-delegation-trigger__label flex min-w-0 flex-col text-start leading-tight\"\n >\n <span class=\"truncate text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\n </span>\n <span class=\"truncate text-[0.6875rem] font-normal text-gray-500\">\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </span>\n </span>\n }\n <mt-delegation-status-chip\n status=\"Active\"\n ></mt-delegation-status-chip>\n } @else {\n <mt-icon\n icon=\"user.users-plus\"\n styleClass=\"text-lg text-primary\"\n ></mt-icon>\n @if (!compact()) {\n <span class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{ t(\"delegations.session.availableTitle\") }}\n </span>\n }\n }\n </button>\n </div>\n\n <p-popover #popover [pt]=\"{ content: { class: 'p-0!' } }\">\n <div class=\"flex flex-col min-w-80 max-w-96 p-0\">\n @if (mode() === \"active\" && active(); as session) {\n <!-- STATE C \u2014 active session -->\n <div\n class=\"flex items-start gap-3 border-b border-gray-200 px-4 py-4\"\n >\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-11! h-11! text-xl! text-gray-600! bg-surface-300!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0 flex-1\">\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.session.actingOnBehalfOf\") }}\n </div>\n <div class=\"text-sm font-medium text-gray-900 truncate\">\n {{ onBehalfOf()?.displayName }}\n </div>\n <div class=\"text-xs text-gray-500 mt-1\">\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </div>\n @if (session.delegation.scopeSummary) {\n @let summary =\n formatScopeSummary(session.delegation.scopeSummary);\n <div\n class=\"text-xs text-gray-500 mt-1 truncate\"\n [title]=\"summary\"\n >\n {{ t(\"delegations.column.scopeSummary\") }}:\n {{ summary }}\n </div>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1 px-2 py-2\">\n <mt-button\n variant=\"text\"\n icon=\"arrow.arrow-left\"\n [label]=\"t('delegations.action.endSession')\"\n styleClass=\"w-full justify-start\"\n (click)=\"endSession($event)\"\n ></mt-button>\n </div>\n\n @if (candidates().length > 1) {\n <div class=\"border-t border-gray-200 pt-2 px-2 pb-2\">\n <div class=\"text-xs text-gray-500 px-2 pb-1\">\n {{ t(\"delegations.session.switchToAnother\") }}\n </div>\n @for (cand of candidates(); track cand.delegationId) {\n @if (cand.delegationId !== session.delegation.delegationId) {\n <button\n type=\"button\"\n class=\"flex items-center justify-between gap-2 w-full px-2 py-2 rounded-md hover:bg-surface-100 cursor-pointer\"\n [attr.aria-label]=\"\n t('delegations.action.switchSession') +\n ': ' +\n cand.delegator.displayName\n \"\n (click)=\"switchTo(cand, $event)\"\n >\n <div class=\"flex items-center gap-2 min-w-0\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-7! h-7! text-sm! bg-surface-200!\"\n ></mt-avatar>\n <span class=\"text-sm text-gray-900 truncate\">\n {{ cand.delegator.displayName }}\n </span>\n </div>\n <mt-icon\n icon=\"arrow.switch-horizontal-01\"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n </button>\n }\n }\n </div>\n }\n } @else if (mode() === \"candidates\") {\n <!-- STATE B \u2014 candidates available -->\n <div class=\"border-b border-gray-200 px-4 py-3\">\n <div class=\"text-sm font-medium text-gray-900\">\n {{ t(\"delegations.session.youCanActAs\") }}\n </div>\n <div class=\"text-xs text-gray-500 mt-1\">\n {{ t(\"delegations.session.chooseDelegatorHint\") }}\n </div>\n </div>\n <div class=\"flex flex-col gap-1 px-2 py-2 max-h-72 overflow-y-auto\">\n @for (cand of candidates(); track cand.delegationId) {\n <button\n type=\"button\"\n class=\"flex items-center justify-between gap-2 w-full px-2 py-2 rounded-md hover:bg-surface-100 cursor-pointer text-start\"\n [attr.aria-label]=\"\n t('delegations.action.startSession') +\n ': ' +\n cand.delegator.displayName\n \"\n (click)=\"start(cand, $event)\"\n >\n <div class=\"flex items-center gap-2 min-w-0 flex-1\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-9! h-9! text-base! bg-surface-200!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0\">\n <span class=\"text-sm font-medium text-gray-900 truncate\">\n {{ cand.delegator.displayName }}\n </span>\n @if (cand.scopeSummary) {\n @let summary = formatScopeSummary(cand.scopeSummary);\n <span\n class=\"text-xs text-gray-500 truncate\"\n [title]=\"summary\"\n >\n {{ summary }}\n </span>\n }\n </div>\n </div>\n <mt-icon\n icon=\"arrow.arrow-right\"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n </button>\n }\n </div>\n }\n\n <!-- Footer -->\n @if (showManageLink()) {\n <div class=\"border-t border-gray-200 px-2 py-2\">\n <a\n [routerLink]=\"managePath()\"\n (click)=\"popover().hide()\"\n class=\"flex items-center gap-2 px-3 py-2 rounded-md text-gray-700 hover:bg-surface-100 text-sm cursor-pointer\"\n >\n <mt-icon\n icon=\"general.settings-02\"\n styleClass=\"text-base\"\n ></mt-icon>\n <span>{{ t(\"delegations.session.manage\") }}</span>\n </a>\n </div>\n }\n </div>\n </p-popover>\n }\n</ng-container>\n", styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.mt-delegation-trigger{min-width:0;max-width:100%}.mt-delegation-trigger__button{transition:background-color .2s ease-out;min-width:0;max-width:100%;border:1px solid transparent}.mt-delegation-trigger__button--active{border-color:color-mix(in srgb,var(--p-primary-color, #2aaec0) 34%,transparent);background-color:color-mix(in srgb,var(--p-primary-color, #2aaec0) 10%,transparent);box-shadow:0 8px 18px #0f172a14}.mt-delegation-trigger__label{max-width:min(16rem,28vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:1200px){.mt-delegation-trigger__label{max-width:10rem}}@media(max-width:1024px){.mt-delegation-trigger__button{gap:.375rem;padding-inline:.375rem}.mt-delegation-trigger__label{display:none}}:host-context(.dark) .mt-delegation-trigger__button:hover{background-color:#94a3b826}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DelegationStatusChip, selector: "mt-delegation-status-chip", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
607
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TopbarDelegationMenu, isStandalone: true, selector: "mt-topbar-delegation-menu", inputs: { managePath: { classPropertyName: "managePath", publicName: "managePath", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, showManageLink: { classPropertyName: "showManageLink", publicName: "showManageLink", isSignal: true, isRequired: false, transformFunction: null }, promptOnCandidates: { classPropertyName: "promptOnCandidates", publicName: "promptOnCandidates", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n @if (mode() !== \"hidden\") {\n @if (mode() === \"active\") {\n <span class=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}.\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </span>\n }\n <div class=\"mt-delegation-trigger flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"mt-delegation-trigger__button flex min-w-0 max-w-full items-center gap-2 rounded-full px-2 py-1 hover:bg-surface-100 cursor-pointer\"\n [class.mt-delegation-trigger__button--active]=\"mode() === 'active'\"\n [attr.aria-label]=\"\n mode() === 'active'\n ? t('delegations.session.banner', {\n delegatorName: onBehalfOf()?.displayName,\n }) +\n '. ' +\n t('delegations.session.executedBy', {\n actualUserName: executedBy()?.displayName,\n })\n : t('delegations.session.availableTitle')\n \"\n [attr.title]=\"\n mode() === 'active'\n ? t('delegations.session.banner', {\n delegatorName: onBehalfOf()?.displayName,\n })\n : null\n \"\n (click)=\"togglePopover($event)\"\n >\n @if (mode() === \"active\") {\n <mt-icon\n icon=\"user.users-check\"\n styleClass=\"text-lg text-primary\"\n ></mt-icon>\n @if (!compact()) {\n <span\n class=\"mt-delegation-trigger__label flex min-w-0 flex-col text-start leading-tight\"\n >\n <span class=\"truncate text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\n </span>\n <span class=\"truncate text-[0.6875rem] font-normal text-gray-500\">\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </span>\n </span>\n }\n <mt-delegation-status-chip\n status=\"Active\"\n ></mt-delegation-status-chip>\n } @else {\n <mt-icon\n icon=\"user.users-plus\"\n styleClass=\"text-lg text-primary\"\n ></mt-icon>\n @if (!compact()) {\n <span class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{ t(\"delegations.session.availableTitle\") }}\n </span>\n }\n }\n </button>\n </div>\n\n <p-popover #popover [pt]=\"{ content: { class: 'p-0!' } }\">\n <div class=\"flex flex-col min-w-80 max-w-96 p-0\">\n @if (mode() === \"active\" && active(); as session) {\n <!-- STATE C \u2014 active session -->\n <div\n class=\"flex items-start gap-3 border-b border-gray-200 px-4 py-4\"\n >\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-11! h-11! text-xl! text-gray-600! bg-surface-300!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0 flex-1\">\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.session.actingOnBehalfOf\") }}\n </div>\n <div class=\"text-sm font-medium text-gray-900 truncate\">\n {{ onBehalfOf()?.displayName }}\n </div>\n <div class=\"text-xs text-gray-500 mt-1\">\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </div>\n @if (session.delegation.scopeSummary) {\n @let summary =\n formatScopeSummary(session.delegation.scopeSummary);\n <div\n class=\"text-xs text-gray-500 mt-1 truncate\"\n [title]=\"summary\"\n >\n {{ t(\"delegations.column.scopeSummary\") }}:\n {{ summary }}\n </div>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1 px-2 py-2\">\n <mt-button\n variant=\"text\"\n icon=\"arrow.arrow-left\"\n [label]=\"t('delegations.action.endSession')\"\n styleClass=\"w-full justify-start\"\n (click)=\"endSession($event)\"\n ></mt-button>\n </div>\n\n @if (candidates().length > 1) {\n <div class=\"border-t border-gray-200 pt-2 px-2 pb-2\">\n <div class=\"text-xs text-gray-500 px-2 pb-1\">\n {{ t(\"delegations.session.switchToAnother\") }}\n </div>\n @for (cand of candidates(); track cand.delegationId) {\n @if (cand.delegationId !== session.delegation.delegationId) {\n <button\n type=\"button\"\n class=\"flex items-center justify-between gap-2 w-full px-2 py-2 rounded-md hover:bg-surface-100 cursor-pointer\"\n [attr.aria-label]=\"\n t('delegations.action.switchSession') +\n ': ' +\n cand.delegator.displayName\n \"\n (click)=\"switchTo(cand, $event)\"\n >\n <div class=\"flex items-center gap-2 min-w-0\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-7! h-7! text-sm! bg-surface-200!\"\n ></mt-avatar>\n <span class=\"text-sm text-gray-900 truncate\">\n {{ cand.delegator.displayName }}\n </span>\n </div>\n <mt-icon\n icon=\"arrow.switch-horizontal-01\"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n </button>\n }\n }\n </div>\n }\n } @else if (mode() === \"candidates\") {\n <!-- STATE B \u2014 candidates available -->\n <div class=\"border-b border-gray-200 px-4 py-3\">\n <div class=\"text-sm font-medium text-gray-900\">\n {{ t(\"delegations.session.youCanActAs\") }}\n </div>\n <div class=\"text-xs text-gray-500 mt-1\">\n {{ t(\"delegations.session.chooseDelegatorHint\") }}\n </div>\n </div>\n <div class=\"flex flex-col gap-1 px-2 py-2 max-h-72 overflow-y-auto\">\n @for (cand of candidates(); track cand.delegationId) {\n <button\n type=\"button\"\n class=\"flex items-center justify-between gap-2 w-full px-2 py-2 rounded-md hover:bg-surface-100 cursor-pointer text-start\"\n [attr.aria-label]=\"\n t('delegations.action.startSession') +\n ': ' +\n cand.delegator.displayName\n \"\n (click)=\"start(cand, $event)\"\n >\n <div class=\"flex items-center gap-2 min-w-0 flex-1\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-9! h-9! text-base! bg-surface-200!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0\">\n <span class=\"text-sm font-medium text-gray-900 truncate\">\n {{ cand.delegator.displayName }}\n </span>\n @if (cand.scopeSummary) {\n @let summary = formatScopeSummary(cand.scopeSummary);\n <span\n class=\"text-xs text-gray-500 truncate\"\n [title]=\"summary\"\n >\n {{ summary }}\n </span>\n }\n </div>\n </div>\n <mt-icon\n icon=\"arrow.arrow-right\"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n </button>\n }\n </div>\n }\n\n <!-- Footer -->\n @if (showManageLink()) {\n <div class=\"border-t border-gray-200 px-2 py-2\">\n <a\n [routerLink]=\"managePath()\"\n (click)=\"popover().hide()\"\n class=\"flex items-center gap-2 px-3 py-2 rounded-md text-gray-700 hover:bg-surface-100 text-sm cursor-pointer\"\n >\n <mt-icon\n icon=\"general.settings-02\"\n styleClass=\"text-base\"\n ></mt-icon>\n <span>{{ t(\"delegations.session.manage\") }}</span>\n </a>\n </div>\n }\n </div>\n </p-popover>\n }\n</ng-container>\n", styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.mt-delegation-trigger{min-width:0;max-width:100%}.mt-delegation-trigger__button{transition:background-color .2s ease-out;min-width:0;max-width:100%;border:1px solid transparent}.mt-delegation-trigger__button--active{border-color:color-mix(in srgb,var(--p-primary-color, #2aaec0) 34%,transparent);background-color:color-mix(in srgb,var(--p-primary-color, #2aaec0) 10%,transparent);box-shadow:0 8px 18px #0f172a14}.mt-delegation-trigger__label{max-width:min(16rem,28vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:1200px){.mt-delegation-trigger__label{max-width:10rem}}@media(max-width:1024px){.mt-delegation-trigger__button{gap:.375rem;padding-inline:.375rem}.mt-delegation-trigger__label{display:none}}:host-context(.dark) .mt-delegation-trigger__button:hover{background-color:#94a3b826}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DelegationStatusChip, selector: "mt-delegation-status-chip", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
553
608
  }
554
609
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TopbarDelegationMenu, decorators: [{
555
610
  type: Component,
@@ -563,7 +618,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
563
618
  TranslocoDirective,
564
619
  DelegationStatusChip,
565
620
  ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n @if (mode() !== \"hidden\") {\n @if (mode() === \"active\") {\n <span class=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}.\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </span>\n }\n <div class=\"mt-delegation-trigger flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"mt-delegation-trigger__button flex min-w-0 max-w-full items-center gap-2 rounded-full px-2 py-1 hover:bg-surface-100 cursor-pointer\"\n [class.mt-delegation-trigger__button--active]=\"mode() === 'active'\"\n [attr.aria-label]=\"\n mode() === 'active'\n ? t('delegations.session.banner', {\n delegatorName: onBehalfOf()?.displayName,\n }) +\n '. ' +\n t('delegations.session.executedBy', {\n actualUserName: executedBy()?.displayName,\n })\n : t('delegations.session.availableTitle')\n \"\n [attr.title]=\"\n mode() === 'active'\n ? t('delegations.session.banner', {\n delegatorName: onBehalfOf()?.displayName,\n })\n : null\n \"\n (click)=\"togglePopover($event)\"\n >\n @if (mode() === \"active\") {\n <mt-icon\n icon=\"user.users-check\"\n styleClass=\"text-lg text-primary\"\n ></mt-icon>\n @if (!compact()) {\n <span\n class=\"mt-delegation-trigger__label flex min-w-0 flex-col text-start leading-tight\"\n >\n <span class=\"truncate text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\n </span>\n <span class=\"truncate text-[0.6875rem] font-normal text-gray-500\">\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </span>\n </span>\n }\n <mt-delegation-status-chip\n status=\"Active\"\n ></mt-delegation-status-chip>\n } @else {\n <mt-icon\n icon=\"user.users-plus\"\n styleClass=\"text-lg text-primary\"\n ></mt-icon>\n @if (!compact()) {\n <span class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{ t(\"delegations.session.availableTitle\") }}\n </span>\n }\n }\n </button>\n </div>\n\n <p-popover #popover [pt]=\"{ content: { class: 'p-0!' } }\">\n <div class=\"flex flex-col min-w-80 max-w-96 p-0\">\n @if (mode() === \"active\" && active(); as session) {\n <!-- STATE C \u2014 active session -->\n <div\n class=\"flex items-start gap-3 border-b border-gray-200 px-4 py-4\"\n >\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-11! h-11! text-xl! text-gray-600! bg-surface-300!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0 flex-1\">\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.session.actingOnBehalfOf\") }}\n </div>\n <div class=\"text-sm font-medium text-gray-900 truncate\">\n {{ onBehalfOf()?.displayName }}\n </div>\n <div class=\"text-xs text-gray-500 mt-1\">\n {{\n t(\"delegations.session.executedBy\", {\n actualUserName: executedBy()?.displayName,\n })\n }}\n </div>\n @if (session.delegation.scopeSummary) {\n @let summary =\n formatScopeSummary(session.delegation.scopeSummary);\n <div\n class=\"text-xs text-gray-500 mt-1 truncate\"\n [title]=\"summary\"\n >\n {{ t(\"delegations.column.scopeSummary\") }}:\n {{ summary }}\n </div>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1 px-2 py-2\">\n <mt-button\n variant=\"text\"\n icon=\"arrow.arrow-left\"\n [label]=\"t('delegations.action.endSession')\"\n styleClass=\"w-full justify-start\"\n (click)=\"endSession($event)\"\n ></mt-button>\n </div>\n\n @if (candidates().length > 1) {\n <div class=\"border-t border-gray-200 pt-2 px-2 pb-2\">\n <div class=\"text-xs text-gray-500 px-2 pb-1\">\n {{ t(\"delegations.session.switchToAnother\") }}\n </div>\n @for (cand of candidates(); track cand.delegationId) {\n @if (cand.delegationId !== session.delegation.delegationId) {\n <button\n type=\"button\"\n class=\"flex items-center justify-between gap-2 w-full px-2 py-2 rounded-md hover:bg-surface-100 cursor-pointer\"\n [attr.aria-label]=\"\n t('delegations.action.switchSession') +\n ': ' +\n cand.delegator.displayName\n \"\n (click)=\"switchTo(cand, $event)\"\n >\n <div class=\"flex items-center gap-2 min-w-0\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-7! h-7! text-sm! bg-surface-200!\"\n ></mt-avatar>\n <span class=\"text-sm text-gray-900 truncate\">\n {{ cand.delegator.displayName }}\n </span>\n </div>\n <mt-icon\n icon=\"arrow.switch-horizontal-01\"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n </button>\n }\n }\n </div>\n }\n } @else if (mode() === \"candidates\") {\n <!-- STATE B \u2014 candidates available -->\n <div class=\"border-b border-gray-200 px-4 py-3\">\n <div class=\"text-sm font-medium text-gray-900\">\n {{ t(\"delegations.session.youCanActAs\") }}\n </div>\n <div class=\"text-xs text-gray-500 mt-1\">\n {{ t(\"delegations.session.chooseDelegatorHint\") }}\n </div>\n </div>\n <div class=\"flex flex-col gap-1 px-2 py-2 max-h-72 overflow-y-auto\">\n @for (cand of candidates(); track cand.delegationId) {\n <button\n type=\"button\"\n class=\"flex items-center justify-between gap-2 w-full px-2 py-2 rounded-md hover:bg-surface-100 cursor-pointer text-start\"\n [attr.aria-label]=\"\n t('delegations.action.startSession') +\n ': ' +\n cand.delegator.displayName\n \"\n (click)=\"start(cand, $event)\"\n >\n <div class=\"flex items-center gap-2 min-w-0 flex-1\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-9! h-9! text-base! bg-surface-200!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0\">\n <span class=\"text-sm font-medium text-gray-900 truncate\">\n {{ cand.delegator.displayName }}\n </span>\n @if (cand.scopeSummary) {\n @let summary = formatScopeSummary(cand.scopeSummary);\n <span\n class=\"text-xs text-gray-500 truncate\"\n [title]=\"summary\"\n >\n {{ summary }}\n </span>\n }\n </div>\n </div>\n <mt-icon\n icon=\"arrow.arrow-right\"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n </button>\n }\n </div>\n }\n\n <!-- Footer -->\n @if (showManageLink()) {\n <div class=\"border-t border-gray-200 px-2 py-2\">\n <a\n [routerLink]=\"managePath()\"\n (click)=\"popover().hide()\"\n class=\"flex items-center gap-2 px-3 py-2 rounded-md text-gray-700 hover:bg-surface-100 text-sm cursor-pointer\"\n >\n <mt-icon\n icon=\"general.settings-02\"\n styleClass=\"text-base\"\n ></mt-icon>\n <span>{{ t(\"delegations.session.manage\") }}</span>\n </a>\n </div>\n }\n </div>\n </p-popover>\n }\n</ng-container>\n", styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.mt-delegation-trigger{min-width:0;max-width:100%}.mt-delegation-trigger__button{transition:background-color .2s ease-out;min-width:0;max-width:100%;border:1px solid transparent}.mt-delegation-trigger__button--active{border-color:color-mix(in srgb,var(--p-primary-color, #2aaec0) 34%,transparent);background-color:color-mix(in srgb,var(--p-primary-color, #2aaec0) 10%,transparent);box-shadow:0 8px 18px #0f172a14}.mt-delegation-trigger__label{max-width:min(16rem,28vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:1200px){.mt-delegation-trigger__label{max-width:10rem}}@media(max-width:1024px){.mt-delegation-trigger__button{gap:.375rem;padding-inline:.375rem}.mt-delegation-trigger__label{display:none}}:host-context(.dark) .mt-delegation-trigger__button:hover{background-color:#94a3b826}\n"] }]
566
- }], propDecorators: { managePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "managePath", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], showManageLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "showManageLink", required: false }] }], popover: [{ type: i0.ViewChild, args: ['popover', { isSignal: true }] }] } });
621
+ }], ctorParameters: () => [], propDecorators: { managePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "managePath", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], showManageLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "showManageLink", required: false }] }], promptOnCandidates: [{ type: i0.Input, args: [{ isSignal: true, alias: "promptOnCandidates", required: false }] }], popover: [{ type: i0.ViewChild, args: ['popover', { isSignal: true }] }] } });
567
622
 
568
623
  // ---------------------------------------------------------------------------
569
624
  // Lists / detail
@@ -2259,6 +2314,10 @@ class DelegationsList {
2259
2314
  assignedDecisionTab = input(false, ...(ngDevMode ? [{ debugName: "assignedDecisionTab" }] : /* istanbul ignore next */ []));
2260
2315
  assignedEmptyStateKey = input('delegations.empty.assigned', ...(ngDevMode ? [{ debugName: "assignedEmptyStateKey" }] : /* istanbul ignore next */ []));
2261
2316
  assignedStatus = input(null, ...(ngDevMode ? [{ debugName: "assignedStatus" }] : /* istanbul ignore next */ []));
2317
+ showApprovalTab = input(true, ...(ngDevMode ? [{ debugName: "showApprovalTab" }] : /* istanbul ignore next */ []));
2318
+ approvalTabLabelKey = input('delegations.tabs.approvals', ...(ngDevMode ? [{ debugName: "approvalTabLabelKey" }] : /* istanbul ignore next */ []));
2319
+ approvalEmptyStateKey = input('delegations.empty.pending', ...(ngDevMode ? [{ debugName: "approvalEmptyStateKey" }] : /* istanbul ignore next */ []));
2320
+ approvalStatus = input('PendingApproval', ...(ngDevMode ? [{ debugName: "approvalStatus" }] : /* istanbul ignore next */ []));
2262
2321
  facade = inject(DelegationsFacade);
2263
2322
  location = inject(Location);
2264
2323
  modal = inject(ModalService);
@@ -2279,25 +2338,32 @@ class DelegationsList {
2279
2338
  ], ...(ngDevMode ? [{ debugName: "breadcrumbItems" }] : /* istanbul ignore next */ []));
2280
2339
  activeTab = signal('my', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
2281
2340
  surfaceTitle = computed(() => this.transloco.translate(this.surfaceTitleKey()), ...(ngDevMode ? [{ debugName: "surfaceTitle" }] : /* istanbul ignore next */ []));
2282
- tabs = computed(() => [
2283
- {
2284
- value: 'my',
2285
- label: this.transloco.translate('delegations.myDelegations'),
2286
- },
2287
- {
2288
- value: 'assigned',
2289
- label: this.assignedDecisionTab()
2290
- ? `${this.transloco.translate('delegations.action.approve')} / ${this.transloco.translate('delegations.action.reject')}`
2291
- : this.transloco.translate(this.assignedTabLabelKey()),
2292
- },
2293
- ], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
2341
+ tabs = computed(() => {
2342
+ const tabs = [
2343
+ {
2344
+ value: 'my',
2345
+ label: this.transloco.translate('delegations.myDelegations'),
2346
+ },
2347
+ {
2348
+ value: 'assigned',
2349
+ label: this.assignedDecisionTab()
2350
+ ? `${this.transloco.translate('delegations.action.approve')} / ${this.transloco.translate('delegations.action.reject')}`
2351
+ : this.transloco.translate(this.assignedTabLabelKey()),
2352
+ },
2353
+ ];
2354
+ if (this.showApprovalTab()) {
2355
+ tabs.push({
2356
+ value: 'approvals',
2357
+ label: this.transloco.translate(this.approvalTabLabelKey()),
2358
+ });
2359
+ }
2360
+ return tabs;
2361
+ }, ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
2294
2362
  isLoading = computed(() => this.adminMode()
2295
2363
  ? this.facade.isLoadingAdmin()
2296
2364
  : this.activeTab() === 'my'
2297
2365
  ? this.facade.isLoadingMy()
2298
2366
  : this.facade.isLoadingAssigned(), ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
2299
- isLoadingScopeOptions = this.facade.isLoadingScopeOptions;
2300
- scopeOptions = this.facade.scopeOptions;
2301
2367
  rows = computed(() => this.adminMode()
2302
2368
  ? this.facade.adminItems()
2303
2369
  : this.activeTab() === 'my'
@@ -2307,30 +2373,22 @@ class DelegationsList {
2307
2373
  ? 'components.table.no-data-found'
2308
2374
  : this.activeTab() === 'my'
2309
2375
  ? 'delegations.empty.my'
2310
- : this.assignedEmptyStateKey(), ...(ngDevMode ? [{ debugName: "emptyStateKey" }] : /* istanbul ignore next */ []));
2376
+ : this.activeTab() === 'approvals'
2377
+ ? this.approvalEmptyStateKey()
2378
+ : this.assignedEmptyStateKey(), ...(ngDevMode ? [{ debugName: "emptyStateKey" }] : /* istanbul ignore next */ []));
2311
2379
  statusCol = viewChild.required('statusCol');
2312
2380
  userCol = viewChild.required('userCol');
2313
2381
  delegatorCol = viewChild.required('delegatorCol');
2314
2382
  delegatedUserCol = viewChild.required('delegatedUserCol');
2315
- scopeCol = viewChild.required('scopeCol');
2316
2383
  daysCol = viewChild.required('daysCol');
2317
- canCreate = computed(() => {
2318
- if (this.adminMode())
2319
- return true;
2320
- if (this.isLoadingScopeOptions())
2321
- return false;
2322
- return hasDelegationGrantableScope(this.scopeOptions());
2323
- }, ...(ngDevMode ? [{ debugName: "canCreate" }] : /* istanbul ignore next */ []));
2324
- tableActions = computed(() => this.canCreate()
2325
- ? [
2326
- {
2327
- icon: 'general.plus',
2328
- label: this.transloco.translate('delegations.action.create'),
2329
- color: 'primary',
2330
- action: () => this.openForm(null),
2331
- },
2332
- ]
2333
- : [], ...(ngDevMode ? [{ debugName: "tableActions" }] : /* istanbul ignore next */ []));
2384
+ tableActions = computed(() => [
2385
+ {
2386
+ icon: 'general.plus',
2387
+ label: this.transloco.translate('delegations.action.create'),
2388
+ color: 'primary',
2389
+ action: () => this.openForm(null),
2390
+ },
2391
+ ], ...(ngDevMode ? [{ debugName: "tableActions" }] : /* istanbul ignore next */ []));
2334
2392
  rowActions = signal([
2335
2393
  {
2336
2394
  icon: 'general.eye',
@@ -2392,13 +2450,6 @@ class DelegationsList {
2392
2450
  customCellTpl: this.statusCol(),
2393
2451
  width: '10rem',
2394
2452
  },
2395
- {
2396
- key: 'scopeSummary',
2397
- label: this.transloco.translate('delegations.column.scopeSummary'),
2398
- type: 'custom',
2399
- customCellTpl: this.scopeCol(),
2400
- width: '18rem',
2401
- },
2402
2453
  {
2403
2454
  key: 'startsAtUtc',
2404
2455
  label: this.transloco.translate('delegations.column.startDate'),
@@ -2468,9 +2519,6 @@ class DelegationsList {
2468
2519
  'saturday',
2469
2520
  ];
2470
2521
  ngOnInit() {
2471
- if (!this.adminMode()) {
2472
- this.facade.loadScopeOptions();
2473
- }
2474
2522
  this.loadCurrentTab();
2475
2523
  }
2476
2524
  switchTab(tab) {
@@ -2488,6 +2536,12 @@ class DelegationsList {
2488
2536
  if (this.activeTab() === 'my') {
2489
2537
  this.facade.getMy(query);
2490
2538
  }
2539
+ else if (this.activeTab() === 'approvals') {
2540
+ this.facade.getAssigned({
2541
+ ...query,
2542
+ status: query.status ?? this.approvalStatus(),
2543
+ });
2544
+ }
2491
2545
  else {
2492
2546
  this.facade.getAssigned({
2493
2547
  ...query,
@@ -2510,9 +2564,6 @@ class DelegationsList {
2510
2564
  }
2511
2565
  return this.transloco.translate('delegations.form.fullRange');
2512
2566
  }
2513
- formatScopeSummary(value) {
2514
- return formatDelegationScopeSummary(value, this.transloco.getActiveLang());
2515
- }
2516
2567
  getListedParty(row) {
2517
2568
  return this.activeTab() === 'my' ? row.delegatedUser : row.delegator;
2518
2569
  }
@@ -2595,7 +2646,7 @@ class DelegationsList {
2595
2646
  this.busyIds.update((ids) => on ? [...ids, key] : ids.filter((id) => id !== key));
2596
2647
  }
2597
2648
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, deps: [], target: i0.ɵɵFactoryTarget.Component });
2598
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationsList, isStandalone: true, selector: "mt-delegations-list", inputs: { showBreadcrumb: { classPropertyName: "showBreadcrumb", publicName: "showBreadcrumb", isSignal: true, isRequired: false, transformFunction: null }, showPageShell: { classPropertyName: "showPageShell", publicName: "showPageShell", isSignal: true, isRequired: false, transformFunction: null }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null }, surfaceTitleKey: { classPropertyName: "surfaceTitleKey", publicName: "surfaceTitleKey", isSignal: true, isRequired: false, transformFunction: null }, assignedTabLabelKey: { classPropertyName: "assignedTabLabelKey", publicName: "assignedTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, assignedDecisionTab: { classPropertyName: "assignedDecisionTab", publicName: "assignedDecisionTab", isSignal: true, isRequired: false, transformFunction: null }, assignedEmptyStateKey: { classPropertyName: "assignedEmptyStateKey", publicName: "assignedEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, assignedStatus: { classPropertyName: "assignedStatus", publicName: "assignedStatus", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "statusCol", first: true, predicate: ["statusCol"], descendants: true, isSignal: true }, { propertyName: "userCol", first: true, predicate: ["userCol"], descendants: true, isSignal: true }, { propertyName: "delegatorCol", first: true, predicate: ["delegatorCol"], descendants: true, isSignal: true }, { propertyName: "delegatedUserCol", first: true, predicate: ["delegatedUserCol"], descendants: true, isSignal: true }, { propertyName: "scopeCol", first: true, predicate: ["scopeCol"], descendants: true, isSignal: true }, { propertyName: "daysCol", first: true, predicate: ["daysCol"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <ng-template #tableContent>\n <div class=\"flex flex-col gap-4\">\n @if (!adminMode()) {\n <div class=\"flex items-center gap-2 border-b border-gray-200\">\n @for (tab of tabs(); track tab.value) {\n <button\n type=\"button\"\n class=\"px-4 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.value\"\n [class.text-primary]=\"activeTab() === tab.value\"\n [class.border-transparent]=\"activeTab() !== tab.value\"\n [class.text-gray-500]=\"activeTab() !== tab.value\"\n (click)=\"switchTab(tab.value)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n }\n\n <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [freezeActions]=\"true\"\n [loading]=\"isLoading()\"\n [noCard]=\"true\"\n >\n <ng-template #statusCol let-row>\n <mt-delegation-status-chip\n [status]=\"row.effectiveStatus\"\n ></mt-delegation-status-chip>\n </ng-template>\n\n <ng-template #userCol let-row>\n @let party = getListedParty(row);\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ party.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatorCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegator?.displayName }}\n </span>\n @if (row.delegator?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegator.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatedUserCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegatedUser?.displayName }}\n </span>\n @if (row.delegatedUser?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegatedUser.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #scopeCol let-row>\n @let summary = formatScopeSummary(row.scopeSummary);\n <span class=\"text-sm text-gray-700\" [title]=\"summary\">\n {{ summary || \"--\" }}\n </span>\n </ng-template>\n\n <ng-template #daysCol let-row>\n <span class=\"text-sm text-gray-700\">{{ formatDays(row) }}</span>\n </ng-template>\n\n <ng-template #empty>\n <p class=\"text-sm text-surface-500\">\n {{ t(emptyStateKey()) }}\n </p>\n </ng-template>\n </mt-table>\n </div>\n </ng-template>\n\n <ng-template #adminContent>\n <div class=\"flex min-h-full flex-col gap-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </div>\n </ng-template>\n\n @if (adminMode()) {\n @if (showPageShell()) {\n <mt-page\n [title]=\"surfaceTitle()\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-indigo-50)',\n '--p-avatar-color': 'var(--p-indigo-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n </mt-page>\n } @else {\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n }\n } @else {\n <div class=\"flex h-full flex-col gap-4 p-4\">\n <mt-card [title]=\"surfaceTitle()\">\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </mt-card>\n </div>\n }\n</ng-container>\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table .p-datatable-table{min-width:72rem}:host ::ng-deep mt-table .mt-actions-column{min-width:14rem}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}:host ::ng-deep mt-table .p-datatable-header>div,:host ::ng-deep mt-table .p-datatable-header>div>div{gap:.75rem;min-width:0;flex-wrap:wrap}:host ::ng-deep mt-table .p-datatable-header mt-tabs{display:block;max-width:100%;overflow-x:auto;padding-bottom:.25rem}:host ::ng-deep mt-table .p-datatable-header mt-text-field{display:block;flex:1 1 16rem;min-width:min(100%,16rem)}:host ::ng-deep mt-table .p-datatable-header .p-inputtext,:host ::ng-deep mt-table .p-datatable-header .p-inputwrapper,:host ::ng-deep mt-table .p-datatable-header .p-selectbutton{width:100%;max-width:100%}@media(max-width:1024px){:host ::ng-deep mt-table .p-datatable-header>div{flex-direction:column;align-items:stretch}:host ::ng-deep mt-table .p-datatable-header>div>div{width:100%;justify-content:flex-start}:host ::ng-deep mt-table .p-datatable-header mt-text-field{flex-basis:100%;min-width:0}}@media(max-width:768px){:host ::ng-deep mt-table .p-datatable-table{min-width:64rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "exportable", "printable", "groupable", "cellClickFilter", "freezeActions", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DelegationStatusChip, selector: "mt-delegation-status-chip", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2649
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationsList, isStandalone: true, selector: "mt-delegations-list", inputs: { showBreadcrumb: { classPropertyName: "showBreadcrumb", publicName: "showBreadcrumb", isSignal: true, isRequired: false, transformFunction: null }, showPageShell: { classPropertyName: "showPageShell", publicName: "showPageShell", isSignal: true, isRequired: false, transformFunction: null }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null }, surfaceTitleKey: { classPropertyName: "surfaceTitleKey", publicName: "surfaceTitleKey", isSignal: true, isRequired: false, transformFunction: null }, assignedTabLabelKey: { classPropertyName: "assignedTabLabelKey", publicName: "assignedTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, assignedDecisionTab: { classPropertyName: "assignedDecisionTab", publicName: "assignedDecisionTab", isSignal: true, isRequired: false, transformFunction: null }, assignedEmptyStateKey: { classPropertyName: "assignedEmptyStateKey", publicName: "assignedEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, assignedStatus: { classPropertyName: "assignedStatus", publicName: "assignedStatus", isSignal: true, isRequired: false, transformFunction: null }, showApprovalTab: { classPropertyName: "showApprovalTab", publicName: "showApprovalTab", isSignal: true, isRequired: false, transformFunction: null }, approvalTabLabelKey: { classPropertyName: "approvalTabLabelKey", publicName: "approvalTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, approvalEmptyStateKey: { classPropertyName: "approvalEmptyStateKey", publicName: "approvalEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, approvalStatus: { classPropertyName: "approvalStatus", publicName: "approvalStatus", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "statusCol", first: true, predicate: ["statusCol"], descendants: true, isSignal: true }, { propertyName: "userCol", first: true, predicate: ["userCol"], descendants: true, isSignal: true }, { propertyName: "delegatorCol", first: true, predicate: ["delegatorCol"], descendants: true, isSignal: true }, { propertyName: "delegatedUserCol", first: true, predicate: ["delegatedUserCol"], descendants: true, isSignal: true }, { propertyName: "daysCol", first: true, predicate: ["daysCol"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <ng-template #tableContent>\n <div class=\"flex flex-col gap-4\">\n @if (!adminMode()) {\n <div class=\"flex items-center gap-2 border-b border-gray-200\">\n @for (tab of tabs(); track tab.value) {\n <button\n type=\"button\"\n class=\"px-4 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.value\"\n [class.text-primary]=\"activeTab() === tab.value\"\n [class.border-transparent]=\"activeTab() !== tab.value\"\n [class.text-gray-500]=\"activeTab() !== tab.value\"\n (click)=\"switchTab(tab.value)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n }\n\n <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [loading]=\"isLoading()\"\n [noCard]=\"true\"\n >\n <ng-template #statusCol let-row>\n <mt-delegation-status-chip\n [status]=\"row.effectiveStatus\"\n ></mt-delegation-status-chip>\n </ng-template>\n\n <ng-template #userCol let-row>\n @let party = getListedParty(row);\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ party.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatorCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegator?.displayName }}\n </span>\n @if (row.delegator?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegator.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatedUserCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegatedUser?.displayName }}\n </span>\n @if (row.delegatedUser?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegatedUser.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #daysCol let-row>\n <span class=\"text-sm text-gray-700\">{{ formatDays(row) }}</span>\n </ng-template>\n\n <ng-template #empty>\n <p class=\"text-sm text-surface-500\">\n {{ t(emptyStateKey()) }}\n </p>\n </ng-template>\n </mt-table>\n </div>\n </ng-template>\n\n <ng-template #adminContent>\n <div class=\"flex min-h-full flex-col gap-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </div>\n </ng-template>\n\n @if (adminMode()) {\n @if (showPageShell()) {\n <mt-page\n [title]=\"surfaceTitle()\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-indigo-50)',\n '--p-avatar-color': 'var(--p-indigo-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n </mt-page>\n } @else {\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n }\n } @else {\n <div class=\"flex h-full flex-col gap-4 p-4\">\n <mt-card [title]=\"surfaceTitle()\">\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </mt-card>\n </div>\n }\n</ng-container>\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}:host ::ng-deep mt-table .p-datatable-header>div,:host ::ng-deep mt-table .p-datatable-header>div>div{gap:.75rem;min-width:0;flex-wrap:wrap}:host ::ng-deep mt-table .p-datatable-header mt-tabs{display:block;max-width:100%;overflow-x:auto;padding-bottom:.25rem}:host ::ng-deep mt-table .p-datatable-header mt-text-field{display:block;flex:1 1 16rem;min-width:min(100%,16rem)}:host ::ng-deep mt-table .p-datatable-header .p-inputtext,:host ::ng-deep mt-table .p-datatable-header .p-inputwrapper,:host ::ng-deep mt-table .p-datatable-header .p-selectbutton{width:100%;max-width:100%}@media(max-width:1024px){:host ::ng-deep mt-table .p-datatable-header>div{flex-direction:column;align-items:stretch}:host ::ng-deep mt-table .p-datatable-header>div>div{width:100%;justify-content:flex-start}:host ::ng-deep mt-table .p-datatable-header mt-text-field{flex-basis:100%;min-width:0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "exportable", "printable", "groupable", "cellClickFilter", "freezeActions", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DelegationStatusChip, selector: "mt-delegation-status-chip", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2599
2650
  }
2600
2651
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, decorators: [{
2601
2652
  type: Component,
@@ -2608,8 +2659,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
2608
2659
  Table,
2609
2660
  TranslocoDirective,
2610
2661
  DelegationStatusChip,
2611
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <ng-template #tableContent>\n <div class=\"flex flex-col gap-4\">\n @if (!adminMode()) {\n <div class=\"flex items-center gap-2 border-b border-gray-200\">\n @for (tab of tabs(); track tab.value) {\n <button\n type=\"button\"\n class=\"px-4 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.value\"\n [class.text-primary]=\"activeTab() === tab.value\"\n [class.border-transparent]=\"activeTab() !== tab.value\"\n [class.text-gray-500]=\"activeTab() !== tab.value\"\n (click)=\"switchTab(tab.value)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n }\n\n <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [freezeActions]=\"true\"\n [loading]=\"isLoading()\"\n [noCard]=\"true\"\n >\n <ng-template #statusCol let-row>\n <mt-delegation-status-chip\n [status]=\"row.effectiveStatus\"\n ></mt-delegation-status-chip>\n </ng-template>\n\n <ng-template #userCol let-row>\n @let party = getListedParty(row);\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ party.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatorCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegator?.displayName }}\n </span>\n @if (row.delegator?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegator.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatedUserCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegatedUser?.displayName }}\n </span>\n @if (row.delegatedUser?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegatedUser.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #scopeCol let-row>\n @let summary = formatScopeSummary(row.scopeSummary);\n <span class=\"text-sm text-gray-700\" [title]=\"summary\">\n {{ summary || \"--\" }}\n </span>\n </ng-template>\n\n <ng-template #daysCol let-row>\n <span class=\"text-sm text-gray-700\">{{ formatDays(row) }}</span>\n </ng-template>\n\n <ng-template #empty>\n <p class=\"text-sm text-surface-500\">\n {{ t(emptyStateKey()) }}\n </p>\n </ng-template>\n </mt-table>\n </div>\n </ng-template>\n\n <ng-template #adminContent>\n <div class=\"flex min-h-full flex-col gap-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </div>\n </ng-template>\n\n @if (adminMode()) {\n @if (showPageShell()) {\n <mt-page\n [title]=\"surfaceTitle()\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-indigo-50)',\n '--p-avatar-color': 'var(--p-indigo-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n </mt-page>\n } @else {\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n }\n } @else {\n <div class=\"flex h-full flex-col gap-4 p-4\">\n <mt-card [title]=\"surfaceTitle()\">\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </mt-card>\n </div>\n }\n</ng-container>\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table .p-datatable-table{min-width:72rem}:host ::ng-deep mt-table .mt-actions-column{min-width:14rem}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}:host ::ng-deep mt-table .p-datatable-header>div,:host ::ng-deep mt-table .p-datatable-header>div>div{gap:.75rem;min-width:0;flex-wrap:wrap}:host ::ng-deep mt-table .p-datatable-header mt-tabs{display:block;max-width:100%;overflow-x:auto;padding-bottom:.25rem}:host ::ng-deep mt-table .p-datatable-header mt-text-field{display:block;flex:1 1 16rem;min-width:min(100%,16rem)}:host ::ng-deep mt-table .p-datatable-header .p-inputtext,:host ::ng-deep mt-table .p-datatable-header .p-inputwrapper,:host ::ng-deep mt-table .p-datatable-header .p-selectbutton{width:100%;max-width:100%}@media(max-width:1024px){:host ::ng-deep mt-table .p-datatable-header>div{flex-direction:column;align-items:stretch}:host ::ng-deep mt-table .p-datatable-header>div>div{width:100%;justify-content:flex-start}:host ::ng-deep mt-table .p-datatable-header mt-text-field{flex-basis:100%;min-width:0}}@media(max-width:768px){:host ::ng-deep mt-table .p-datatable-table{min-width:64rem}}\n"] }]
2612
- }], propDecorators: { showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", required: false }] }], showPageShell: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageShell", required: false }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }], surfaceTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceTitleKey", required: false }] }], assignedTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedTabLabelKey", required: false }] }], assignedDecisionTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedDecisionTab", required: false }] }], assignedEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedEmptyStateKey", required: false }] }], assignedStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedStatus", required: false }] }], statusCol: [{ type: i0.ViewChild, args: ['statusCol', { isSignal: true }] }], userCol: [{ type: i0.ViewChild, args: ['userCol', { isSignal: true }] }], delegatorCol: [{ type: i0.ViewChild, args: ['delegatorCol', { isSignal: true }] }], delegatedUserCol: [{ type: i0.ViewChild, args: ['delegatedUserCol', { isSignal: true }] }], scopeCol: [{ type: i0.ViewChild, args: ['scopeCol', { isSignal: true }] }], daysCol: [{ type: i0.ViewChild, args: ['daysCol', { isSignal: true }] }] } });
2662
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <ng-template #tableContent>\n <div class=\"flex flex-col gap-4\">\n @if (!adminMode()) {\n <div class=\"flex items-center gap-2 border-b border-gray-200\">\n @for (tab of tabs(); track tab.value) {\n <button\n type=\"button\"\n class=\"px-4 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.value\"\n [class.text-primary]=\"activeTab() === tab.value\"\n [class.border-transparent]=\"activeTab() !== tab.value\"\n [class.text-gray-500]=\"activeTab() !== tab.value\"\n (click)=\"switchTab(tab.value)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n }\n\n <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [loading]=\"isLoading()\"\n [noCard]=\"true\"\n >\n <ng-template #statusCol let-row>\n <mt-delegation-status-chip\n [status]=\"row.effectiveStatus\"\n ></mt-delegation-status-chip>\n </ng-template>\n\n <ng-template #userCol let-row>\n @let party = getListedParty(row);\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ party.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatorCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegator?.displayName }}\n </span>\n @if (row.delegator?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegator.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatedUserCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegatedUser?.displayName }}\n </span>\n @if (row.delegatedUser?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegatedUser.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #daysCol let-row>\n <span class=\"text-sm text-gray-700\">{{ formatDays(row) }}</span>\n </ng-template>\n\n <ng-template #empty>\n <p class=\"text-sm text-surface-500\">\n {{ t(emptyStateKey()) }}\n </p>\n </ng-template>\n </mt-table>\n </div>\n </ng-template>\n\n <ng-template #adminContent>\n <div class=\"flex min-h-full flex-col gap-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </div>\n </ng-template>\n\n @if (adminMode()) {\n @if (showPageShell()) {\n <mt-page\n [title]=\"surfaceTitle()\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-indigo-50)',\n '--p-avatar-color': 'var(--p-indigo-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n </mt-page>\n } @else {\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\n }\n } @else {\n <div class=\"flex h-full flex-col gap-4 p-4\">\n <mt-card [title]=\"surfaceTitle()\">\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </mt-card>\n </div>\n }\n</ng-container>\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}:host ::ng-deep mt-table .p-datatable-header>div,:host ::ng-deep mt-table .p-datatable-header>div>div{gap:.75rem;min-width:0;flex-wrap:wrap}:host ::ng-deep mt-table .p-datatable-header mt-tabs{display:block;max-width:100%;overflow-x:auto;padding-bottom:.25rem}:host ::ng-deep mt-table .p-datatable-header mt-text-field{display:block;flex:1 1 16rem;min-width:min(100%,16rem)}:host ::ng-deep mt-table .p-datatable-header .p-inputtext,:host ::ng-deep mt-table .p-datatable-header .p-inputwrapper,:host ::ng-deep mt-table .p-datatable-header .p-selectbutton{width:100%;max-width:100%}@media(max-width:1024px){:host ::ng-deep mt-table .p-datatable-header>div{flex-direction:column;align-items:stretch}:host ::ng-deep mt-table .p-datatable-header>div>div{width:100%;justify-content:flex-start}:host ::ng-deep mt-table .p-datatable-header mt-text-field{flex-basis:100%;min-width:0}}\n"] }]
2663
+ }], propDecorators: { showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", required: false }] }], showPageShell: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageShell", required: false }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }], surfaceTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceTitleKey", required: false }] }], assignedTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedTabLabelKey", required: false }] }], assignedDecisionTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedDecisionTab", required: false }] }], assignedEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedEmptyStateKey", required: false }] }], assignedStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedStatus", required: false }] }], showApprovalTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "showApprovalTab", required: false }] }], approvalTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalTabLabelKey", required: false }] }], approvalEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalEmptyStateKey", required: false }] }], approvalStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalStatus", required: false }] }], statusCol: [{ type: i0.ViewChild, args: ['statusCol', { isSignal: true }] }], userCol: [{ type: i0.ViewChild, args: ['userCol', { isSignal: true }] }], delegatorCol: [{ type: i0.ViewChild, args: ['delegatorCol', { isSignal: true }] }], delegatedUserCol: [{ type: i0.ViewChild, args: ['delegatedUserCol', { isSignal: true }] }], daysCol: [{ type: i0.ViewChild, args: ['daysCol', { isSignal: true }] }] } });
2613
2664
 
2614
2665
  /**
2615
2666
  * Endpoints that must NEVER carry the `app-delegation` header.