@masterteam/delegations 0.0.21 → 0.0.22
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.
|
@@ -19,6 +19,7 @@ import { ToastService } from '@masterteam/components/toast';
|
|
|
19
19
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
20
20
|
import { Page } from '@masterteam/components/page';
|
|
21
21
|
import { Breadcrumb } from '@masterteam/components/breadcrumb';
|
|
22
|
+
import { Card } from '@masterteam/components/card';
|
|
22
23
|
import { Table } from '@masterteam/components/table';
|
|
23
24
|
import * as i1$1 from '@angular/forms';
|
|
24
25
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
@@ -460,6 +461,7 @@ class TopbarDelegationMenu {
|
|
|
460
461
|
/** Path to the management page, e.g. `/control-panel/delegations` or `/delegations`. */
|
|
461
462
|
managePath = input('/delegations', ...(ngDevMode ? [{ debugName: "managePath" }] : /* istanbul ignore next */ []));
|
|
462
463
|
compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
|
|
464
|
+
showManageLink = input(true, ...(ngDevMode ? [{ debugName: "showManageLink" }] : /* istanbul ignore next */ []));
|
|
463
465
|
facade = inject(DelegationSessionFacade);
|
|
464
466
|
modal = inject(ModalService);
|
|
465
467
|
transloco = inject(TranslocoService);
|
|
@@ -507,7 +509,7 @@ class TopbarDelegationMenu {
|
|
|
507
509
|
});
|
|
508
510
|
}
|
|
509
511
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TopbarDelegationMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
510
|
-
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 } }, viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n @if (mode() !== \"hidden\") {\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 [attr.aria-label]=\"t('delegations.title')\"\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 class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\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 (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 (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 <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 </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%}.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 });
|
|
512
|
+
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 <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 [attr.aria-label]=\"t('delegations.title')\"\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 class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\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 (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 (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%}.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 });
|
|
511
513
|
}
|
|
512
514
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TopbarDelegationMenu, decorators: [{
|
|
513
515
|
type: Component,
|
|
@@ -520,8 +522,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
520
522
|
RouterLink,
|
|
521
523
|
TranslocoDirective,
|
|
522
524
|
DelegationStatusChip,
|
|
523
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n @if (mode() !== \"hidden\") {\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 [attr.aria-label]=\"t('delegations.title')\"\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 class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\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 (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 (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 <div class=\"border-t border-gray-200 px-2 py-2\">\n
|
|
524
|
-
}], propDecorators: { managePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "managePath", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], popover: [{ type: i0.ViewChild, args: ['popover', { isSignal: true }] }] } });
|
|
525
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n @if (mode() !== \"hidden\") {\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 [attr.aria-label]=\"t('delegations.title')\"\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 class=\"mt-delegation-trigger__label text-sm font-medium\">\n {{\n t(\"delegations.session.banner\", {\n delegatorName: onBehalfOf()?.displayName,\n })\n }}\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 (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 (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%}.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"] }]
|
|
526
|
+
}], 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 }] }] } });
|
|
525
527
|
|
|
526
528
|
// ---------------------------------------------------------------------------
|
|
527
529
|
// Lists / detail
|
|
@@ -540,6 +542,13 @@ class GetAssignedDelegations {
|
|
|
540
542
|
this.query = query;
|
|
541
543
|
}
|
|
542
544
|
}
|
|
545
|
+
class GetAdminDelegations {
|
|
546
|
+
query;
|
|
547
|
+
static type = '[Delegations] Get Admin Delegations';
|
|
548
|
+
constructor(query = {}) {
|
|
549
|
+
this.query = query;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
543
552
|
class GetActiveAssignedDelegations {
|
|
544
553
|
query;
|
|
545
554
|
static type = '[Delegations] Get Active Assigned Delegations';
|
|
@@ -652,6 +661,7 @@ var DelegationsActionKey;
|
|
|
652
661
|
(function (DelegationsActionKey) {
|
|
653
662
|
DelegationsActionKey["GetMy"] = "getMy";
|
|
654
663
|
DelegationsActionKey["GetAssigned"] = "getAssigned";
|
|
664
|
+
DelegationsActionKey["GetAdmin"] = "getAdmin";
|
|
655
665
|
DelegationsActionKey["GetActive"] = "getActive";
|
|
656
666
|
DelegationsActionKey["GetDetail"] = "getDetail";
|
|
657
667
|
DelegationsActionKey["GetScopeOptions"] = "getScopeOptions";
|
|
@@ -705,6 +715,9 @@ let DelegationsState = class DelegationsState {
|
|
|
705
715
|
static getAssigned(state) {
|
|
706
716
|
return state.assigned;
|
|
707
717
|
}
|
|
718
|
+
static getAdmin(state) {
|
|
719
|
+
return state.admin;
|
|
720
|
+
}
|
|
708
721
|
static getActive(state) {
|
|
709
722
|
return state.active;
|
|
710
723
|
}
|
|
@@ -746,6 +759,15 @@ let DelegationsState = class DelegationsState {
|
|
|
746
759
|
onSuccess: (response) => ({ assigned: response.data }),
|
|
747
760
|
});
|
|
748
761
|
}
|
|
762
|
+
getAdmin(ctx, { query }) {
|
|
763
|
+
const req$ = this.http.get(`${BASE}/All`, { params: buildListParams(query) });
|
|
764
|
+
return handleApiRequest({
|
|
765
|
+
ctx,
|
|
766
|
+
key: DelegationsActionKey.GetAdmin,
|
|
767
|
+
request$: req$,
|
|
768
|
+
onSuccess: (response) => ({ admin: response.data }),
|
|
769
|
+
});
|
|
770
|
+
}
|
|
749
771
|
getActive(ctx, { query }) {
|
|
750
772
|
const req$ = this.http.get(`${BASE}/user/activedelegations`, { params: buildListParams(query) });
|
|
751
773
|
return handleApiRequest({
|
|
@@ -876,6 +898,9 @@ __decorate([
|
|
|
876
898
|
__decorate([
|
|
877
899
|
Action(GetAssignedDelegations)
|
|
878
900
|
], DelegationsState.prototype, "getAssigned", null);
|
|
901
|
+
__decorate([
|
|
902
|
+
Action(GetAdminDelegations)
|
|
903
|
+
], DelegationsState.prototype, "getAdmin", null);
|
|
879
904
|
__decorate([
|
|
880
905
|
Action(GetActiveAssignedDelegations)
|
|
881
906
|
], DelegationsState.prototype, "getActive", null);
|
|
@@ -921,6 +946,9 @@ __decorate([
|
|
|
921
946
|
__decorate([
|
|
922
947
|
Selector()
|
|
923
948
|
], DelegationsState, "getAssigned", null);
|
|
949
|
+
__decorate([
|
|
950
|
+
Selector()
|
|
951
|
+
], DelegationsState, "getAdmin", null);
|
|
924
952
|
__decorate([
|
|
925
953
|
Selector()
|
|
926
954
|
], DelegationsState, "getActive", null);
|
|
@@ -945,6 +973,7 @@ DelegationsState = __decorate([
|
|
|
945
973
|
defaults: {
|
|
946
974
|
my: null,
|
|
947
975
|
assigned: null,
|
|
976
|
+
admin: null,
|
|
948
977
|
active: null,
|
|
949
978
|
detail: null,
|
|
950
979
|
scopeOptions: null,
|
|
@@ -956,7 +985,7 @@ DelegationsState = __decorate([
|
|
|
956
985
|
], DelegationsState);
|
|
957
986
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsState, decorators: [{
|
|
958
987
|
type: Injectable
|
|
959
|
-
}], propDecorators: { getMy: [], getAssigned: [], getActive: [], getDetail: [], clearDetail: [], getScopeOptions: [], previewScope: [], clearScopePreview: [], createLegacy: [], createV2: [], updateLegacy: [], updateV2: [], approve: [], reject: [], cancel: [] } });
|
|
988
|
+
}], propDecorators: { getMy: [], getAssigned: [], getAdmin: [], getActive: [], getDetail: [], clearDetail: [], getScopeOptions: [], previewScope: [], clearScopePreview: [], createLegacy: [], createV2: [], updateLegacy: [], updateV2: [], approve: [], reject: [], cancel: [] } });
|
|
960
989
|
|
|
961
990
|
class DelegationsFacade {
|
|
962
991
|
store = inject(Store);
|
|
@@ -965,6 +994,7 @@ class DelegationsFacade {
|
|
|
965
994
|
// ---------------------------------------------------------------------------
|
|
966
995
|
myPage = select(DelegationsState.getMy);
|
|
967
996
|
assignedPage = select(DelegationsState.getAssigned);
|
|
997
|
+
adminPage = select(DelegationsState.getAdmin);
|
|
968
998
|
activePage = select(DelegationsState.getActive);
|
|
969
999
|
detail = select(DelegationsState.getDetail);
|
|
970
1000
|
scopeOptions = select(DelegationsState.getScopeOptions);
|
|
@@ -976,12 +1006,14 @@ class DelegationsFacade {
|
|
|
976
1006
|
// ---------------------------------------------------------------------------
|
|
977
1007
|
myItems = computed(() => this.myPage()?.items ?? [], ...(ngDevMode ? [{ debugName: "myItems" }] : /* istanbul ignore next */ []));
|
|
978
1008
|
assignedItems = computed(() => this.assignedPage()?.items ?? [], ...(ngDevMode ? [{ debugName: "assignedItems" }] : /* istanbul ignore next */ []));
|
|
1009
|
+
adminItems = computed(() => this.adminPage()?.items ?? [], ...(ngDevMode ? [{ debugName: "adminItems" }] : /* istanbul ignore next */ []));
|
|
979
1010
|
activeItems = computed(() => this.activePage()?.items ?? [], ...(ngDevMode ? [{ debugName: "activeItems" }] : /* istanbul ignore next */ []));
|
|
980
1011
|
// ---------------------------------------------------------------------------
|
|
981
1012
|
// Loading
|
|
982
1013
|
// ---------------------------------------------------------------------------
|
|
983
1014
|
isLoadingMy = computed(() => this.loadingActive().includes(DelegationsActionKey.GetMy), ...(ngDevMode ? [{ debugName: "isLoadingMy" }] : /* istanbul ignore next */ []));
|
|
984
1015
|
isLoadingAssigned = computed(() => this.loadingActive().includes(DelegationsActionKey.GetAssigned), ...(ngDevMode ? [{ debugName: "isLoadingAssigned" }] : /* istanbul ignore next */ []));
|
|
1016
|
+
isLoadingAdmin = computed(() => this.loadingActive().includes(DelegationsActionKey.GetAdmin), ...(ngDevMode ? [{ debugName: "isLoadingAdmin" }] : /* istanbul ignore next */ []));
|
|
985
1017
|
isLoadingActive = computed(() => this.loadingActive().includes(DelegationsActionKey.GetActive), ...(ngDevMode ? [{ debugName: "isLoadingActive" }] : /* istanbul ignore next */ []));
|
|
986
1018
|
isLoadingDetail = computed(() => this.loadingActive().includes(DelegationsActionKey.GetDetail), ...(ngDevMode ? [{ debugName: "isLoadingDetail" }] : /* istanbul ignore next */ []));
|
|
987
1019
|
isLoadingScopeOptions = computed(() => this.loadingActive().includes(DelegationsActionKey.GetScopeOptions), ...(ngDevMode ? [{ debugName: "isLoadingScopeOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -996,6 +1028,7 @@ class DelegationsFacade {
|
|
|
996
1028
|
// ---------------------------------------------------------------------------
|
|
997
1029
|
errorMy = computed(() => this.errors()[DelegationsActionKey.GetMy] ?? null, ...(ngDevMode ? [{ debugName: "errorMy" }] : /* istanbul ignore next */ []));
|
|
998
1030
|
errorAssigned = computed(() => this.errors()[DelegationsActionKey.GetAssigned] ?? null, ...(ngDevMode ? [{ debugName: "errorAssigned" }] : /* istanbul ignore next */ []));
|
|
1031
|
+
errorAdmin = computed(() => this.errors()[DelegationsActionKey.GetAdmin] ?? null, ...(ngDevMode ? [{ debugName: "errorAdmin" }] : /* istanbul ignore next */ []));
|
|
999
1032
|
errorDetail = computed(() => this.errors()[DelegationsActionKey.GetDetail] ?? null, ...(ngDevMode ? [{ debugName: "errorDetail" }] : /* istanbul ignore next */ []));
|
|
1000
1033
|
errorScopeOptions = computed(() => this.errors()[DelegationsActionKey.GetScopeOptions] ?? null, ...(ngDevMode ? [{ debugName: "errorScopeOptions" }] : /* istanbul ignore next */ []));
|
|
1001
1034
|
errorSave = computed(() => this.errors()[DelegationsActionKey.Create] ??
|
|
@@ -1010,6 +1043,9 @@ class DelegationsFacade {
|
|
|
1010
1043
|
getAssigned(query = {}) {
|
|
1011
1044
|
return this.store.dispatch(new GetAssignedDelegations(query));
|
|
1012
1045
|
}
|
|
1046
|
+
getAdmin(query = {}) {
|
|
1047
|
+
return this.store.dispatch(new GetAdminDelegations(query));
|
|
1048
|
+
}
|
|
1013
1049
|
getActive(query = {}) {
|
|
1014
1050
|
return this.store.dispatch(new GetActiveAssignedDelegations(query));
|
|
1015
1051
|
}
|
|
@@ -1555,6 +1591,21 @@ class ScopePicker {
|
|
|
1555
1591
|
timer = setTimeout(() => this.facade.previewScope(s), 300);
|
|
1556
1592
|
});
|
|
1557
1593
|
});
|
|
1594
|
+
let lastGroupKeys = '';
|
|
1595
|
+
effect(() => {
|
|
1596
|
+
const groups = this.groups();
|
|
1597
|
+
const nextGroupKeys = groups.map((group) => group.key).join('|');
|
|
1598
|
+
if (!nextGroupKeys) {
|
|
1599
|
+
lastGroupKeys = '';
|
|
1600
|
+
this.expanded.set(new Set());
|
|
1601
|
+
return;
|
|
1602
|
+
}
|
|
1603
|
+
if (nextGroupKeys === lastGroupKeys) {
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
lastGroupKeys = nextGroupKeys;
|
|
1607
|
+
this.expanded.set(new Set(groups.map((group) => group.key)));
|
|
1608
|
+
});
|
|
1558
1609
|
}
|
|
1559
1610
|
isExpanded(group) {
|
|
1560
1611
|
return this.expanded().has(group.key);
|
|
@@ -1618,7 +1669,7 @@ class ScopePicker {
|
|
|
1618
1669
|
return this.transloco.getActiveLang();
|
|
1619
1670
|
}
|
|
1620
1671
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ScopePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1621
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ScopePicker, isStandalone: true, selector: "mt-scope-picker", inputs: { scope: { classPropertyName: "scope", publicName: "scope", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, delegatorUserId: { classPropertyName: "delegatorUserId", publicName: "delegatorUserId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scope: "scopeChange" }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"mt-scope-picker flex flex-col gap-4\">\n @if (isLoadingOptions()) {\n <p-skeleton height=\"2rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n } @else {\n <section class=\"flex flex-col gap-2\">\n
|
|
1672
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ScopePicker, isStandalone: true, selector: "mt-scope-picker", inputs: { scope: { classPropertyName: "scope", publicName: "scope", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, delegatorUserId: { classPropertyName: "delegatorUserId", publicName: "delegatorUserId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scope: "scopeChange" }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"mt-scope-picker flex flex-col gap-4\">\n @if (isLoadingOptions()) {\n <p-skeleton height=\"2rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n } @else {\n <section class=\"flex flex-col gap-2\">\n @if (errorOptions(); as errorMessage) {\n <div\n class=\"rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700\"\n >\n {{ errorMessage }}\n </div>\n }\n\n @if (groups().length === 0 && !errorOptions()) {\n <p class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noGrantableOptions\") }}\n </p>\n }\n\n @for (group of groups(); track group.key) {\n <div class=\"overflow-hidden rounded-md border border-gray-200\">\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center justify-between px-3 py-2 hover:bg-surface-50\"\n (click)=\"toggleAccordion(group)\"\n >\n <div class=\"flex min-w-0 items-center gap-2\">\n <mt-icon\n [icon]=\"\n isExpanded(group)\n ? 'arrow.chevron-down'\n : 'arrow.chevron-right'\n \"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n <span class=\"truncate text-sm text-gray-900\">\n {{ getGroupLabel(group) }}\n </span>\n </div>\n @if (selectedCount(group); as selectedGrantCount) {\n @if (selectedGrantCount > 0) {\n <span\n class=\"rounded-full bg-primary-50 px-2 py-0.5 text-xs font-medium text-primary\"\n >\n {{ selectedGrantCount }}\n </span>\n }\n }\n </button>\n\n @if (isExpanded(group)) {\n <div\n class=\"mt-scope-picker__group flex flex-col gap-3 bg-surface-50/40 px-3 py-3\"\n >\n @for (targetGroup of group.targets; track targetGroup.key) {\n <section\n class=\"rounded-md border border-surface-200 bg-white px-3 py-3\"\n >\n <div\n class=\"flex flex-wrap items-center justify-between gap-2\"\n >\n <div class=\"min-w-0\">\n <div class=\"truncate text-sm font-medium text-gray-900\">\n {{ getTargetLabel(targetGroup.target) }}\n </div>\n </div>\n @if (\n selectedTargetCount(targetGroup);\n as selectedTargetGrantCount\n ) {\n @if (selectedTargetGrantCount > 0) {\n <span\n class=\"rounded-full bg-primary-50 px-2 py-0.5 text-xs font-medium text-primary\"\n >\n {{ selectedTargetGrantCount }}\n </span>\n }\n }\n </div>\n\n <div\n class=\"mt-scope-picker__actions mt-3 flex flex-col gap-1\"\n >\n @for (\n grant of getTargetActions(targetGroup);\n track $index\n ) {\n <label\n class=\"flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 hover:bg-surface-100\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(grant)\"\n [disabled]=\"readonly()\"\n (change)=\"toggleGrant(grant)\"\n />\n <span class=\"text-sm\">\n {{ getActionLabel(grant) }}\n </span>\n @if (grant.action.isHighRisk) {\n <mt-icon\n icon=\"alert.alert-triangle\"\n styleClass=\"text-sm text-amber-500\"\n [pTooltip]=\"t('delegations.scope.highRisk')\"\n tooltipPosition=\"top\"\n ></mt-icon>\n }\n </label>\n }\n </div>\n </section>\n } @empty {\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noGrantableOptions\") }}\n </div>\n }\n </div>\n }\n </div>\n }\n </section>\n\n <section\n class=\"flex flex-col gap-1 rounded-md border border-dashed border-gray-300 bg-surface-50 px-3 py-2\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-xs font-medium text-gray-700\">\n {{ t(\"delegations.scope.previewTitle\") }}\n </div>\n @if (isPreviewing()) {\n <p-skeleton width=\"6rem\" height=\"0.75rem\"></p-skeleton>\n }\n </div>\n @if (preview(); as p) {\n @if (p.isValid) {\n <div class=\"text-sm text-gray-900\">\n {{\n getPreviewSummary(p.summary) ||\n t(\"delegations.column.scopeSummary\")\n }}\n </div>\n } @else {\n <div class=\"text-sm text-red-700\">\n {{ t(\"delegations.scope.previewInvalid\") }}\n </div>\n }\n @if (p.warnings.length > 0) {\n <ul class=\"list-inside list-disc text-xs text-amber-700\">\n @for (w of p.warnings; track w.message) {\n <li>{{ w.message }}</li>\n }\n </ul>\n }\n @if (p.deniedItems.length > 0) {\n <ul class=\"list-inside list-disc text-xs text-red-700\">\n @for (d of p.deniedItems; track d.operationKey) {\n <li>\n {{ formatDeniedTarget(d.targetKey) }} /\n {{ formatDeniedOperation(d.operationKey) }} -\n {{ d.reasonCode }}\n </li>\n }\n </ul>\n }\n } @else {\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </div>\n }\n </section>\n }\n </div>\n</ng-container>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1622
1673
|
}
|
|
1623
1674
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ScopePicker, decorators: [{
|
|
1624
1675
|
type: Component,
|
|
@@ -1628,10 +1679,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1628
1679
|
SkeletonModule,
|
|
1629
1680
|
TooltipModule,
|
|
1630
1681
|
TranslocoDirective,
|
|
1631
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"mt-scope-picker flex flex-col gap-4\">\n @if (isLoadingOptions()) {\n <p-skeleton height=\"2rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n } @else {\n <section class=\"flex flex-col gap-2\">\n
|
|
1682
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"mt-scope-picker flex flex-col gap-4\">\n @if (isLoadingOptions()) {\n <p-skeleton height=\"2rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n } @else {\n <section class=\"flex flex-col gap-2\">\n @if (errorOptions(); as errorMessage) {\n <div\n class=\"rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700\"\n >\n {{ errorMessage }}\n </div>\n }\n\n @if (groups().length === 0 && !errorOptions()) {\n <p class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noGrantableOptions\") }}\n </p>\n }\n\n @for (group of groups(); track group.key) {\n <div class=\"overflow-hidden rounded-md border border-gray-200\">\n <button\n type=\"button\"\n class=\"flex w-full cursor-pointer items-center justify-between px-3 py-2 hover:bg-surface-50\"\n (click)=\"toggleAccordion(group)\"\n >\n <div class=\"flex min-w-0 items-center gap-2\">\n <mt-icon\n [icon]=\"\n isExpanded(group)\n ? 'arrow.chevron-down'\n : 'arrow.chevron-right'\n \"\n styleClass=\"text-base text-gray-400\"\n ></mt-icon>\n <span class=\"truncate text-sm text-gray-900\">\n {{ getGroupLabel(group) }}\n </span>\n </div>\n @if (selectedCount(group); as selectedGrantCount) {\n @if (selectedGrantCount > 0) {\n <span\n class=\"rounded-full bg-primary-50 px-2 py-0.5 text-xs font-medium text-primary\"\n >\n {{ selectedGrantCount }}\n </span>\n }\n }\n </button>\n\n @if (isExpanded(group)) {\n <div\n class=\"mt-scope-picker__group flex flex-col gap-3 bg-surface-50/40 px-3 py-3\"\n >\n @for (targetGroup of group.targets; track targetGroup.key) {\n <section\n class=\"rounded-md border border-surface-200 bg-white px-3 py-3\"\n >\n <div\n class=\"flex flex-wrap items-center justify-between gap-2\"\n >\n <div class=\"min-w-0\">\n <div class=\"truncate text-sm font-medium text-gray-900\">\n {{ getTargetLabel(targetGroup.target) }}\n </div>\n </div>\n @if (\n selectedTargetCount(targetGroup);\n as selectedTargetGrantCount\n ) {\n @if (selectedTargetGrantCount > 0) {\n <span\n class=\"rounded-full bg-primary-50 px-2 py-0.5 text-xs font-medium text-primary\"\n >\n {{ selectedTargetGrantCount }}\n </span>\n }\n }\n </div>\n\n <div\n class=\"mt-scope-picker__actions mt-3 flex flex-col gap-1\"\n >\n @for (\n grant of getTargetActions(targetGroup);\n track $index\n ) {\n <label\n class=\"flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 hover:bg-surface-100\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(grant)\"\n [disabled]=\"readonly()\"\n (change)=\"toggleGrant(grant)\"\n />\n <span class=\"text-sm\">\n {{ getActionLabel(grant) }}\n </span>\n @if (grant.action.isHighRisk) {\n <mt-icon\n icon=\"alert.alert-triangle\"\n styleClass=\"text-sm text-amber-500\"\n [pTooltip]=\"t('delegations.scope.highRisk')\"\n tooltipPosition=\"top\"\n ></mt-icon>\n }\n </label>\n }\n </div>\n </section>\n } @empty {\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noGrantableOptions\") }}\n </div>\n }\n </div>\n }\n </div>\n }\n </section>\n\n <section\n class=\"flex flex-col gap-1 rounded-md border border-dashed border-gray-300 bg-surface-50 px-3 py-2\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-xs font-medium text-gray-700\">\n {{ t(\"delegations.scope.previewTitle\") }}\n </div>\n @if (isPreviewing()) {\n <p-skeleton width=\"6rem\" height=\"0.75rem\"></p-skeleton>\n }\n </div>\n @if (preview(); as p) {\n @if (p.isValid) {\n <div class=\"text-sm text-gray-900\">\n {{\n getPreviewSummary(p.summary) ||\n t(\"delegations.column.scopeSummary\")\n }}\n </div>\n } @else {\n <div class=\"text-sm text-red-700\">\n {{ t(\"delegations.scope.previewInvalid\") }}\n </div>\n }\n @if (p.warnings.length > 0) {\n <ul class=\"list-inside list-disc text-xs text-amber-700\">\n @for (w of p.warnings; track w.message) {\n <li>{{ w.message }}</li>\n }\n </ul>\n }\n @if (p.deniedItems.length > 0) {\n <ul class=\"list-inside list-disc text-xs text-red-700\">\n @for (d of p.deniedItems; track d.operationKey) {\n <li>\n {{ formatDeniedTarget(d.targetKey) }} /\n {{ formatDeniedOperation(d.operationKey) }} -\n {{ d.reasonCode }}\n </li>\n }\n </ul>\n }\n } @else {\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </div>\n }\n </section>\n }\n </div>\n</ng-container>\n", styles: [":host{display:block}\n"] }]
|
|
1632
1683
|
}], ctorParameters: () => [], propDecorators: { scope: [{ type: i0.Input, args: [{ isSignal: true, alias: "scope", required: false }] }, { type: i0.Output, args: ["scopeChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], delegatorUserId: [{ type: i0.Input, args: [{ isSignal: true, alias: "delegatorUserId", required: false }] }] } });
|
|
1633
1684
|
|
|
1634
1685
|
const EMPTY_SCOPE = { grants: [], metadata: {} };
|
|
1686
|
+
function getCurrentDelegatorFromLocalStorage() {
|
|
1687
|
+
if (typeof localStorage === 'undefined') {
|
|
1688
|
+
return null;
|
|
1689
|
+
}
|
|
1690
|
+
try {
|
|
1691
|
+
const raw = localStorage.getItem('auth');
|
|
1692
|
+
if (!raw)
|
|
1693
|
+
return null;
|
|
1694
|
+
const parsed = JSON.parse(raw);
|
|
1695
|
+
if (!parsed || typeof parsed !== 'object')
|
|
1696
|
+
return null;
|
|
1697
|
+
const state = (parsed['state'] ?? parsed) ||
|
|
1698
|
+
null;
|
|
1699
|
+
const userWrapper = state?.['user'];
|
|
1700
|
+
const user = userWrapper?.['user'] ??
|
|
1701
|
+
userWrapper;
|
|
1702
|
+
if (!user || typeof user !== 'object')
|
|
1703
|
+
return null;
|
|
1704
|
+
const id = user['id'] ??
|
|
1705
|
+
user['userId'];
|
|
1706
|
+
if (!id)
|
|
1707
|
+
return null;
|
|
1708
|
+
const photo = user['photo'];
|
|
1709
|
+
const photoPath = typeof photo === 'string'
|
|
1710
|
+
? photo
|
|
1711
|
+
: (photo?.fileName ?? null);
|
|
1712
|
+
return {
|
|
1713
|
+
id,
|
|
1714
|
+
userId: id,
|
|
1715
|
+
displayName: user['displayName'] ??
|
|
1716
|
+
user['name'] ??
|
|
1717
|
+
user['userName'] ??
|
|
1718
|
+
'',
|
|
1719
|
+
userName: user['userName'] ?? '',
|
|
1720
|
+
email: user['email'] ?? null,
|
|
1721
|
+
photo: photoPath,
|
|
1722
|
+
isExternal: !!user['isExternal'],
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
catch {
|
|
1726
|
+
return null;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1635
1729
|
function extractUserId(value) {
|
|
1636
1730
|
if (typeof value === 'string') {
|
|
1637
1731
|
return value.trim() || undefined;
|
|
@@ -1680,13 +1774,15 @@ class DelegationForm {
|
|
|
1680
1774
|
isSaving = this.facade.isSaving;
|
|
1681
1775
|
context = new HttpContext().set(REQUEST_CONTEXT, { useBaseUrl: false });
|
|
1682
1776
|
scope = signal(EMPTY_SCOPE, ...(ngDevMode ? [{ debugName: "scope" }] : /* istanbul ignore next */ []));
|
|
1683
|
-
|
|
1777
|
+
currentDelegator = signal(getCurrentDelegatorFromLocalStorage(), ...(ngDevMode ? [{ debugName: "currentDelegator" }] : /* istanbul ignore next */ []));
|
|
1778
|
+
/** Selected delegator id drives scope/options loading and the admin payload. */
|
|
1684
1779
|
selectedDelegatorId = computed(() => {
|
|
1685
|
-
if (
|
|
1686
|
-
return
|
|
1687
|
-
|
|
1780
|
+
if (this.adminMode()) {
|
|
1781
|
+
return extractUserId(this.formValue()?.delegateFrom);
|
|
1782
|
+
}
|
|
1783
|
+
return this.currentDelegator()?.id;
|
|
1688
1784
|
}, ...(ngDevMode ? [{ debugName: "selectedDelegatorId" }] : /* istanbul ignore next */ []));
|
|
1689
|
-
/**
|
|
1785
|
+
/** Admin mode waits for a chosen delegator; self-service always has one. */
|
|
1690
1786
|
showScopePicker = computed(() => !this.adminMode() || !!this.selectedDelegatorId(), ...(ngDevMode ? [{ debugName: "showScopePicker" }] : /* istanbul ignore next */ []));
|
|
1691
1787
|
specificDaysOptions = signal([
|
|
1692
1788
|
{ label: this.transloco.translate('delegations.days.sunday'), value: 0 },
|
|
@@ -1705,21 +1801,19 @@ class DelegationForm {
|
|
|
1705
1801
|
bodyClass: 'grid grid-cols-1 gap-4 items-start lg:grid-cols-12',
|
|
1706
1802
|
order: 1,
|
|
1707
1803
|
fields: [
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
]
|
|
1722
|
-
: []),
|
|
1804
|
+
new UserSearchFieldConfig({
|
|
1805
|
+
key: 'delegateFrom',
|
|
1806
|
+
label: this.transloco.translate('delegations.column.delegatorName'),
|
|
1807
|
+
apiUrl: 'Identity/users',
|
|
1808
|
+
context: this.context,
|
|
1809
|
+
validators: [ValidatorConfig.required()],
|
|
1810
|
+
cssClass: this.halfWidth,
|
|
1811
|
+
colSpan: 6,
|
|
1812
|
+
order: 0,
|
|
1813
|
+
disabled: this.readonly() ||
|
|
1814
|
+
!this.adminMode() ||
|
|
1815
|
+
!!this.delegationForEdit(),
|
|
1816
|
+
}),
|
|
1723
1817
|
new UserSearchFieldConfig({
|
|
1724
1818
|
key: 'delegateTo',
|
|
1725
1819
|
label: this.transloco.translate('delegations.column.delegatedTo'),
|
|
@@ -1819,6 +1913,7 @@ class DelegationForm {
|
|
|
1819
1913
|
const d = this.detail();
|
|
1820
1914
|
if (editing && d && d.row.delegationId === editing.delegationId) {
|
|
1821
1915
|
this.delegationFormControl.patchValue({
|
|
1916
|
+
delegateFrom: this.mapPartyToUserValue(d.row.delegator),
|
|
1822
1917
|
delegateTo: d.row.delegatedUser,
|
|
1823
1918
|
description: '',
|
|
1824
1919
|
delegateFromDateTime: d.row.startsAtUtc,
|
|
@@ -1834,12 +1929,26 @@ class DelegationForm {
|
|
|
1834
1929
|
}
|
|
1835
1930
|
else if (!editing) {
|
|
1836
1931
|
this.delegationFormControl.reset({
|
|
1932
|
+
delegateFrom: null,
|
|
1837
1933
|
delegationDaysType: 'FullRange',
|
|
1838
1934
|
requiresApproval: true,
|
|
1839
1935
|
});
|
|
1840
1936
|
this.scope.set(EMPTY_SCOPE);
|
|
1841
1937
|
}
|
|
1842
1938
|
});
|
|
1939
|
+
effect(() => {
|
|
1940
|
+
const currentDelegator = this.currentDelegator();
|
|
1941
|
+
if (this.adminMode() || this.delegationForEdit() || !currentDelegator) {
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
const existingDelegator = extractUserId(this.delegationFormControl.getRawValue()?.delegateFrom);
|
|
1945
|
+
if (existingDelegator === currentDelegator.id) {
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
this.delegationFormControl.patchValue({
|
|
1949
|
+
delegateFrom: currentDelegator,
|
|
1950
|
+
});
|
|
1951
|
+
});
|
|
1843
1952
|
}
|
|
1844
1953
|
ngOnInit() {
|
|
1845
1954
|
const editing = this.delegationForEdit();
|
|
@@ -1893,8 +2002,19 @@ class DelegationForm {
|
|
|
1893
2002
|
});
|
|
1894
2003
|
}
|
|
1895
2004
|
}
|
|
2005
|
+
mapPartyToUserValue(party) {
|
|
2006
|
+
return {
|
|
2007
|
+
id: party.userId,
|
|
2008
|
+
userId: party.userId,
|
|
2009
|
+
displayName: party.displayName,
|
|
2010
|
+
userName: party.email || party.displayName,
|
|
2011
|
+
email: party.email ?? null,
|
|
2012
|
+
photo: null,
|
|
2013
|
+
isExternal: false,
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
1896
2016
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1897
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationForm, isStandalone: true, selector: "mt-delegation-form", inputs: { delegationForEdit: { classPropertyName: "delegationForEdit", publicName: "delegationForEdit", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n 'delegation-form-content flex min-w-0 flex-col gap-
|
|
2017
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationForm, isStandalone: true, selector: "mt-delegation-form", inputs: { delegationForEdit: { classPropertyName: "delegationForEdit", publicName: "delegationForEdit", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n 'delegation-form-content flex min-w-0 flex-col gap-4 overflow-x-hidden p-4 max-[640px]:p-3 ' +\n modal.contentClass\n \"\n >\n <section class=\"delegation-form-section\">\n <mt-dynamic-form\n [formConfig]=\"formConfig()\"\n [formControl]=\"delegationFormControl\"\n />\n </section>\n\n <section class=\"delegation-form-section delegation-form-section--scope\">\n <header class=\"delegation-form-section__header\">\n <h3 class=\"delegation-form-section__title\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </h3>\n @if (adminMode() && !showScopePicker()) {\n <p class=\"delegation-form-section__subtitle\">\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </p>\n }\n </header>\n\n @if (showScopePicker()) {\n <mt-scope-picker\n [(scope)]=\"scope\"\n [readonly]=\"readonly()\"\n [delegatorUserId]=\"selectedDelegatorId()\"\n ></mt-scope-picker>\n } @else {\n <div class=\"delegation-form-section__empty\">\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </div>\n }\n </section>\n </div>\n\n <div\n [class]=\"\n 'delegation-form-footer ' +\n modal.footerClass +\n ' flex-col gap-2 sm:flex-row sm:items-center sm:justify-end'\n \"\n >\n <mt-button\n [label]=\"t('delegations.common.cancel')\"\n variant=\"outlined\"\n (click)=\"ref.close()\"\n styleClass=\"w-full sm:w-auto\"\n />\n @if (!readonly()) {\n <mt-button\n [label]=\"\n delegationForEdit()\n ? t('delegations.common.update')\n : t('delegations.common.create')\n \"\n [loading]=\"isSaving()\"\n [disabled]=\"!delegationFormControl.valid || !canSubmit()\"\n (click)=\"onSubmit()\"\n styleClass=\"w-full sm:w-auto\"\n />\n }\n </div>\n</ng-container>\n", styles: [":host{display:block}.delegation-form-section{display:flex;flex-direction:column;gap:1rem;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:1rem;background:color-mix(in srgb,var(--p-surface-0, #ffffff) 92%,var(--p-primary-50, #eff6ff));padding:1rem}.delegation-form-section--scope{gap:.75rem}.delegation-form-section__header{display:flex;flex-direction:column;gap:.25rem}.delegation-form-section__title{margin:0;font-size:.95rem;font-weight:600;color:var(--p-surface-900, #111827)}.delegation-form-section__subtitle{margin:0;font-size:.8rem;color:var(--p-surface-500, #6b7280)}.delegation-form-section__empty{border:1px dashed var(--p-surface-300, #d1d5db);border-radius:.875rem;background:var(--p-surface-50, #f8fafc);padding:.875rem 1rem;font-size:.85rem;color:var(--p-surface-500, #6b7280)}@media(max-width:640px){.delegation-form-section{border-radius:.875rem;padding:.875rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ScopePicker, selector: "mt-scope-picker", inputs: ["scope", "readonly", "delegatorUserId"], outputs: ["scopeChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1898
2018
|
}
|
|
1899
2019
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationForm, decorators: [{
|
|
1900
2020
|
type: Component,
|
|
@@ -1905,7 +2025,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1905
2025
|
ReactiveFormsModule,
|
|
1906
2026
|
ScopePicker,
|
|
1907
2027
|
TranslocoDirective,
|
|
1908
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n 'delegation-form-content flex min-w-0 flex-col gap-
|
|
2028
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n 'delegation-form-content flex min-w-0 flex-col gap-4 overflow-x-hidden p-4 max-[640px]:p-3 ' +\n modal.contentClass\n \"\n >\n <section class=\"delegation-form-section\">\n <mt-dynamic-form\n [formConfig]=\"formConfig()\"\n [formControl]=\"delegationFormControl\"\n />\n </section>\n\n <section class=\"delegation-form-section delegation-form-section--scope\">\n <header class=\"delegation-form-section__header\">\n <h3 class=\"delegation-form-section__title\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </h3>\n @if (adminMode() && !showScopePicker()) {\n <p class=\"delegation-form-section__subtitle\">\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </p>\n }\n </header>\n\n @if (showScopePicker()) {\n <mt-scope-picker\n [(scope)]=\"scope\"\n [readonly]=\"readonly()\"\n [delegatorUserId]=\"selectedDelegatorId()\"\n ></mt-scope-picker>\n } @else {\n <div class=\"delegation-form-section__empty\">\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </div>\n }\n </section>\n </div>\n\n <div\n [class]=\"\n 'delegation-form-footer ' +\n modal.footerClass +\n ' flex-col gap-2 sm:flex-row sm:items-center sm:justify-end'\n \"\n >\n <mt-button\n [label]=\"t('delegations.common.cancel')\"\n variant=\"outlined\"\n (click)=\"ref.close()\"\n styleClass=\"w-full sm:w-auto\"\n />\n @if (!readonly()) {\n <mt-button\n [label]=\"\n delegationForEdit()\n ? t('delegations.common.update')\n : t('delegations.common.create')\n \"\n [loading]=\"isSaving()\"\n [disabled]=\"!delegationFormControl.valid || !canSubmit()\"\n (click)=\"onSubmit()\"\n styleClass=\"w-full sm:w-auto\"\n />\n }\n </div>\n</ng-container>\n", styles: [":host{display:block}.delegation-form-section{display:flex;flex-direction:column;gap:1rem;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:1rem;background:color-mix(in srgb,var(--p-surface-0, #ffffff) 92%,var(--p-primary-50, #eff6ff));padding:1rem}.delegation-form-section--scope{gap:.75rem}.delegation-form-section__header{display:flex;flex-direction:column;gap:.25rem}.delegation-form-section__title{margin:0;font-size:.95rem;font-weight:600;color:var(--p-surface-900, #111827)}.delegation-form-section__subtitle{margin:0;font-size:.8rem;color:var(--p-surface-500, #6b7280)}.delegation-form-section__empty{border:1px dashed var(--p-surface-300, #d1d5db);border-radius:.875rem;background:var(--p-surface-50, #f8fafc);padding:.875rem 1rem;font-size:.85rem;color:var(--p-surface-500, #6b7280)}@media(max-width:640px){.delegation-form-section{border-radius:.875rem;padding:.875rem}}\n"] }]
|
|
1909
2029
|
}], ctorParameters: () => [], propDecorators: { delegationForEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "delegationForEdit", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }] } });
|
|
1910
2030
|
|
|
1911
2031
|
/**
|
|
@@ -1978,6 +2098,11 @@ class DelegationsList {
|
|
|
1978
2098
|
* `withComponentInputBinding()` — admin passes `data: { adminMode: true }`.
|
|
1979
2099
|
*/
|
|
1980
2100
|
adminMode = input(false, ...(ngDevMode ? [{ debugName: "adminMode" }] : /* istanbul ignore next */ []));
|
|
2101
|
+
surfaceTitleKey = input('delegations.title', ...(ngDevMode ? [{ debugName: "surfaceTitleKey" }] : /* istanbul ignore next */ []));
|
|
2102
|
+
assignedTabLabelKey = input('delegations.delegatedToMe', ...(ngDevMode ? [{ debugName: "assignedTabLabelKey" }] : /* istanbul ignore next */ []));
|
|
2103
|
+
assignedDecisionTab = input(false, ...(ngDevMode ? [{ debugName: "assignedDecisionTab" }] : /* istanbul ignore next */ []));
|
|
2104
|
+
assignedEmptyStateKey = input('delegations.empty.assigned', ...(ngDevMode ? [{ debugName: "assignedEmptyStateKey" }] : /* istanbul ignore next */ []));
|
|
2105
|
+
assignedStatus = input(null, ...(ngDevMode ? [{ debugName: "assignedStatus" }] : /* istanbul ignore next */ []));
|
|
1981
2106
|
facade = inject(DelegationsFacade);
|
|
1982
2107
|
modal = inject(ModalService);
|
|
1983
2108
|
transloco = inject(TranslocoService);
|
|
@@ -1996,25 +2121,39 @@ class DelegationsList {
|
|
|
1996
2121
|
},
|
|
1997
2122
|
], ...(ngDevMode ? [{ debugName: "breadcrumbItems" }] : /* istanbul ignore next */ []));
|
|
1998
2123
|
activeTab = signal('my', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
1999
|
-
|
|
2124
|
+
surfaceTitle = computed(() => this.transloco.translate(this.surfaceTitleKey()), ...(ngDevMode ? [{ debugName: "surfaceTitle" }] : /* istanbul ignore next */ []));
|
|
2125
|
+
tabs = computed(() => [
|
|
2000
2126
|
{
|
|
2001
2127
|
value: 'my',
|
|
2002
2128
|
label: this.transloco.translate('delegations.myDelegations'),
|
|
2003
2129
|
},
|
|
2004
2130
|
{
|
|
2005
2131
|
value: 'assigned',
|
|
2006
|
-
label: this.
|
|
2132
|
+
label: this.assignedDecisionTab()
|
|
2133
|
+
? `${this.transloco.translate('delegations.action.approve')} / ${this.transloco.translate('delegations.action.reject')}`
|
|
2134
|
+
: this.transloco.translate(this.assignedTabLabelKey()),
|
|
2007
2135
|
},
|
|
2008
2136
|
], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
2009
|
-
isLoading = computed(() => this.
|
|
2010
|
-
? this.facade.
|
|
2011
|
-
: this.
|
|
2137
|
+
isLoading = computed(() => this.adminMode()
|
|
2138
|
+
? this.facade.isLoadingAdmin()
|
|
2139
|
+
: this.activeTab() === 'my'
|
|
2140
|
+
? this.facade.isLoadingMy()
|
|
2141
|
+
: this.facade.isLoadingAssigned(), ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
2012
2142
|
scopeOptions = this.facade.scopeOptions;
|
|
2013
|
-
rows = computed(() => this.
|
|
2014
|
-
? this.facade.
|
|
2015
|
-
: this.
|
|
2143
|
+
rows = computed(() => this.adminMode()
|
|
2144
|
+
? this.facade.adminItems()
|
|
2145
|
+
: this.activeTab() === 'my'
|
|
2146
|
+
? this.facade.myItems()
|
|
2147
|
+
: this.facade.assignedItems(), ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
2148
|
+
emptyStateKey = computed(() => this.adminMode()
|
|
2149
|
+
? 'components.table.no-data-found'
|
|
2150
|
+
: this.activeTab() === 'my'
|
|
2151
|
+
? 'delegations.empty.my'
|
|
2152
|
+
: this.assignedEmptyStateKey(), ...(ngDevMode ? [{ debugName: "emptyStateKey" }] : /* istanbul ignore next */ []));
|
|
2016
2153
|
statusCol = viewChild.required('statusCol');
|
|
2017
2154
|
userCol = viewChild.required('userCol');
|
|
2155
|
+
delegatorCol = viewChild.required('delegatorCol');
|
|
2156
|
+
delegatedUserCol = viewChild.required('delegatedUserCol');
|
|
2018
2157
|
scopeCol = viewChild.required('scopeCol');
|
|
2019
2158
|
daysCol = viewChild.required('daysCol');
|
|
2020
2159
|
canCreate = computed(() => {
|
|
@@ -2084,56 +2223,80 @@ class DelegationsList {
|
|
|
2084
2223
|
hidden: (row) => !this.has(row, 'StartSession'),
|
|
2085
2224
|
},
|
|
2086
2225
|
], ...(ngDevMode ? [{ debugName: "rowActions" }] : /* istanbul ignore next */ []));
|
|
2087
|
-
tableColumns = linkedSignal(() =>
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
: '
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
{
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2226
|
+
tableColumns = linkedSignal(() => {
|
|
2227
|
+
const baseColumns = [
|
|
2228
|
+
{
|
|
2229
|
+
key: 'effectiveStatus',
|
|
2230
|
+
label: this.transloco.translate('delegations.column.status'),
|
|
2231
|
+
type: 'custom',
|
|
2232
|
+
customCellTpl: this.statusCol(),
|
|
2233
|
+
width: '10rem',
|
|
2234
|
+
},
|
|
2235
|
+
{
|
|
2236
|
+
key: 'scopeSummary',
|
|
2237
|
+
label: this.transloco.translate('delegations.column.scopeSummary'),
|
|
2238
|
+
type: 'custom',
|
|
2239
|
+
customCellTpl: this.scopeCol(),
|
|
2240
|
+
width: '18rem',
|
|
2241
|
+
},
|
|
2242
|
+
{
|
|
2243
|
+
key: 'startsAtUtc',
|
|
2244
|
+
label: this.transloco.translate('delegations.column.startDate'),
|
|
2245
|
+
type: 'dateTime',
|
|
2246
|
+
width: '11rem',
|
|
2247
|
+
},
|
|
2248
|
+
{
|
|
2249
|
+
key: 'endsAtUtc',
|
|
2250
|
+
label: this.transloco.translate('delegations.column.endDate'),
|
|
2251
|
+
type: 'dateTime',
|
|
2252
|
+
width: '11rem',
|
|
2253
|
+
},
|
|
2254
|
+
{
|
|
2255
|
+
key: 'createdAtUtc',
|
|
2256
|
+
label: this.transloco.translate('delegations.column.createdDate'),
|
|
2257
|
+
type: 'dateTime',
|
|
2258
|
+
width: '11rem',
|
|
2259
|
+
},
|
|
2260
|
+
{
|
|
2261
|
+
key: 'dayRuleMode',
|
|
2262
|
+
label: this.transloco.translate('delegations.column.days'),
|
|
2263
|
+
type: 'custom',
|
|
2264
|
+
customCellTpl: this.daysCol(),
|
|
2265
|
+
width: '12rem',
|
|
2266
|
+
},
|
|
2267
|
+
];
|
|
2268
|
+
if (this.adminMode()) {
|
|
2269
|
+
return [
|
|
2270
|
+
{
|
|
2271
|
+
key: 'delegator',
|
|
2272
|
+
label: this.transloco.translate('delegations.column.delegatorName'),
|
|
2273
|
+
type: 'custom',
|
|
2274
|
+
customCellTpl: this.delegatorCol(),
|
|
2275
|
+
width: '16rem',
|
|
2276
|
+
},
|
|
2277
|
+
{
|
|
2278
|
+
key: 'delegatedUser',
|
|
2279
|
+
label: this.transloco.translate('delegations.column.delegatedTo'),
|
|
2280
|
+
type: 'custom',
|
|
2281
|
+
customCellTpl: this.delegatedUserCol(),
|
|
2282
|
+
width: '16rem',
|
|
2283
|
+
},
|
|
2284
|
+
...baseColumns,
|
|
2285
|
+
];
|
|
2286
|
+
}
|
|
2287
|
+
return [
|
|
2288
|
+
{
|
|
2289
|
+
key: this.activeTab() === 'my' ? 'delegatedUser' : 'delegator',
|
|
2290
|
+
label: this.transloco.translate(this.activeTab() === 'my'
|
|
2291
|
+
? 'delegations.column.delegatedTo'
|
|
2292
|
+
: 'delegations.column.delegatorName'),
|
|
2293
|
+
type: 'custom',
|
|
2294
|
+
customCellTpl: this.userCol(),
|
|
2295
|
+
width: '16rem',
|
|
2296
|
+
},
|
|
2297
|
+
...baseColumns,
|
|
2298
|
+
];
|
|
2299
|
+
}, ...(ngDevMode ? [{ debugName: "tableColumns" }] : /* istanbul ignore next */ []));
|
|
2137
2300
|
busyIds = signal([], ...(ngDevMode ? [{ debugName: "busyIds" }] : /* istanbul ignore next */ []));
|
|
2138
2301
|
weekdayKeys = [
|
|
2139
2302
|
'sunday',
|
|
@@ -2155,11 +2318,18 @@ class DelegationsList {
|
|
|
2155
2318
|
this.loadCurrentTab();
|
|
2156
2319
|
}
|
|
2157
2320
|
loadCurrentTab(query = { page: 1, pageSize: 25 }) {
|
|
2321
|
+
if (this.adminMode()) {
|
|
2322
|
+
this.facade.getAdmin(query);
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2158
2325
|
if (this.activeTab() === 'my') {
|
|
2159
2326
|
this.facade.getMy(query);
|
|
2160
2327
|
}
|
|
2161
2328
|
else {
|
|
2162
|
-
this.facade.getAssigned(
|
|
2329
|
+
this.facade.getAssigned({
|
|
2330
|
+
...query,
|
|
2331
|
+
status: query.status ?? this.assignedStatus() ?? undefined,
|
|
2332
|
+
});
|
|
2163
2333
|
}
|
|
2164
2334
|
}
|
|
2165
2335
|
reloadCurrentTab() {
|
|
@@ -2180,6 +2350,9 @@ class DelegationsList {
|
|
|
2180
2350
|
formatScopeSummary(value) {
|
|
2181
2351
|
return formatDelegationScopeSummary(value, this.transloco.getActiveLang());
|
|
2182
2352
|
}
|
|
2353
|
+
getListedParty(row) {
|
|
2354
|
+
return this.activeTab() === 'my' ? row.delegatedUser : row.delegator;
|
|
2355
|
+
}
|
|
2183
2356
|
viewDetails(row) {
|
|
2184
2357
|
this.modal.openModal(DelegationDetailDrawer, 'drawer', {
|
|
2185
2358
|
header: this.transloco.translate('delegations.action.view'),
|
|
@@ -2235,7 +2408,7 @@ class DelegationsList {
|
|
|
2235
2408
|
cancel(row) {
|
|
2236
2409
|
this.mark(`cancel:${row.delegationId}`, true);
|
|
2237
2410
|
this.facade
|
|
2238
|
-
.cancel(row.delegationId, row.rowVersion)
|
|
2411
|
+
.cancel(row.delegationId, row.rowVersion, this.adminMode())
|
|
2239
2412
|
.pipe(finalize(() => this.mark(`cancel:${row.delegationId}`, false)))
|
|
2240
2413
|
.subscribe({ next: () => this.reloadCurrentTab() });
|
|
2241
2414
|
}
|
|
@@ -2256,7 +2429,7 @@ class DelegationsList {
|
|
|
2256
2429
|
this.busyIds.update((ids) => on ? [...ids, key] : ids.filter((id) => id !== key));
|
|
2257
2430
|
}
|
|
2258
2431
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2259
|
-
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 }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", 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: "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 <div class=\"flex flex-col
|
|
2432
|
+
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 }, 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 <div class=\"flex h-full flex-col gap-4 p-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n\n <mt-card [title]=\"surfaceTitle()\">\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 </mt-card>\n </div>\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 .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: "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: 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 });
|
|
2260
2433
|
}
|
|
2261
2434
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, decorators: [{
|
|
2262
2435
|
type: Component,
|
|
@@ -2264,11 +2437,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2264
2437
|
CommonModule,
|
|
2265
2438
|
Avatar,
|
|
2266
2439
|
Breadcrumb,
|
|
2440
|
+
Card,
|
|
2267
2441
|
Table,
|
|
2268
2442
|
TranslocoDirective,
|
|
2269
2443
|
DelegationStatusChip,
|
|
2270
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col
|
|
2271
|
-
}], propDecorators: { showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", required: false }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }], statusCol: [{ type: i0.ViewChild, args: ['statusCol', { isSignal: true }] }], userCol: [{ type: i0.ViewChild, args: ['userCol', { isSignal: true }] }], scopeCol: [{ type: i0.ViewChild, args: ['scopeCol', { isSignal: true }] }], daysCol: [{ type: i0.ViewChild, args: ['daysCol', { isSignal: true }] }] } });
|
|
2444
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex h-full flex-col gap-4 p-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n\n <mt-card [title]=\"surfaceTitle()\">\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 </mt-card>\n </div>\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 .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"] }]
|
|
2445
|
+
}], propDecorators: { showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", 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 }] }] } });
|
|
2272
2446
|
|
|
2273
2447
|
/**
|
|
2274
2448
|
* Endpoints that must NEVER carry the `app-delegation` header.
|
|
@@ -2301,5 +2475,5 @@ const appDelegationInterceptor = (req, next) => {
|
|
|
2301
2475
|
* Generated bundle index. Do not edit.
|
|
2302
2476
|
*/
|
|
2303
2477
|
|
|
2304
|
-
export { ApproveDelegation, CancelDelegation, ClearDelegationDetail, ClearScopePreview, CreateDelegationLegacy, CreateDelegationV2, DelegationDetailDrawer, DelegationForm, DelegationSessionActionKey, DelegationSessionFacade, DelegationSessionState, DelegationStatusChip, Delegations, DelegationsActionKey, DelegationsFacade, DelegationsList, DelegationsState, EndDelegationSession, GetActiveAssignedDelegations, GetAssignedDelegations, GetDelegationDetail, GetMyDelegations, GetScopeOptions, LoadDelegationCandidates, PreviewScope, RejectDelegation, RejectDelegationDialog, ScopePicker, StartDelegationSession, StartSessionDialog, SwitchDelegationSession, TopbarDelegationMenu, UpdateDelegationLegacy, UpdateDelegationV2, appDelegationInterceptor };
|
|
2478
|
+
export { ApproveDelegation, CancelDelegation, ClearDelegationDetail, ClearScopePreview, CreateDelegationLegacy, CreateDelegationV2, DelegationDetailDrawer, DelegationForm, DelegationSessionActionKey, DelegationSessionFacade, DelegationSessionState, DelegationStatusChip, Delegations, DelegationsActionKey, DelegationsFacade, DelegationsList, DelegationsState, EndDelegationSession, GetActiveAssignedDelegations, GetAdminDelegations, GetAssignedDelegations, GetDelegationDetail, GetMyDelegations, GetScopeOptions, LoadDelegationCandidates, PreviewScope, RejectDelegation, RejectDelegationDialog, ScopePicker, StartDelegationSession, StartSessionDialog, SwitchDelegationSession, TopbarDelegationMenu, UpdateDelegationLegacy, UpdateDelegationV2, appDelegationInterceptor };
|
|
2305
2479
|
//# sourceMappingURL=masterteam-delegations.mjs.map
|