@masterteam/delegations 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as i2
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
1
|
+
import * as i2 from '@angular/common';
|
|
2
|
+
import { CommonModule, Location } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { input, computed, Component, inject, Injectable, ChangeDetectionStrategy, viewChild, signal, model, effect, untracked, linkedSignal } from '@angular/core';
|
|
5
5
|
import { RouterLink, ActivatedRoute, Router, NavigationEnd, RouterOutlet } from '@angular/router';
|
|
@@ -19,14 +19,14 @@ 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';
|
|
25
26
|
import { DynamicForm } from '@masterteam/forms/dynamic-form';
|
|
27
|
+
import { Tree } from '@masterteam/components/tree';
|
|
26
28
|
import * as i1 from 'primeng/skeleton';
|
|
27
29
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
28
|
-
import * as i2 from 'primeng/tooltip';
|
|
29
|
-
import { TooltipModule } from 'primeng/tooltip';
|
|
30
30
|
|
|
31
31
|
const STATUS_VISUAL = {
|
|
32
32
|
Active: {
|
|
@@ -460,6 +460,7 @@ class TopbarDelegationMenu {
|
|
|
460
460
|
/** Path to the management page, e.g. `/control-panel/delegations` or `/delegations`. */
|
|
461
461
|
managePath = input('/delegations', ...(ngDevMode ? [{ debugName: "managePath" }] : /* istanbul ignore next */ []));
|
|
462
462
|
compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
|
|
463
|
+
showManageLink = input(true, ...(ngDevMode ? [{ debugName: "showManageLink" }] : /* istanbul ignore next */ []));
|
|
463
464
|
facade = inject(DelegationSessionFacade);
|
|
464
465
|
modal = inject(ModalService);
|
|
465
466
|
transloco = inject(TranslocoService);
|
|
@@ -507,7 +508,7 @@ class TopbarDelegationMenu {
|
|
|
507
508
|
});
|
|
508
509
|
}
|
|
509
510
|
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 });
|
|
511
|
+
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
512
|
}
|
|
512
513
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TopbarDelegationMenu, decorators: [{
|
|
513
514
|
type: Component,
|
|
@@ -520,8 +521,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
520
521
|
RouterLink,
|
|
521
522
|
TranslocoDirective,
|
|
522
523
|
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 }] }] } });
|
|
524
|
+
], 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"] }]
|
|
525
|
+
}], 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
526
|
|
|
526
527
|
// ---------------------------------------------------------------------------
|
|
527
528
|
// Lists / detail
|
|
@@ -540,6 +541,13 @@ class GetAssignedDelegations {
|
|
|
540
541
|
this.query = query;
|
|
541
542
|
}
|
|
542
543
|
}
|
|
544
|
+
class GetAdminDelegations {
|
|
545
|
+
query;
|
|
546
|
+
static type = '[Delegations] Get Admin Delegations';
|
|
547
|
+
constructor(query = {}) {
|
|
548
|
+
this.query = query;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
543
551
|
class GetActiveAssignedDelegations {
|
|
544
552
|
query;
|
|
545
553
|
static type = '[Delegations] Get Active Assigned Delegations';
|
|
@@ -652,6 +660,7 @@ var DelegationsActionKey;
|
|
|
652
660
|
(function (DelegationsActionKey) {
|
|
653
661
|
DelegationsActionKey["GetMy"] = "getMy";
|
|
654
662
|
DelegationsActionKey["GetAssigned"] = "getAssigned";
|
|
663
|
+
DelegationsActionKey["GetAdmin"] = "getAdmin";
|
|
655
664
|
DelegationsActionKey["GetActive"] = "getActive";
|
|
656
665
|
DelegationsActionKey["GetDetail"] = "getDetail";
|
|
657
666
|
DelegationsActionKey["GetScopeOptions"] = "getScopeOptions";
|
|
@@ -705,6 +714,9 @@ let DelegationsState = class DelegationsState {
|
|
|
705
714
|
static getAssigned(state) {
|
|
706
715
|
return state.assigned;
|
|
707
716
|
}
|
|
717
|
+
static getAdmin(state) {
|
|
718
|
+
return state.admin;
|
|
719
|
+
}
|
|
708
720
|
static getActive(state) {
|
|
709
721
|
return state.active;
|
|
710
722
|
}
|
|
@@ -746,6 +758,15 @@ let DelegationsState = class DelegationsState {
|
|
|
746
758
|
onSuccess: (response) => ({ assigned: response.data }),
|
|
747
759
|
});
|
|
748
760
|
}
|
|
761
|
+
getAdmin(ctx, { query }) {
|
|
762
|
+
const req$ = this.http.get(`${BASE}/All`, { params: buildListParams(query) });
|
|
763
|
+
return handleApiRequest({
|
|
764
|
+
ctx,
|
|
765
|
+
key: DelegationsActionKey.GetAdmin,
|
|
766
|
+
request$: req$,
|
|
767
|
+
onSuccess: (response) => ({ admin: response.data }),
|
|
768
|
+
});
|
|
769
|
+
}
|
|
749
770
|
getActive(ctx, { query }) {
|
|
750
771
|
const req$ = this.http.get(`${BASE}/user/activedelegations`, { params: buildListParams(query) });
|
|
751
772
|
return handleApiRequest({
|
|
@@ -876,6 +897,9 @@ __decorate([
|
|
|
876
897
|
__decorate([
|
|
877
898
|
Action(GetAssignedDelegations)
|
|
878
899
|
], DelegationsState.prototype, "getAssigned", null);
|
|
900
|
+
__decorate([
|
|
901
|
+
Action(GetAdminDelegations)
|
|
902
|
+
], DelegationsState.prototype, "getAdmin", null);
|
|
879
903
|
__decorate([
|
|
880
904
|
Action(GetActiveAssignedDelegations)
|
|
881
905
|
], DelegationsState.prototype, "getActive", null);
|
|
@@ -921,6 +945,9 @@ __decorate([
|
|
|
921
945
|
__decorate([
|
|
922
946
|
Selector()
|
|
923
947
|
], DelegationsState, "getAssigned", null);
|
|
948
|
+
__decorate([
|
|
949
|
+
Selector()
|
|
950
|
+
], DelegationsState, "getAdmin", null);
|
|
924
951
|
__decorate([
|
|
925
952
|
Selector()
|
|
926
953
|
], DelegationsState, "getActive", null);
|
|
@@ -945,6 +972,7 @@ DelegationsState = __decorate([
|
|
|
945
972
|
defaults: {
|
|
946
973
|
my: null,
|
|
947
974
|
assigned: null,
|
|
975
|
+
admin: null,
|
|
948
976
|
active: null,
|
|
949
977
|
detail: null,
|
|
950
978
|
scopeOptions: null,
|
|
@@ -956,7 +984,7 @@ DelegationsState = __decorate([
|
|
|
956
984
|
], DelegationsState);
|
|
957
985
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsState, decorators: [{
|
|
958
986
|
type: Injectable
|
|
959
|
-
}], propDecorators: { getMy: [], getAssigned: [], getActive: [], getDetail: [], clearDetail: [], getScopeOptions: [], previewScope: [], clearScopePreview: [], createLegacy: [], createV2: [], updateLegacy: [], updateV2: [], approve: [], reject: [], cancel: [] } });
|
|
987
|
+
}], propDecorators: { getMy: [], getAssigned: [], getAdmin: [], getActive: [], getDetail: [], clearDetail: [], getScopeOptions: [], previewScope: [], clearScopePreview: [], createLegacy: [], createV2: [], updateLegacy: [], updateV2: [], approve: [], reject: [], cancel: [] } });
|
|
960
988
|
|
|
961
989
|
class DelegationsFacade {
|
|
962
990
|
store = inject(Store);
|
|
@@ -965,6 +993,7 @@ class DelegationsFacade {
|
|
|
965
993
|
// ---------------------------------------------------------------------------
|
|
966
994
|
myPage = select(DelegationsState.getMy);
|
|
967
995
|
assignedPage = select(DelegationsState.getAssigned);
|
|
996
|
+
adminPage = select(DelegationsState.getAdmin);
|
|
968
997
|
activePage = select(DelegationsState.getActive);
|
|
969
998
|
detail = select(DelegationsState.getDetail);
|
|
970
999
|
scopeOptions = select(DelegationsState.getScopeOptions);
|
|
@@ -976,12 +1005,14 @@ class DelegationsFacade {
|
|
|
976
1005
|
// ---------------------------------------------------------------------------
|
|
977
1006
|
myItems = computed(() => this.myPage()?.items ?? [], ...(ngDevMode ? [{ debugName: "myItems" }] : /* istanbul ignore next */ []));
|
|
978
1007
|
assignedItems = computed(() => this.assignedPage()?.items ?? [], ...(ngDevMode ? [{ debugName: "assignedItems" }] : /* istanbul ignore next */ []));
|
|
1008
|
+
adminItems = computed(() => this.adminPage()?.items ?? [], ...(ngDevMode ? [{ debugName: "adminItems" }] : /* istanbul ignore next */ []));
|
|
979
1009
|
activeItems = computed(() => this.activePage()?.items ?? [], ...(ngDevMode ? [{ debugName: "activeItems" }] : /* istanbul ignore next */ []));
|
|
980
1010
|
// ---------------------------------------------------------------------------
|
|
981
1011
|
// Loading
|
|
982
1012
|
// ---------------------------------------------------------------------------
|
|
983
1013
|
isLoadingMy = computed(() => this.loadingActive().includes(DelegationsActionKey.GetMy), ...(ngDevMode ? [{ debugName: "isLoadingMy" }] : /* istanbul ignore next */ []));
|
|
984
1014
|
isLoadingAssigned = computed(() => this.loadingActive().includes(DelegationsActionKey.GetAssigned), ...(ngDevMode ? [{ debugName: "isLoadingAssigned" }] : /* istanbul ignore next */ []));
|
|
1015
|
+
isLoadingAdmin = computed(() => this.loadingActive().includes(DelegationsActionKey.GetAdmin), ...(ngDevMode ? [{ debugName: "isLoadingAdmin" }] : /* istanbul ignore next */ []));
|
|
985
1016
|
isLoadingActive = computed(() => this.loadingActive().includes(DelegationsActionKey.GetActive), ...(ngDevMode ? [{ debugName: "isLoadingActive" }] : /* istanbul ignore next */ []));
|
|
986
1017
|
isLoadingDetail = computed(() => this.loadingActive().includes(DelegationsActionKey.GetDetail), ...(ngDevMode ? [{ debugName: "isLoadingDetail" }] : /* istanbul ignore next */ []));
|
|
987
1018
|
isLoadingScopeOptions = computed(() => this.loadingActive().includes(DelegationsActionKey.GetScopeOptions), ...(ngDevMode ? [{ debugName: "isLoadingScopeOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -996,6 +1027,7 @@ class DelegationsFacade {
|
|
|
996
1027
|
// ---------------------------------------------------------------------------
|
|
997
1028
|
errorMy = computed(() => this.errors()[DelegationsActionKey.GetMy] ?? null, ...(ngDevMode ? [{ debugName: "errorMy" }] : /* istanbul ignore next */ []));
|
|
998
1029
|
errorAssigned = computed(() => this.errors()[DelegationsActionKey.GetAssigned] ?? null, ...(ngDevMode ? [{ debugName: "errorAssigned" }] : /* istanbul ignore next */ []));
|
|
1030
|
+
errorAdmin = computed(() => this.errors()[DelegationsActionKey.GetAdmin] ?? null, ...(ngDevMode ? [{ debugName: "errorAdmin" }] : /* istanbul ignore next */ []));
|
|
999
1031
|
errorDetail = computed(() => this.errors()[DelegationsActionKey.GetDetail] ?? null, ...(ngDevMode ? [{ debugName: "errorDetail" }] : /* istanbul ignore next */ []));
|
|
1000
1032
|
errorScopeOptions = computed(() => this.errors()[DelegationsActionKey.GetScopeOptions] ?? null, ...(ngDevMode ? [{ debugName: "errorScopeOptions" }] : /* istanbul ignore next */ []));
|
|
1001
1033
|
errorSave = computed(() => this.errors()[DelegationsActionKey.Create] ??
|
|
@@ -1010,6 +1042,9 @@ class DelegationsFacade {
|
|
|
1010
1042
|
getAssigned(query = {}) {
|
|
1011
1043
|
return this.store.dispatch(new GetAssignedDelegations(query));
|
|
1012
1044
|
}
|
|
1045
|
+
getAdmin(query = {}) {
|
|
1046
|
+
return this.store.dispatch(new GetAdminDelegations(query));
|
|
1047
|
+
}
|
|
1013
1048
|
getActive(query = {}) {
|
|
1014
1049
|
return this.store.dispatch(new GetActiveAssignedDelegations(query));
|
|
1015
1050
|
}
|
|
@@ -1493,6 +1528,16 @@ function normalizeGrant(g) {
|
|
|
1493
1528
|
constraints: g.constraints ?? [],
|
|
1494
1529
|
};
|
|
1495
1530
|
}
|
|
1531
|
+
function sameSelectionKeys(left, right) {
|
|
1532
|
+
const leftKeys = (left ?? [])
|
|
1533
|
+
.map((node) => node.key)
|
|
1534
|
+
.filter((key) => !!key);
|
|
1535
|
+
if (leftKeys.length !== right.length) {
|
|
1536
|
+
return false;
|
|
1537
|
+
}
|
|
1538
|
+
const rightSet = new Set(right);
|
|
1539
|
+
return leftKeys.every((key) => rightSet.has(key));
|
|
1540
|
+
}
|
|
1496
1541
|
/**
|
|
1497
1542
|
* Hierarchy-based scope picker (doc 03). Driven entirely by `scope/options`:
|
|
1498
1543
|
* - renders backend-owned Level -> Level Module -> operations hierarchy,
|
|
@@ -1520,9 +1565,24 @@ class ScopePicker {
|
|
|
1520
1565
|
isPreviewing = this.facade.isPreviewingScope;
|
|
1521
1566
|
errorOptions = this.facade.errorScopeOptions;
|
|
1522
1567
|
groups = computed(() => getDelegationGrantableGroups(this.options()), ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
1568
|
+
activeLang = toSignal(this.transloco.langChanges$, {
|
|
1569
|
+
initialValue: this.transloco.getActiveLang(),
|
|
1570
|
+
});
|
|
1523
1571
|
/** Selected grant keys for O(1) checkbox state. */
|
|
1524
1572
|
selectedKeys = computed(() => new Set(this.scope().grants.map(grantKey)), ...(ngDevMode ? [{ debugName: "selectedKeys" }] : /* istanbul ignore next */ []));
|
|
1525
|
-
|
|
1573
|
+
treeSelection = signal([], ...(ngDevMode ? [{ debugName: "treeSelection" }] : /* istanbul ignore next */ []));
|
|
1574
|
+
treeNodes = computed(() => this.buildTreeNodes(this.groups()), ...(ngDevMode ? [{ debugName: "treeNodes" }] : /* istanbul ignore next */ []));
|
|
1575
|
+
grantIndex = computed(() => {
|
|
1576
|
+
const index = new Map();
|
|
1577
|
+
for (const group of this.groups()) {
|
|
1578
|
+
for (const targetGroup of group.targets) {
|
|
1579
|
+
for (const grant of targetGroup.grants) {
|
|
1580
|
+
index.set(grantKey(grant), normalizeGrant(grant));
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
return index;
|
|
1585
|
+
}, ...(ngDevMode ? [{ debugName: "grantIndex" }] : /* istanbul ignore next */ []));
|
|
1526
1586
|
constructor() {
|
|
1527
1587
|
// Load (and reload) grantable options whenever the delegator changes.
|
|
1528
1588
|
let initialized = false;
|
|
@@ -1538,7 +1598,7 @@ class ScopePicker {
|
|
|
1538
1598
|
if (lastDelegatorUserId !== delegator) {
|
|
1539
1599
|
lastDelegatorUserId = delegator;
|
|
1540
1600
|
this.scope.set(EMPTY_SCOPE$1);
|
|
1541
|
-
this.
|
|
1601
|
+
this.treeSelection.set([]);
|
|
1542
1602
|
this.facade.clearScopePreview();
|
|
1543
1603
|
}
|
|
1544
1604
|
});
|
|
@@ -1555,33 +1615,29 @@ class ScopePicker {
|
|
|
1555
1615
|
timer = setTimeout(() => this.facade.previewScope(s), 300);
|
|
1556
1616
|
});
|
|
1557
1617
|
});
|
|
1618
|
+
effect(() => {
|
|
1619
|
+
const selectedKeys = Array.from(this.selectedKeys());
|
|
1620
|
+
const selection = this.treeSelection();
|
|
1621
|
+
if (sameSelectionKeys(selection, selectedKeys)) {
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
this.treeSelection.set(selectedKeys.map((key) => ({
|
|
1625
|
+
key,
|
|
1626
|
+
})));
|
|
1627
|
+
});
|
|
1558
1628
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
const
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
return this.selectedKeys().has(grantKey(grant));
|
|
1572
|
-
}
|
|
1573
|
-
getGroupLabel(group) {
|
|
1574
|
-
return (formatDelegationDisplayValue(group.displayName, this.currentLanguage()) ||
|
|
1575
|
-
humanizeDelegationKey(group.groupType));
|
|
1576
|
-
}
|
|
1577
|
-
getTargetLabel(target) {
|
|
1578
|
-
return formatDelegationTargetLabel(target, this.currentLanguage());
|
|
1579
|
-
}
|
|
1580
|
-
getActionLabel(grant) {
|
|
1581
|
-
return formatDelegationActionLabel(grant.action, this.currentLanguage());
|
|
1582
|
-
}
|
|
1583
|
-
getTargetActions(targetGroup) {
|
|
1584
|
-
return targetGroup.grants;
|
|
1629
|
+
onTreeAction(event) {
|
|
1630
|
+
if (event.action !== 'selectionChange' || this.readonly()) {
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
const index = this.grantIndex();
|
|
1634
|
+
const grants = (this.treeSelection() ?? [])
|
|
1635
|
+
.map((node) => (node.key ? index.get(node.key) : undefined))
|
|
1636
|
+
.filter((grant) => !!grant);
|
|
1637
|
+
this.scope.update((scope) => ({
|
|
1638
|
+
...scope,
|
|
1639
|
+
grants,
|
|
1640
|
+
}));
|
|
1585
1641
|
}
|
|
1586
1642
|
getPreviewSummary(summary) {
|
|
1587
1643
|
return formatDelegationScopeSummary(summary, this.currentLanguage());
|
|
@@ -1592,46 +1648,98 @@ class ScopePicker {
|
|
|
1592
1648
|
formatDeniedTarget(value) {
|
|
1593
1649
|
return humanizeDelegationKey(value);
|
|
1594
1650
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
: [...s.grants, normalizeGrant(grant)];
|
|
1604
|
-
return { ...s, grants };
|
|
1605
|
-
});
|
|
1651
|
+
buildTreeNodes(groups) {
|
|
1652
|
+
return groups.map((group) => ({
|
|
1653
|
+
key: `group:${group.key}`,
|
|
1654
|
+
label: this.getGroupLabel(group),
|
|
1655
|
+
selectable: false,
|
|
1656
|
+
expanded: true,
|
|
1657
|
+
children: group.targets.map((targetGroup) => this.buildTargetNode(targetGroup)),
|
|
1658
|
+
}));
|
|
1606
1659
|
}
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1660
|
+
buildTargetNode(targetGroup) {
|
|
1661
|
+
return {
|
|
1662
|
+
key: `target:${targetGroup.key}`,
|
|
1663
|
+
label: this.getTargetLabel(targetGroup),
|
|
1664
|
+
selectable: false,
|
|
1665
|
+
expanded: true,
|
|
1666
|
+
children: targetGroup.grants.map((grant) => ({
|
|
1667
|
+
key: grantKey(grant),
|
|
1668
|
+
label: this.getActionLabel(grant),
|
|
1669
|
+
selectable: !this.readonly(),
|
|
1670
|
+
})),
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
getGroupLabel(group) {
|
|
1674
|
+
return group.displayName
|
|
1675
|
+
? humanizeDelegationDisplay(group.displayName, this.currentLanguage())
|
|
1676
|
+
: humanizeDelegationKey(group.groupType);
|
|
1611
1677
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1678
|
+
getTargetLabel(targetGroup) {
|
|
1679
|
+
return formatDelegationTargetLabel(targetGroup.target, this.currentLanguage());
|
|
1680
|
+
}
|
|
1681
|
+
getActionLabel(grant) {
|
|
1682
|
+
return formatDelegationActionLabel(grant.action, this.currentLanguage());
|
|
1616
1683
|
}
|
|
1617
1684
|
currentLanguage() {
|
|
1618
|
-
return this.transloco.getActiveLang();
|
|
1685
|
+
return this.activeLang() ?? this.transloco.getActiveLang();
|
|
1619
1686
|
}
|
|
1620
1687
|
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=\"
|
|
1688
|
+
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=\"flex flex-col gap-4\">\n @if (isLoadingOptions()) {\n <p-skeleton height=\"2rem\"></p-skeleton>\n <p-skeleton height=\"8rem\"></p-skeleton>\n <p-skeleton height=\"8rem\"></p-skeleton>\n } @else {\n <section class=\"flex flex-col gap-3\">\n @if (errorOptions(); as errorMessage) {\n <div\n class=\"rounded-xl 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 <div\n class=\"rounded-xl border border-dashed border-surface-300 bg-surface-50 px-4 py-3 text-sm text-surface-500\"\n >\n {{ t(\"delegations.scope.noGrantableOptions\") }}\n </div>\n }\n\n @if (groups().length > 0) {\n <div class=\"rounded-2xl border border-surface-200 bg-surface-0 p-2\">\n <mt-tree\n [value]=\"treeNodes()\"\n [(selection)]=\"treeSelection\"\n selectionMode=\"checkbox\"\n [loading]=\"isLoadingOptions()\"\n [checkAllChildren]=\"!readonly()\"\n (action)=\"onTreeAction($event)\"\n [filter]=\"true\"\n filterMode=\"lenient\"\n scrollHeight=\"22rem\"\n [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"68\"\n />\n </div>\n }\n </section>\n\n <section\n class=\"flex flex-col gap-2 rounded-2xl border border-dashed border-surface-300 bg-surface-50 px-4 py-3\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-sm font-medium text-surface-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-surface-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-surface-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </div>\n }\n </section>\n }\n </div>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Tree, selector: "mt-tree", inputs: ["value", "selection", "selectionMode", "nodeIcon", "propagateSelectionUp", "propagateSelectionDown", "checkAllChildren", "loading", "emptyMessage", "checkAllLabel", "filterPlaceholder", "dataKey", "filter", "filterMode", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "styleClass", "style", "pInputs", "nodeActions", "nodeContextmenuActions", "contextMenuSelection"], outputs: ["selectionChange", "contextMenuSelectionChange", "action"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1622
1689
|
}
|
|
1623
1690
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ScopePicker, decorators: [{
|
|
1624
1691
|
type: Component,
|
|
1625
|
-
args: [{ selector: 'mt-scope-picker',
|
|
1626
|
-
CommonModule,
|
|
1627
|
-
Icon,
|
|
1628
|
-
SkeletonModule,
|
|
1629
|
-
TooltipModule,
|
|
1630
|
-
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 <h4 class=\"text-sm font-medium text-gray-800\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </h4>\n\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}.mt-scope-picker__group{border-top:1px solid color-mix(in srgb,var(--p-surface-200, #e5e7eb) 65%,transparent)}.mt-scope-picker input[type=checkbox]{accent-color:var(--p-primary-color, currentColor)}\n"] }]
|
|
1692
|
+
args: [{ selector: 'mt-scope-picker', imports: [CommonModule, Tree, SkeletonModule, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col gap-4\">\n @if (isLoadingOptions()) {\n <p-skeleton height=\"2rem\"></p-skeleton>\n <p-skeleton height=\"8rem\"></p-skeleton>\n <p-skeleton height=\"8rem\"></p-skeleton>\n } @else {\n <section class=\"flex flex-col gap-3\">\n @if (errorOptions(); as errorMessage) {\n <div\n class=\"rounded-xl 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 <div\n class=\"rounded-xl border border-dashed border-surface-300 bg-surface-50 px-4 py-3 text-sm text-surface-500\"\n >\n {{ t(\"delegations.scope.noGrantableOptions\") }}\n </div>\n }\n\n @if (groups().length > 0) {\n <div class=\"rounded-2xl border border-surface-200 bg-surface-0 p-2\">\n <mt-tree\n [value]=\"treeNodes()\"\n [(selection)]=\"treeSelection\"\n selectionMode=\"checkbox\"\n [loading]=\"isLoadingOptions()\"\n [checkAllChildren]=\"!readonly()\"\n (action)=\"onTreeAction($event)\"\n [filter]=\"true\"\n filterMode=\"lenient\"\n scrollHeight=\"22rem\"\n [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"68\"\n />\n </div>\n }\n </section>\n\n <section\n class=\"flex flex-col gap-2 rounded-2xl border border-dashed border-surface-300 bg-surface-50 px-4 py-3\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-sm font-medium text-surface-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-surface-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-surface-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </div>\n }\n </section>\n }\n </div>\n</ng-container>\n" }]
|
|
1632
1693
|
}], 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 }] }] } });
|
|
1694
|
+
function humanizeDelegationDisplay(value, language) {
|
|
1695
|
+
return (formatDelegationScopeSummary(value, language) ||
|
|
1696
|
+
humanizeDelegationKey(typeof value === 'string' ? value : null));
|
|
1697
|
+
}
|
|
1633
1698
|
|
|
1634
1699
|
const EMPTY_SCOPE = { grants: [], metadata: {} };
|
|
1700
|
+
function getCurrentDelegatorFromLocalStorage() {
|
|
1701
|
+
if (typeof localStorage === 'undefined') {
|
|
1702
|
+
return null;
|
|
1703
|
+
}
|
|
1704
|
+
try {
|
|
1705
|
+
const raw = localStorage.getItem('auth');
|
|
1706
|
+
if (!raw)
|
|
1707
|
+
return null;
|
|
1708
|
+
const parsed = JSON.parse(raw);
|
|
1709
|
+
if (!parsed || typeof parsed !== 'object')
|
|
1710
|
+
return null;
|
|
1711
|
+
const state = (parsed['state'] ?? parsed) ||
|
|
1712
|
+
null;
|
|
1713
|
+
const userWrapper = state?.['user'];
|
|
1714
|
+
const user = userWrapper?.['user'] ??
|
|
1715
|
+
userWrapper;
|
|
1716
|
+
if (!user || typeof user !== 'object')
|
|
1717
|
+
return null;
|
|
1718
|
+
const id = user['id'] ??
|
|
1719
|
+
user['userId'];
|
|
1720
|
+
if (!id)
|
|
1721
|
+
return null;
|
|
1722
|
+
const photo = user['photo'];
|
|
1723
|
+
const photoPath = typeof photo === 'string'
|
|
1724
|
+
? photo
|
|
1725
|
+
: (photo?.fileName ?? null);
|
|
1726
|
+
return {
|
|
1727
|
+
id,
|
|
1728
|
+
userId: id,
|
|
1729
|
+
displayName: user['displayName'] ??
|
|
1730
|
+
user['name'] ??
|
|
1731
|
+
user['userName'] ??
|
|
1732
|
+
'',
|
|
1733
|
+
userName: user['userName'] ?? '',
|
|
1734
|
+
email: user['email'] ?? null,
|
|
1735
|
+
photo: photoPath,
|
|
1736
|
+
isExternal: !!user['isExternal'],
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
catch {
|
|
1740
|
+
return null;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1635
1743
|
function extractUserId(value) {
|
|
1636
1744
|
if (typeof value === 'string') {
|
|
1637
1745
|
return value.trim() || undefined;
|
|
@@ -1680,13 +1788,15 @@ class DelegationForm {
|
|
|
1680
1788
|
isSaving = this.facade.isSaving;
|
|
1681
1789
|
context = new HttpContext().set(REQUEST_CONTEXT, { useBaseUrl: false });
|
|
1682
1790
|
scope = signal(EMPTY_SCOPE, ...(ngDevMode ? [{ debugName: "scope" }] : /* istanbul ignore next */ []));
|
|
1683
|
-
|
|
1791
|
+
currentDelegator = signal(getCurrentDelegatorFromLocalStorage(), ...(ngDevMode ? [{ debugName: "currentDelegator" }] : /* istanbul ignore next */ []));
|
|
1792
|
+
/** Selected delegator id drives scope/options loading and the admin payload. */
|
|
1684
1793
|
selectedDelegatorId = computed(() => {
|
|
1685
|
-
if (
|
|
1686
|
-
return
|
|
1687
|
-
|
|
1794
|
+
if (this.adminMode()) {
|
|
1795
|
+
return extractUserId(this.formValue()?.delegateFrom);
|
|
1796
|
+
}
|
|
1797
|
+
return this.currentDelegator()?.id;
|
|
1688
1798
|
}, ...(ngDevMode ? [{ debugName: "selectedDelegatorId" }] : /* istanbul ignore next */ []));
|
|
1689
|
-
/**
|
|
1799
|
+
/** Admin mode waits for a chosen delegator; self-service always has one. */
|
|
1690
1800
|
showScopePicker = computed(() => !this.adminMode() || !!this.selectedDelegatorId(), ...(ngDevMode ? [{ debugName: "showScopePicker" }] : /* istanbul ignore next */ []));
|
|
1691
1801
|
specificDaysOptions = signal([
|
|
1692
1802
|
{ label: this.transloco.translate('delegations.days.sunday'), value: 0 },
|
|
@@ -1705,21 +1815,19 @@ class DelegationForm {
|
|
|
1705
1815
|
bodyClass: 'grid grid-cols-1 gap-4 items-start lg:grid-cols-12',
|
|
1706
1816
|
order: 1,
|
|
1707
1817
|
fields: [
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
]
|
|
1722
|
-
: []),
|
|
1818
|
+
new UserSearchFieldConfig({
|
|
1819
|
+
key: 'delegateFrom',
|
|
1820
|
+
label: this.transloco.translate('delegations.column.delegatorName'),
|
|
1821
|
+
apiUrl: 'Identity/users',
|
|
1822
|
+
context: this.context,
|
|
1823
|
+
validators: [ValidatorConfig.required()],
|
|
1824
|
+
cssClass: this.halfWidth,
|
|
1825
|
+
colSpan: 6,
|
|
1826
|
+
order: 0,
|
|
1827
|
+
disabled: this.readonly() ||
|
|
1828
|
+
!this.adminMode() ||
|
|
1829
|
+
!!this.delegationForEdit(),
|
|
1830
|
+
}),
|
|
1723
1831
|
new UserSearchFieldConfig({
|
|
1724
1832
|
key: 'delegateTo',
|
|
1725
1833
|
label: this.transloco.translate('delegations.column.delegatedTo'),
|
|
@@ -1819,6 +1927,7 @@ class DelegationForm {
|
|
|
1819
1927
|
const d = this.detail();
|
|
1820
1928
|
if (editing && d && d.row.delegationId === editing.delegationId) {
|
|
1821
1929
|
this.delegationFormControl.patchValue({
|
|
1930
|
+
delegateFrom: this.mapPartyToUserValue(d.row.delegator),
|
|
1822
1931
|
delegateTo: d.row.delegatedUser,
|
|
1823
1932
|
description: '',
|
|
1824
1933
|
delegateFromDateTime: d.row.startsAtUtc,
|
|
@@ -1834,12 +1943,26 @@ class DelegationForm {
|
|
|
1834
1943
|
}
|
|
1835
1944
|
else if (!editing) {
|
|
1836
1945
|
this.delegationFormControl.reset({
|
|
1946
|
+
delegateFrom: null,
|
|
1837
1947
|
delegationDaysType: 'FullRange',
|
|
1838
1948
|
requiresApproval: true,
|
|
1839
1949
|
});
|
|
1840
1950
|
this.scope.set(EMPTY_SCOPE);
|
|
1841
1951
|
}
|
|
1842
1952
|
});
|
|
1953
|
+
effect(() => {
|
|
1954
|
+
const currentDelegator = this.currentDelegator();
|
|
1955
|
+
if (this.adminMode() || this.delegationForEdit() || !currentDelegator) {
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
const existingDelegator = extractUserId(this.delegationFormControl.getRawValue()?.delegateFrom);
|
|
1959
|
+
if (existingDelegator === currentDelegator.id) {
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
this.delegationFormControl.patchValue({
|
|
1963
|
+
delegateFrom: currentDelegator,
|
|
1964
|
+
});
|
|
1965
|
+
});
|
|
1843
1966
|
}
|
|
1844
1967
|
ngOnInit() {
|
|
1845
1968
|
const editing = this.delegationForEdit();
|
|
@@ -1893,8 +2016,19 @@ class DelegationForm {
|
|
|
1893
2016
|
});
|
|
1894
2017
|
}
|
|
1895
2018
|
}
|
|
2019
|
+
mapPartyToUserValue(party) {
|
|
2020
|
+
return {
|
|
2021
|
+
id: party.userId,
|
|
2022
|
+
userId: party.userId,
|
|
2023
|
+
displayName: party.displayName,
|
|
2024
|
+
userName: party.email || party.displayName,
|
|
2025
|
+
email: party.email ?? null,
|
|
2026
|
+
photo: null,
|
|
2027
|
+
isExternal: false,
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
1896
2030
|
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 '
|
|
2031
|
+
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 'flex h-full min-h-0 min-w-0 flex-col overflow-hidden ' +\n modal.contentClass\n \"\n >\n <div\n class=\"flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-4 max-[640px]:p-3\"\n >\n <section\n class=\"flex flex-col gap-4 rounded-2xl border border-surface-200 bg-surface-0 p-4\"\n >\n <mt-dynamic-form\n [formConfig]=\"formConfig()\"\n [formControl]=\"delegationFormControl\"\n />\n </section>\n\n <section\n class=\"flex flex-col gap-4 rounded-2xl border border-surface-200 bg-surface-0 p-4\"\n >\n <div class=\"flex flex-col gap-1\">\n <h3 class=\"text-sm font-semibold text-surface-900\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </h3>\n @if (adminMode() && !showScopePicker()) {\n <p class=\"text-xs text-surface-500\">\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </p>\n }\n </div>\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\n class=\"rounded-xl border border-dashed border-surface-300 bg-surface-50 px-4 py-3 text-sm text-surface-500\"\n >\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </div>\n }\n </section>\n </div>\n\n <div\n [class]=\"\n 'flex shrink-0 flex-col gap-2 sm:flex-row sm:items-center sm:justify-end ' +\n modal.footerClass\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 </div>\n</ng-container>\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
2032
|
}
|
|
1899
2033
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationForm, decorators: [{
|
|
1900
2034
|
type: Component,
|
|
@@ -1905,7 +2039,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1905
2039
|
ReactiveFormsModule,
|
|
1906
2040
|
ScopePicker,
|
|
1907
2041
|
TranslocoDirective,
|
|
1908
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n '
|
|
2042
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n 'flex h-full min-h-0 min-w-0 flex-col overflow-hidden ' +\n modal.contentClass\n \"\n >\n <div\n class=\"flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-4 max-[640px]:p-3\"\n >\n <section\n class=\"flex flex-col gap-4 rounded-2xl border border-surface-200 bg-surface-0 p-4\"\n >\n <mt-dynamic-form\n [formConfig]=\"formConfig()\"\n [formControl]=\"delegationFormControl\"\n />\n </section>\n\n <section\n class=\"flex flex-col gap-4 rounded-2xl border border-surface-200 bg-surface-0 p-4\"\n >\n <div class=\"flex flex-col gap-1\">\n <h3 class=\"text-sm font-semibold text-surface-900\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </h3>\n @if (adminMode() && !showScopePicker()) {\n <p class=\"text-xs text-surface-500\">\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </p>\n }\n </div>\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\n class=\"rounded-xl border border-dashed border-surface-300 bg-surface-50 px-4 py-3 text-sm text-surface-500\"\n >\n {{ t(\"delegations.form.selectDelegatorFirst\") }}\n </div>\n }\n </section>\n </div>\n\n <div\n [class]=\"\n 'flex shrink-0 flex-col gap-2 sm:flex-row sm:items-center sm:justify-end ' +\n modal.footerClass\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 </div>\n</ng-container>\n" }]
|
|
1909
2043
|
}], 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
2044
|
|
|
1911
2045
|
/**
|
|
@@ -1944,7 +2078,7 @@ class DelegationDetailDrawer {
|
|
|
1944
2078
|
return formatDelegationScopeSummary(summary, this.transloco.getActiveLang());
|
|
1945
2079
|
}
|
|
1946
2080
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationDetailDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1947
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationDetailDrawer, isStandalone: true, selector: "mt-delegation-detail-drawer", inputs: { delegationId: { classPropertyName: "delegationId", publicName: "delegationId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col h-full\">\n <!-- Tabs -->\n <div class=\"flex border-b border-gray-200 px-4\">\n @for (tab of tabs; track tab.key) {\n <button\n type=\"button\"\n class=\"px-3 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.key\"\n [class.text-primary]=\"activeTab() === tab.key\"\n [class.border-transparent]=\"activeTab() !== tab.key\"\n [class.text-gray-500]=\"activeTab() !== tab.key\"\n (click)=\"setTab(tab.key)\"\n >\n {{ t(tab.i18n) }}\n </button>\n }\n </div>\n\n <!-- Body -->\n <div class=\"flex-1 overflow-y-auto p-4\">\n @if (isLoading() && !detail()) {\n <p-skeleton height=\"2rem\" class=\"mb-3\"></p-skeleton>\n <p-skeleton height=\"6rem\" class=\"mb-3\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n } @else if (detail(); as d) {\n @if (activeTab() === \"overview\") {\n <div class=\"flex flex-col gap-4\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-3 min-w-0\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-12! h-12! text-lg!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0\">\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.delegatorName\") }}\n </div>\n <div class=\"text-base font-medium text-gray-900 truncate\">\n {{ d.row.delegator.displayName }}\n </div>\n @if (d.row.delegator.email) {\n <div class=\"text-xs text-gray-500 truncate\">\n {{ d.row.delegator.email }}\n </div>\n }\n </div>\n </div>\n <mt-delegation-status-chip\n [status]=\"d.status.effectiveStatus\"\n ></mt-delegation-status-chip>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4\">\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.delegatedTo\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n {{ d.row.delegatedUser.displayName }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.approval\") }}\n </span>\n <span class=\"text-sm text-gray-900\">{{ approvalLabel() }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.startDate\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n {{ d.row.startsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.endDate\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n {{ d.row.endsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.form.timeZone\") }}\n </span>\n <span class=\"text-sm text-gray-900\">{{\n d.row.timeZoneId\n }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.days\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n @if (d.row.dayRuleMode === \"FullRange\") {\n {{ t(\"delegations.form.fullRange\") }}\n } @else {\n {{ d.row.specificDays.join(\", \") }}\n }\n </span>\n </div>\n </div>\n\n @if (d.row.cancellation?.cancellationReason) {\n <div\n class=\"rounded-md border border-gray-200 bg-surface-50 p-3 text-sm text-gray-800\"\n >\n <div class=\"font-medium\">\n {{ t(\"delegations.form.cancellationReason\") }}\n </div>\n <div>{{ d.row.cancellation.cancellationReason }}</div>\n </div>\n }\n </div>\n } @else {\n <!-- Scope tab -->\n <div class=\"flex flex-col gap-3\">\n <div class=\"text-sm text-gray-900\">\n {{\n formatScopeSummary(d.row.scopeSummary) ||\n t(\"delegations.column.scopeSummary\")\n }}\n </div>\n <div class=\"flex flex-col gap-2\">\n @for (grant of d.scope.grants; track $index) {\n <div\n class=\"border border-gray-200 rounded-md px-3 py-2 flex flex-col gap-1\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <span class=\"text-sm font-medium text-gray-900\">\n {{ getScopeTargetLabel(grant.target) }}\n </span>\n <span class=\"text-xs text-gray-500\">\n {{ grant.target.targetType }}\n </span>\n </div>\n <span\n class=\"text-xs px-2 py-0.5 rounded-md bg-primary-50 text-primary w-fit\"\n >\n {{ getScopeActionLabel(grant.action) }}\n </span>\n </div>\n }\n @if (d.scope.grants.length === 0) {\n <p class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </p>\n }\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Footer -->\n <div\n class=\"border-t border-gray-200 px-4 py-3 flex items-center justify-end\"\n >\n <mt-button\n [label]=\"t('delegations.common.cancel')\"\n variant=\"outlined\"\n (click)=\"ref.close()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n", styles: [":host{display:block;height:100%}\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: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { 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"] }, { kind: "pipe", type: i2
|
|
2081
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationDetailDrawer, isStandalone: true, selector: "mt-delegation-detail-drawer", inputs: { delegationId: { classPropertyName: "delegationId", publicName: "delegationId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col h-full\">\n <!-- Tabs -->\n <div class=\"flex border-b border-gray-200 px-4\">\n @for (tab of tabs; track tab.key) {\n <button\n type=\"button\"\n class=\"px-3 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.key\"\n [class.text-primary]=\"activeTab() === tab.key\"\n [class.border-transparent]=\"activeTab() !== tab.key\"\n [class.text-gray-500]=\"activeTab() !== tab.key\"\n (click)=\"setTab(tab.key)\"\n >\n {{ t(tab.i18n) }}\n </button>\n }\n </div>\n\n <!-- Body -->\n <div class=\"flex-1 overflow-y-auto p-4\">\n @if (isLoading() && !detail()) {\n <p-skeleton height=\"2rem\" class=\"mb-3\"></p-skeleton>\n <p-skeleton height=\"6rem\" class=\"mb-3\"></p-skeleton>\n <p-skeleton height=\"6rem\"></p-skeleton>\n } @else if (detail(); as d) {\n @if (activeTab() === \"overview\") {\n <div class=\"flex flex-col gap-4\">\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-3 min-w-0\">\n <mt-avatar\n icon=\"user.user-01\"\n styleClass=\"w-12! h-12! text-lg!\"\n ></mt-avatar>\n <div class=\"flex flex-col min-w-0\">\n <div class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.delegatorName\") }}\n </div>\n <div class=\"text-base font-medium text-gray-900 truncate\">\n {{ d.row.delegator.displayName }}\n </div>\n @if (d.row.delegator.email) {\n <div class=\"text-xs text-gray-500 truncate\">\n {{ d.row.delegator.email }}\n </div>\n }\n </div>\n </div>\n <mt-delegation-status-chip\n [status]=\"d.status.effectiveStatus\"\n ></mt-delegation-status-chip>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4\">\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.delegatedTo\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n {{ d.row.delegatedUser.displayName }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.approval\") }}\n </span>\n <span class=\"text-sm text-gray-900\">{{ approvalLabel() }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.startDate\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n {{ d.row.startsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.endDate\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n {{ d.row.endsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.form.timeZone\") }}\n </span>\n <span class=\"text-sm text-gray-900\">{{\n d.row.timeZoneId\n }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-gray-500\">\n {{ t(\"delegations.column.days\") }}\n </span>\n <span class=\"text-sm text-gray-900\">\n @if (d.row.dayRuleMode === \"FullRange\") {\n {{ t(\"delegations.form.fullRange\") }}\n } @else {\n {{ d.row.specificDays.join(\", \") }}\n }\n </span>\n </div>\n </div>\n\n @if (d.row.cancellation?.cancellationReason) {\n <div\n class=\"rounded-md border border-gray-200 bg-surface-50 p-3 text-sm text-gray-800\"\n >\n <div class=\"font-medium\">\n {{ t(\"delegations.form.cancellationReason\") }}\n </div>\n <div>{{ d.row.cancellation.cancellationReason }}</div>\n </div>\n }\n </div>\n } @else {\n <!-- Scope tab -->\n <div class=\"flex flex-col gap-3\">\n <div class=\"text-sm text-gray-900\">\n {{\n formatScopeSummary(d.row.scopeSummary) ||\n t(\"delegations.column.scopeSummary\")\n }}\n </div>\n <div class=\"flex flex-col gap-2\">\n @for (grant of d.scope.grants; track $index) {\n <div\n class=\"border border-gray-200 rounded-md px-3 py-2 flex flex-col gap-1\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <span class=\"text-sm font-medium text-gray-900\">\n {{ getScopeTargetLabel(grant.target) }}\n </span>\n <span class=\"text-xs text-gray-500\">\n {{ grant.target.targetType }}\n </span>\n </div>\n <span\n class=\"text-xs px-2 py-0.5 rounded-md bg-primary-50 text-primary w-fit\"\n >\n {{ getScopeActionLabel(grant.action) }}\n </span>\n </div>\n }\n @if (d.scope.grants.length === 0) {\n <p class=\"text-xs text-gray-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </p>\n }\n </div>\n </div>\n }\n }\n </div>\n\n <!-- Footer -->\n <div\n class=\"border-t border-gray-200 px-4 py-3 flex items-center justify-end\"\n >\n <mt-button\n [label]=\"t('delegations.common.cancel')\"\n variant=\"outlined\"\n (click)=\"ref.close()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n", styles: [":host{display:block;height:100%}\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: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { 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"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1948
2082
|
}
|
|
1949
2083
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationDetailDrawer, decorators: [{
|
|
1950
2084
|
type: Component,
|
|
@@ -1978,7 +2112,13 @@ class DelegationsList {
|
|
|
1978
2112
|
* `withComponentInputBinding()` — admin passes `data: { adminMode: true }`.
|
|
1979
2113
|
*/
|
|
1980
2114
|
adminMode = input(false, ...(ngDevMode ? [{ debugName: "adminMode" }] : /* istanbul ignore next */ []));
|
|
2115
|
+
surfaceTitleKey = input('delegations.title', ...(ngDevMode ? [{ debugName: "surfaceTitleKey" }] : /* istanbul ignore next */ []));
|
|
2116
|
+
assignedTabLabelKey = input('delegations.delegatedToMe', ...(ngDevMode ? [{ debugName: "assignedTabLabelKey" }] : /* istanbul ignore next */ []));
|
|
2117
|
+
assignedDecisionTab = input(false, ...(ngDevMode ? [{ debugName: "assignedDecisionTab" }] : /* istanbul ignore next */ []));
|
|
2118
|
+
assignedEmptyStateKey = input('delegations.empty.assigned', ...(ngDevMode ? [{ debugName: "assignedEmptyStateKey" }] : /* istanbul ignore next */ []));
|
|
2119
|
+
assignedStatus = input(null, ...(ngDevMode ? [{ debugName: "assignedStatus" }] : /* istanbul ignore next */ []));
|
|
1981
2120
|
facade = inject(DelegationsFacade);
|
|
2121
|
+
location = inject(Location);
|
|
1982
2122
|
modal = inject(ModalService);
|
|
1983
2123
|
transloco = inject(TranslocoService);
|
|
1984
2124
|
breadcrumbItems = linkedSignal(() => [
|
|
@@ -1996,30 +2136,47 @@ class DelegationsList {
|
|
|
1996
2136
|
},
|
|
1997
2137
|
], ...(ngDevMode ? [{ debugName: "breadcrumbItems" }] : /* istanbul ignore next */ []));
|
|
1998
2138
|
activeTab = signal('my', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
1999
|
-
|
|
2139
|
+
surfaceTitle = computed(() => this.transloco.translate(this.surfaceTitleKey()), ...(ngDevMode ? [{ debugName: "surfaceTitle" }] : /* istanbul ignore next */ []));
|
|
2140
|
+
tabs = computed(() => [
|
|
2000
2141
|
{
|
|
2001
2142
|
value: 'my',
|
|
2002
2143
|
label: this.transloco.translate('delegations.myDelegations'),
|
|
2003
2144
|
},
|
|
2004
2145
|
{
|
|
2005
2146
|
value: 'assigned',
|
|
2006
|
-
label: this.
|
|
2147
|
+
label: this.assignedDecisionTab()
|
|
2148
|
+
? `${this.transloco.translate('delegations.action.approve')} / ${this.transloco.translate('delegations.action.reject')}`
|
|
2149
|
+
: this.transloco.translate(this.assignedTabLabelKey()),
|
|
2007
2150
|
},
|
|
2008
2151
|
], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
2009
|
-
isLoading = computed(() => this.
|
|
2010
|
-
? this.facade.
|
|
2011
|
-
: this.
|
|
2152
|
+
isLoading = computed(() => this.adminMode()
|
|
2153
|
+
? this.facade.isLoadingAdmin()
|
|
2154
|
+
: this.activeTab() === 'my'
|
|
2155
|
+
? this.facade.isLoadingMy()
|
|
2156
|
+
: this.facade.isLoadingAssigned(), ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
2157
|
+
isLoadingScopeOptions = this.facade.isLoadingScopeOptions;
|
|
2012
2158
|
scopeOptions = this.facade.scopeOptions;
|
|
2013
|
-
rows = computed(() => this.
|
|
2014
|
-
? this.facade.
|
|
2015
|
-
: this.
|
|
2159
|
+
rows = computed(() => this.adminMode()
|
|
2160
|
+
? this.facade.adminItems()
|
|
2161
|
+
: this.activeTab() === 'my'
|
|
2162
|
+
? this.facade.myItems()
|
|
2163
|
+
: this.facade.assignedItems(), ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
2164
|
+
emptyStateKey = computed(() => this.adminMode()
|
|
2165
|
+
? 'components.table.no-data-found'
|
|
2166
|
+
: this.activeTab() === 'my'
|
|
2167
|
+
? 'delegations.empty.my'
|
|
2168
|
+
: this.assignedEmptyStateKey(), ...(ngDevMode ? [{ debugName: "emptyStateKey" }] : /* istanbul ignore next */ []));
|
|
2016
2169
|
statusCol = viewChild.required('statusCol');
|
|
2017
2170
|
userCol = viewChild.required('userCol');
|
|
2171
|
+
delegatorCol = viewChild.required('delegatorCol');
|
|
2172
|
+
delegatedUserCol = viewChild.required('delegatedUserCol');
|
|
2018
2173
|
scopeCol = viewChild.required('scopeCol');
|
|
2019
2174
|
daysCol = viewChild.required('daysCol');
|
|
2020
2175
|
canCreate = computed(() => {
|
|
2021
2176
|
if (this.adminMode())
|
|
2022
2177
|
return true;
|
|
2178
|
+
if (this.isLoadingScopeOptions())
|
|
2179
|
+
return true;
|
|
2023
2180
|
return hasDelegationGrantableScope(this.scopeOptions());
|
|
2024
2181
|
}, ...(ngDevMode ? [{ debugName: "canCreate" }] : /* istanbul ignore next */ []));
|
|
2025
2182
|
tableActions = computed(() => this.canCreate()
|
|
@@ -2084,56 +2241,80 @@ class DelegationsList {
|
|
|
2084
2241
|
hidden: (row) => !this.has(row, 'StartSession'),
|
|
2085
2242
|
},
|
|
2086
2243
|
], ...(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
|
-
|
|
2244
|
+
tableColumns = linkedSignal(() => {
|
|
2245
|
+
const baseColumns = [
|
|
2246
|
+
{
|
|
2247
|
+
key: 'effectiveStatus',
|
|
2248
|
+
label: this.transloco.translate('delegations.column.status'),
|
|
2249
|
+
type: 'custom',
|
|
2250
|
+
customCellTpl: this.statusCol(),
|
|
2251
|
+
width: '10rem',
|
|
2252
|
+
},
|
|
2253
|
+
{
|
|
2254
|
+
key: 'scopeSummary',
|
|
2255
|
+
label: this.transloco.translate('delegations.column.scopeSummary'),
|
|
2256
|
+
type: 'custom',
|
|
2257
|
+
customCellTpl: this.scopeCol(),
|
|
2258
|
+
width: '18rem',
|
|
2259
|
+
},
|
|
2260
|
+
{
|
|
2261
|
+
key: 'startsAtUtc',
|
|
2262
|
+
label: this.transloco.translate('delegations.column.startDate'),
|
|
2263
|
+
type: 'dateTime',
|
|
2264
|
+
width: '11rem',
|
|
2265
|
+
},
|
|
2266
|
+
{
|
|
2267
|
+
key: 'endsAtUtc',
|
|
2268
|
+
label: this.transloco.translate('delegations.column.endDate'),
|
|
2269
|
+
type: 'dateTime',
|
|
2270
|
+
width: '11rem',
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
key: 'createdAtUtc',
|
|
2274
|
+
label: this.transloco.translate('delegations.column.createdDate'),
|
|
2275
|
+
type: 'dateTime',
|
|
2276
|
+
width: '11rem',
|
|
2277
|
+
},
|
|
2278
|
+
{
|
|
2279
|
+
key: 'dayRuleMode',
|
|
2280
|
+
label: this.transloco.translate('delegations.column.days'),
|
|
2281
|
+
type: 'custom',
|
|
2282
|
+
customCellTpl: this.daysCol(),
|
|
2283
|
+
width: '12rem',
|
|
2284
|
+
},
|
|
2285
|
+
];
|
|
2286
|
+
if (this.adminMode()) {
|
|
2287
|
+
return [
|
|
2288
|
+
{
|
|
2289
|
+
key: 'delegator',
|
|
2290
|
+
label: this.transloco.translate('delegations.column.delegatorName'),
|
|
2291
|
+
type: 'custom',
|
|
2292
|
+
customCellTpl: this.delegatorCol(),
|
|
2293
|
+
width: '16rem',
|
|
2294
|
+
},
|
|
2295
|
+
{
|
|
2296
|
+
key: 'delegatedUser',
|
|
2297
|
+
label: this.transloco.translate('delegations.column.delegatedTo'),
|
|
2298
|
+
type: 'custom',
|
|
2299
|
+
customCellTpl: this.delegatedUserCol(),
|
|
2300
|
+
width: '16rem',
|
|
2301
|
+
},
|
|
2302
|
+
...baseColumns,
|
|
2303
|
+
];
|
|
2304
|
+
}
|
|
2305
|
+
return [
|
|
2306
|
+
{
|
|
2307
|
+
key: this.activeTab() === 'my' ? 'delegatedUser' : 'delegator',
|
|
2308
|
+
label: this.transloco.translate(this.activeTab() === 'my'
|
|
2309
|
+
? 'delegations.column.delegatedTo'
|
|
2310
|
+
: 'delegations.column.delegatorName'),
|
|
2311
|
+
type: 'custom',
|
|
2312
|
+
customCellTpl: this.userCol(),
|
|
2313
|
+
width: '16rem',
|
|
2314
|
+
},
|
|
2315
|
+
...baseColumns,
|
|
2316
|
+
];
|
|
2317
|
+
}, ...(ngDevMode ? [{ debugName: "tableColumns" }] : /* istanbul ignore next */ []));
|
|
2137
2318
|
busyIds = signal([], ...(ngDevMode ? [{ debugName: "busyIds" }] : /* istanbul ignore next */ []));
|
|
2138
2319
|
weekdayKeys = [
|
|
2139
2320
|
'sunday',
|
|
@@ -2154,12 +2335,22 @@ class DelegationsList {
|
|
|
2154
2335
|
this.activeTab.set(tab);
|
|
2155
2336
|
this.loadCurrentTab();
|
|
2156
2337
|
}
|
|
2338
|
+
goBack() {
|
|
2339
|
+
this.location.back();
|
|
2340
|
+
}
|
|
2157
2341
|
loadCurrentTab(query = { page: 1, pageSize: 25 }) {
|
|
2342
|
+
if (this.adminMode()) {
|
|
2343
|
+
this.facade.getAdmin(query);
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2158
2346
|
if (this.activeTab() === 'my') {
|
|
2159
2347
|
this.facade.getMy(query);
|
|
2160
2348
|
}
|
|
2161
2349
|
else {
|
|
2162
|
-
this.facade.getAssigned(
|
|
2350
|
+
this.facade.getAssigned({
|
|
2351
|
+
...query,
|
|
2352
|
+
status: query.status ?? this.assignedStatus() ?? undefined,
|
|
2353
|
+
});
|
|
2163
2354
|
}
|
|
2164
2355
|
}
|
|
2165
2356
|
reloadCurrentTab() {
|
|
@@ -2180,6 +2371,9 @@ class DelegationsList {
|
|
|
2180
2371
|
formatScopeSummary(value) {
|
|
2181
2372
|
return formatDelegationScopeSummary(value, this.transloco.getActiveLang());
|
|
2182
2373
|
}
|
|
2374
|
+
getListedParty(row) {
|
|
2375
|
+
return this.activeTab() === 'my' ? row.delegatedUser : row.delegator;
|
|
2376
|
+
}
|
|
2183
2377
|
viewDetails(row) {
|
|
2184
2378
|
this.modal.openModal(DelegationDetailDrawer, 'drawer', {
|
|
2185
2379
|
header: this.transloco.translate('delegations.action.view'),
|
|
@@ -2196,7 +2390,7 @@ class DelegationsList {
|
|
|
2196
2390
|
header: this.transloco.translate(row ? 'delegations.action.edit' : 'delegations.action.create'),
|
|
2197
2391
|
styleClass: row
|
|
2198
2392
|
? '!absolute !shadow-none !w-full !max-w-full sm:!w-[42rem] xl:!w-[50rem]'
|
|
2199
|
-
: '!w-[min(96vw,
|
|
2393
|
+
: '!w-[min(96vw,52rem)] !max-w-[96vw] !h-[min(92vh,46rem)] !max-h-[92vh] !overflow-hidden',
|
|
2200
2394
|
position: row ? 'end' : '',
|
|
2201
2395
|
appendTo: row ? 'page-content' : 'body',
|
|
2202
2396
|
dismissableMask: true,
|
|
@@ -2235,7 +2429,7 @@ class DelegationsList {
|
|
|
2235
2429
|
cancel(row) {
|
|
2236
2430
|
this.mark(`cancel:${row.delegationId}`, true);
|
|
2237
2431
|
this.facade
|
|
2238
|
-
.cancel(row.delegationId, row.rowVersion)
|
|
2432
|
+
.cancel(row.delegationId, row.rowVersion, this.adminMode())
|
|
2239
2433
|
.pipe(finalize(() => this.mark(`cancel:${row.delegationId}`, false)))
|
|
2240
2434
|
.subscribe({ next: () => this.reloadCurrentTab() });
|
|
2241
2435
|
}
|
|
@@ -2256,7 +2450,7 @@ class DelegationsList {
|
|
|
2256
2450
|
this.busyIds.update((ids) => on ? [...ids, key] : ids.filter((id) => id !== key));
|
|
2257
2451
|
}
|
|
2258
2452
|
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 h-full gap-2 p-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n\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 <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [freezeActions]=\"true\"\n [loading]=\"isLoading()\"\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 = activeTab() === \"my\" ? row.delegatedUser : row.delegator;\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 flex-col min-w-0\">\n <span class=\"text-sm text-gray-900 truncate\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"text-xs text-gray-500 truncate\">\n {{ party.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 || \"\u2014\" }}\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 </mt-table>\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: 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 });
|
|
2453
|
+
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 <ng-template #tableContent>\n <div class=\"flex flex-col gap-4\">\n @if (!adminMode()) {\n <div class=\"flex items-center gap-2 border-b border-gray-200\">\n @for (tab of tabs(); track tab.value) {\n <button\n type=\"button\"\n class=\"px-4 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.value\"\n [class.text-primary]=\"activeTab() === tab.value\"\n [class.border-transparent]=\"activeTab() !== tab.value\"\n [class.text-gray-500]=\"activeTab() !== tab.value\"\n (click)=\"switchTab(tab.value)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n }\n\n <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [freezeActions]=\"true\"\n [loading]=\"isLoading()\"\n [noCard]=\"true\"\n >\n <ng-template #statusCol let-row>\n <mt-delegation-status-chip\n [status]=\"row.effectiveStatus\"\n ></mt-delegation-status-chip>\n </ng-template>\n\n <ng-template #userCol let-row>\n @let party = getListedParty(row);\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ party.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatorCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegator?.displayName }}\n </span>\n @if (row.delegator?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegator.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatedUserCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegatedUser?.displayName }}\n </span>\n @if (row.delegatedUser?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegatedUser.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #scopeCol let-row>\n @let summary = formatScopeSummary(row.scopeSummary);\n <span class=\"text-sm text-gray-700\" [title]=\"summary\">\n {{ summary || \"--\" }}\n </span>\n </ng-template>\n\n <ng-template #daysCol let-row>\n <span class=\"text-sm text-gray-700\">{{ formatDays(row) }}</span>\n </ng-template>\n\n <ng-template #empty>\n <p class=\"text-sm text-surface-500\">\n {{ t(emptyStateKey()) }}\n </p>\n </ng-template>\n </mt-table>\n </div>\n </ng-template>\n\n @if (adminMode()) {\n <mt-page\n [title]=\"surfaceTitle()\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-indigo-50)',\n '--p-avatar-color': 'var(--p-indigo-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <div class=\"flex min-h-full flex-col gap-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </div>\n </mt-page>\n } @else {\n <div class=\"flex h-full flex-col gap-4 p-4\">\n <mt-card [title]=\"surfaceTitle()\">\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </mt-card>\n </div>\n }\n</ng-container>\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table .p-datatable-table{min-width:72rem}:host ::ng-deep mt-table .mt-actions-column{min-width:14rem}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}:host ::ng-deep mt-table .p-datatable-header>div,:host ::ng-deep mt-table .p-datatable-header>div>div{gap:.75rem;min-width:0;flex-wrap:wrap}:host ::ng-deep mt-table .p-datatable-header mt-tabs{display:block;max-width:100%;overflow-x:auto;padding-bottom:.25rem}:host ::ng-deep mt-table .p-datatable-header mt-text-field{display:block;flex:1 1 16rem;min-width:min(100%,16rem)}:host ::ng-deep mt-table .p-datatable-header .p-inputtext,:host ::ng-deep mt-table .p-datatable-header .p-inputwrapper,:host ::ng-deep mt-table .p-datatable-header .p-selectbutton{width:100%;max-width:100%}@media(max-width:1024px){:host ::ng-deep mt-table .p-datatable-header>div{flex-direction:column;align-items:stretch}:host ::ng-deep mt-table .p-datatable-header>div>div{width:100%;justify-content:flex-start}:host ::ng-deep mt-table .p-datatable-header mt-text-field{flex-basis:100%;min-width:0}}@media(max-width:768px){:host ::ng-deep mt-table .p-datatable-table{min-width:64rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "exportable", "printable", "groupable", "cellClickFilter", "freezeActions", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DelegationStatusChip, selector: "mt-delegation-status-chip", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2260
2454
|
}
|
|
2261
2455
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, decorators: [{
|
|
2262
2456
|
type: Component,
|
|
@@ -2264,11 +2458,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2264
2458
|
CommonModule,
|
|
2265
2459
|
Avatar,
|
|
2266
2460
|
Breadcrumb,
|
|
2461
|
+
Card,
|
|
2462
|
+
Page,
|
|
2267
2463
|
Table,
|
|
2268
2464
|
TranslocoDirective,
|
|
2269
2465
|
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 }] }] } });
|
|
2466
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <ng-template #tableContent>\n <div class=\"flex flex-col gap-4\">\n @if (!adminMode()) {\n <div class=\"flex items-center gap-2 border-b border-gray-200\">\n @for (tab of tabs(); track tab.value) {\n <button\n type=\"button\"\n class=\"px-4 py-2 -mb-px border-b-2 text-sm font-medium transition-colors\"\n [class.border-primary]=\"activeTab() === tab.value\"\n [class.text-primary]=\"activeTab() === tab.value\"\n [class.border-transparent]=\"activeTab() !== tab.value\"\n [class.text-gray-500]=\"activeTab() !== tab.value\"\n (click)=\"switchTab(tab.value)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n }\n\n <mt-table\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n [actions]=\"tableActions()\"\n [rowActions]=\"rowActions()\"\n [freezeActions]=\"true\"\n [loading]=\"isLoading()\"\n [noCard]=\"true\"\n >\n <ng-template #statusCol let-row>\n <mt-delegation-status-chip\n [status]=\"row.effectiveStatus\"\n ></mt-delegation-status-chip>\n </ng-template>\n\n <ng-template #userCol let-row>\n @let party = getListedParty(row);\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ party?.displayName }}\n </span>\n @if (party?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ party.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatorCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegator?.displayName }}\n </span>\n @if (row.delegator?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegator.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #delegatedUserCol let-row>\n <div class=\"flex items-center gap-2\">\n <mt-avatar icon=\"user.user-01\" styleClass=\"w-8! h-8!\"></mt-avatar>\n <div class=\"flex min-w-0 flex-col\">\n <span class=\"truncate text-sm text-gray-900\">\n {{ row.delegatedUser?.displayName }}\n </span>\n @if (row.delegatedUser?.email) {\n <span class=\"truncate text-xs text-gray-500\">\n {{ row.delegatedUser.email }}\n </span>\n }\n </div>\n </div>\n </ng-template>\n\n <ng-template #scopeCol let-row>\n @let summary = formatScopeSummary(row.scopeSummary);\n <span class=\"text-sm text-gray-700\" [title]=\"summary\">\n {{ summary || \"--\" }}\n </span>\n </ng-template>\n\n <ng-template #daysCol let-row>\n <span class=\"text-sm text-gray-700\">{{ formatDays(row) }}</span>\n </ng-template>\n\n <ng-template #empty>\n <p class=\"text-sm text-surface-500\">\n {{ t(emptyStateKey()) }}\n </p>\n </ng-template>\n </mt-table>\n </div>\n </ng-template>\n\n @if (adminMode()) {\n <mt-page\n [title]=\"surfaceTitle()\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-indigo-50)',\n '--p-avatar-color': 'var(--p-indigo-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <div class=\"flex min-h-full flex-col gap-4\">\n @if (showBreadcrumb()) {\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\n }\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </div>\n </mt-page>\n } @else {\n <div class=\"flex h-full flex-col gap-4 p-4\">\n <mt-card [title]=\"surfaceTitle()\">\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\n </mt-card>\n </div>\n }\n</ng-container>\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table .p-datatable-table{min-width:72rem}:host ::ng-deep mt-table .mt-actions-column{min-width:14rem}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}:host ::ng-deep mt-table .p-datatable-header>div,:host ::ng-deep mt-table .p-datatable-header>div>div{gap:.75rem;min-width:0;flex-wrap:wrap}:host ::ng-deep mt-table .p-datatable-header mt-tabs{display:block;max-width:100%;overflow-x:auto;padding-bottom:.25rem}:host ::ng-deep mt-table .p-datatable-header mt-text-field{display:block;flex:1 1 16rem;min-width:min(100%,16rem)}:host ::ng-deep mt-table .p-datatable-header .p-inputtext,:host ::ng-deep mt-table .p-datatable-header .p-inputwrapper,:host ::ng-deep mt-table .p-datatable-header .p-selectbutton{width:100%;max-width:100%}@media(max-width:1024px){:host ::ng-deep mt-table .p-datatable-header>div{flex-direction:column;align-items:stretch}:host ::ng-deep mt-table .p-datatable-header>div>div{width:100%;justify-content:flex-start}:host ::ng-deep mt-table .p-datatable-header mt-text-field{flex-basis:100%;min-width:0}}@media(max-width:768px){:host ::ng-deep mt-table .p-datatable-table{min-width:64rem}}\n"] }]
|
|
2467
|
+
}], 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
2468
|
|
|
2273
2469
|
/**
|
|
2274
2470
|
* Endpoints that must NEVER carry the `app-delegation` header.
|
|
@@ -2301,5 +2497,5 @@ const appDelegationInterceptor = (req, next) => {
|
|
|
2301
2497
|
* Generated bundle index. Do not edit.
|
|
2302
2498
|
*/
|
|
2303
2499
|
|
|
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 };
|
|
2500
|
+
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
2501
|
//# sourceMappingURL=masterteam-delegations.mjs.map
|