@masterteam/delegations 0.0.42 → 0.0.44
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.
- package/assets/delegations.css +1 -1
- package/assets/i18n/ar.json +165 -164
- package/assets/i18n/en.json +165 -164
- package/fesm2022/masterteam-delegations.mjs +255 -139
- package/fesm2022/masterteam-delegations.mjs.map +1 -1
- package/package.json +4 -4
- package/types/masterteam-delegations.d.ts +89 -13
|
@@ -336,121 +336,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
336
336
|
args: [{ providedIn: 'root' }]
|
|
337
337
|
}] });
|
|
338
338
|
|
|
339
|
-
function isRecord$1(value) {
|
|
340
|
-
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
341
|
-
}
|
|
342
|
-
function readLocalizedValue(source, preferredLanguage) {
|
|
343
|
-
const normalizedLanguage = preferredLanguage.toLowerCase();
|
|
344
|
-
const baseLanguage = normalizedLanguage.split('-')[0];
|
|
345
|
-
const preferredKeys = normalizedLanguage.startsWith('ar')
|
|
346
|
-
? ['defaultAr', 'ar', normalizedLanguage, baseLanguage, 'defaultEn', 'en']
|
|
347
|
-
: ['defaultEn', 'en', normalizedLanguage, baseLanguage, 'defaultAr', 'ar'];
|
|
348
|
-
for (const key of preferredKeys) {
|
|
349
|
-
const value = source[key];
|
|
350
|
-
if (typeof value === 'string' && value.trim()) {
|
|
351
|
-
return value.trim();
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
for (const key of ['en', 'ar', 'defaultEn', 'defaultAr']) {
|
|
355
|
-
const value = source[key];
|
|
356
|
-
if (typeof value === 'string' && value.trim()) {
|
|
357
|
-
return value.trim();
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return null;
|
|
361
|
-
}
|
|
362
|
-
function parseJsonRecord(value) {
|
|
363
|
-
const trimmed = value.trim();
|
|
364
|
-
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
try {
|
|
368
|
-
const parsed = JSON.parse(trimmed);
|
|
369
|
-
return isRecord$1(parsed) ? parsed : null;
|
|
370
|
-
}
|
|
371
|
-
catch {
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
function resolveDisplayValue(value, preferredLanguage) {
|
|
376
|
-
if (typeof value === 'string') {
|
|
377
|
-
const trimmed = value.trim();
|
|
378
|
-
if (!trimmed) {
|
|
379
|
-
return null;
|
|
380
|
-
}
|
|
381
|
-
const parsed = parseJsonRecord(trimmed);
|
|
382
|
-
if (parsed) {
|
|
383
|
-
return (readLocalizedValue(parsed, preferredLanguage) ??
|
|
384
|
-
readDisplayValue(parsed, ['displayName', 'displayLabel', 'label'], preferredLanguage) ??
|
|
385
|
-
trimmed);
|
|
386
|
-
}
|
|
387
|
-
return trimmed;
|
|
388
|
-
}
|
|
389
|
-
if (!isRecord$1(value)) {
|
|
390
|
-
return null;
|
|
391
|
-
}
|
|
392
|
-
return (readLocalizedValue(value, preferredLanguage) ??
|
|
393
|
-
readDisplayValue(value, [
|
|
394
|
-
'displayName',
|
|
395
|
-
'displayLabel',
|
|
396
|
-
'operationDisplayName',
|
|
397
|
-
'operationLabel',
|
|
398
|
-
'label',
|
|
399
|
-
'name',
|
|
400
|
-
'value',
|
|
401
|
-
], preferredLanguage));
|
|
402
|
-
}
|
|
403
|
-
function readDisplayValue(source, keys, preferredLanguage) {
|
|
404
|
-
for (const key of keys) {
|
|
405
|
-
const value = resolveDisplayValue(source[key], preferredLanguage);
|
|
406
|
-
if (value) {
|
|
407
|
-
return value;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
function resolveDisplayOrHumanizedKey(source, displayKeys, fallbackKey, preferredLanguage = 'en') {
|
|
413
|
-
const displayValue = readDisplayValue(source, displayKeys, preferredLanguage);
|
|
414
|
-
if (displayValue) {
|
|
415
|
-
return displayValue;
|
|
416
|
-
}
|
|
417
|
-
return humanizeDelegationKey(fallbackKey);
|
|
418
|
-
}
|
|
419
|
-
function humanizeDelegationKey(value) {
|
|
420
|
-
if (!value) {
|
|
421
|
-
return '';
|
|
422
|
-
}
|
|
423
|
-
const normalized = value
|
|
424
|
-
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
425
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
426
|
-
.replace(/[._-]+/g, ' ')
|
|
427
|
-
.replace(/\s+/g, ' ')
|
|
428
|
-
.trim();
|
|
429
|
-
if (!normalized) {
|
|
430
|
-
return '';
|
|
431
|
-
}
|
|
432
|
-
return normalized.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
433
|
-
}
|
|
434
|
-
function formatDelegationDisplayValue(value, preferredLanguage = 'en') {
|
|
435
|
-
return resolveDisplayValue(value, preferredLanguage) ?? '';
|
|
436
|
-
}
|
|
437
|
-
function formatDelegationTargetLabel(target, preferredLanguage = 'en') {
|
|
438
|
-
return resolveDisplayOrHumanizedKey(target, ['name', 'displayName', 'displayLabel', 'label'], target.targetKey, preferredLanguage);
|
|
439
|
-
}
|
|
440
|
-
function formatDelegationActionLabel(action, preferredLanguage = 'en') {
|
|
441
|
-
return resolveDisplayOrHumanizedKey(action, [
|
|
442
|
-
'name',
|
|
443
|
-
'displayName',
|
|
444
|
-
'displayLabel',
|
|
445
|
-
'operationDisplayName',
|
|
446
|
-
'operationLabel',
|
|
447
|
-
'label',
|
|
448
|
-
], action.operationKey, preferredLanguage);
|
|
449
|
-
}
|
|
450
|
-
function formatDelegationScopeSummary(value, preferredLanguage = 'en') {
|
|
451
|
-
return formatDelegationDisplayValue(value, preferredLanguage);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
339
|
function toDelegationUserValue(party) {
|
|
455
340
|
const displayName = party?.displayName?.trim() || party?.email?.trim() || '';
|
|
456
341
|
return {
|
|
@@ -494,9 +379,6 @@ class StartSessionDialog {
|
|
|
494
379
|
successMessageKey = computed(() => this.intent() === 'switch'
|
|
495
380
|
? 'delegations.session.switched'
|
|
496
381
|
: 'delegations.session.started', ...(ngDevMode ? [{ debugName: "successMessageKey" }] : /* istanbul ignore next */ []));
|
|
497
|
-
formatScopeSummary(summary) {
|
|
498
|
-
return formatDelegationScopeSummary(summary, this.transloco.getActiveLang());
|
|
499
|
-
}
|
|
500
382
|
userEntity(party) {
|
|
501
383
|
return toDelegationUserEntity(party, { showEmail: false });
|
|
502
384
|
}
|
|
@@ -519,11 +401,11 @@ class StartSessionDialog {
|
|
|
519
401
|
this.ref.close(false);
|
|
520
402
|
}
|
|
521
403
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StartSessionDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
522
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
404
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: StartSessionDialog, isStandalone: true, selector: "mt-start-session-dialog", inputs: { delegation: { classPropertyName: "delegation", publicName: "delegation", isSignal: true, isRequired: true, transformFunction: null }, intent: { classPropertyName: "intent", publicName: "intent", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col gap-4 p-2\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex flex-col min-w-0\">\n <mt-entity-preview\n [data]=\"userEntity(delegation().delegator)\"\n ></mt-entity-preview>\n </div>\n </div>\n\n <p class=\"text-sm text-surface-600 leading-relaxed\">\n {{ t(bodyKey()) }}\n </p>\n\n <div class=\"flex justify-end gap-2 pt-2 border-t border-surface-200\">\n <mt-button\n variant=\"outlined\"\n color=\"secondary\"\n [label]=\"t('delegations.common.cancel')\"\n [disabled]=\"isBusy()\"\n (click)=\"cancel()\"\n ></mt-button>\n <mt-button\n color=\"primary\"\n icon=\"user.users-check\"\n [label]=\"t(confirmLabelKey())\"\n [loading]=\"isBusy()\"\n (click)=\"confirm()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n", 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: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
523
405
|
}
|
|
524
406
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StartSessionDialog, decorators: [{
|
|
525
407
|
type: Component,
|
|
526
|
-
args: [{ selector: 'mt-start-session-dialog', imports: [CommonModule, Button, EntityPreview, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\
|
|
408
|
+
args: [{ selector: 'mt-start-session-dialog', imports: [CommonModule, Button, EntityPreview, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col gap-4 p-2\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex flex-col min-w-0\">\n <mt-entity-preview\n [data]=\"userEntity(delegation().delegator)\"\n ></mt-entity-preview>\n </div>\n </div>\n\n <p class=\"text-sm text-surface-600 leading-relaxed\">\n {{ t(bodyKey()) }}\n </p>\n\n <div class=\"flex justify-end gap-2 pt-2 border-t border-surface-200\">\n <mt-button\n variant=\"outlined\"\n color=\"secondary\"\n [label]=\"t('delegations.common.cancel')\"\n [disabled]=\"isBusy()\"\n (click)=\"cancel()\"\n ></mt-button>\n <mt-button\n color=\"primary\"\n icon=\"user.users-check\"\n [label]=\"t(confirmLabelKey())\"\n [loading]=\"isBusy()\"\n (click)=\"confirm()\"\n ></mt-button>\n </div>\n </div>\n</ng-container>\n" }]
|
|
527
409
|
}], propDecorators: { delegation: [{ type: i0.Input, args: [{ isSignal: true, alias: "delegation", required: true }] }], intent: [{ type: i0.Input, args: [{ isSignal: true, alias: "intent", required: false }] }] } });
|
|
528
410
|
|
|
529
411
|
/**
|
|
@@ -1558,6 +1440,121 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1558
1440
|
args: [{ selector: 'mt-delegations', imports: [Page, RouterOutlet, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <mt-page\n [title]=\"t('delegations.title')\"\n [avatarIcon]=\"'custom.hierarchy-structure'\"\n [tabs]=\"tabs()\"\n [activeTab]=\"activeTab()\"\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 (tabChange)=\"onTabChange($event)\"\n (backButtonClick)=\"goBack()\"\n backButton\n >\n <router-outlet />\n </mt-page>\n</ng-container>\n" }]
|
|
1559
1441
|
}], ctorParameters: () => [] });
|
|
1560
1442
|
|
|
1443
|
+
function isRecord$1(value) {
|
|
1444
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
1445
|
+
}
|
|
1446
|
+
function readLocalizedValue(source, preferredLanguage) {
|
|
1447
|
+
const normalizedLanguage = preferredLanguage.toLowerCase();
|
|
1448
|
+
const baseLanguage = normalizedLanguage.split('-')[0];
|
|
1449
|
+
const preferredKeys = normalizedLanguage.startsWith('ar')
|
|
1450
|
+
? ['defaultAr', 'ar', normalizedLanguage, baseLanguage, 'defaultEn', 'en']
|
|
1451
|
+
: ['defaultEn', 'en', normalizedLanguage, baseLanguage, 'defaultAr', 'ar'];
|
|
1452
|
+
for (const key of preferredKeys) {
|
|
1453
|
+
const value = source[key];
|
|
1454
|
+
if (typeof value === 'string' && value.trim()) {
|
|
1455
|
+
return value.trim();
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
for (const key of ['en', 'ar', 'defaultEn', 'defaultAr']) {
|
|
1459
|
+
const value = source[key];
|
|
1460
|
+
if (typeof value === 'string' && value.trim()) {
|
|
1461
|
+
return value.trim();
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
return null;
|
|
1465
|
+
}
|
|
1466
|
+
function parseJsonRecord(value) {
|
|
1467
|
+
const trimmed = value.trim();
|
|
1468
|
+
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
|
|
1469
|
+
return null;
|
|
1470
|
+
}
|
|
1471
|
+
try {
|
|
1472
|
+
const parsed = JSON.parse(trimmed);
|
|
1473
|
+
return isRecord$1(parsed) ? parsed : null;
|
|
1474
|
+
}
|
|
1475
|
+
catch {
|
|
1476
|
+
return null;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
function resolveDisplayValue(value, preferredLanguage) {
|
|
1480
|
+
if (typeof value === 'string') {
|
|
1481
|
+
const trimmed = value.trim();
|
|
1482
|
+
if (!trimmed) {
|
|
1483
|
+
return null;
|
|
1484
|
+
}
|
|
1485
|
+
const parsed = parseJsonRecord(trimmed);
|
|
1486
|
+
if (parsed) {
|
|
1487
|
+
return (readLocalizedValue(parsed, preferredLanguage) ??
|
|
1488
|
+
readDisplayValue(parsed, ['displayName', 'displayLabel', 'label'], preferredLanguage) ??
|
|
1489
|
+
trimmed);
|
|
1490
|
+
}
|
|
1491
|
+
return trimmed;
|
|
1492
|
+
}
|
|
1493
|
+
if (!isRecord$1(value)) {
|
|
1494
|
+
return null;
|
|
1495
|
+
}
|
|
1496
|
+
return (readLocalizedValue(value, preferredLanguage) ??
|
|
1497
|
+
readDisplayValue(value, [
|
|
1498
|
+
'displayName',
|
|
1499
|
+
'displayLabel',
|
|
1500
|
+
'operationDisplayName',
|
|
1501
|
+
'operationLabel',
|
|
1502
|
+
'label',
|
|
1503
|
+
'name',
|
|
1504
|
+
'value',
|
|
1505
|
+
], preferredLanguage));
|
|
1506
|
+
}
|
|
1507
|
+
function readDisplayValue(source, keys, preferredLanguage) {
|
|
1508
|
+
for (const key of keys) {
|
|
1509
|
+
const value = resolveDisplayValue(source[key], preferredLanguage);
|
|
1510
|
+
if (value) {
|
|
1511
|
+
return value;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
return null;
|
|
1515
|
+
}
|
|
1516
|
+
function resolveDisplayOrHumanizedKey(source, displayKeys, fallbackKey, preferredLanguage = 'en') {
|
|
1517
|
+
const displayValue = readDisplayValue(source, displayKeys, preferredLanguage);
|
|
1518
|
+
if (displayValue) {
|
|
1519
|
+
return displayValue;
|
|
1520
|
+
}
|
|
1521
|
+
return humanizeDelegationKey(fallbackKey);
|
|
1522
|
+
}
|
|
1523
|
+
function humanizeDelegationKey(value) {
|
|
1524
|
+
if (!value) {
|
|
1525
|
+
return '';
|
|
1526
|
+
}
|
|
1527
|
+
const normalized = value
|
|
1528
|
+
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
1529
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
1530
|
+
.replace(/[._-]+/g, ' ')
|
|
1531
|
+
.replace(/\s+/g, ' ')
|
|
1532
|
+
.trim();
|
|
1533
|
+
if (!normalized) {
|
|
1534
|
+
return '';
|
|
1535
|
+
}
|
|
1536
|
+
return normalized.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
1537
|
+
}
|
|
1538
|
+
function formatDelegationDisplayValue(value, preferredLanguage = 'en') {
|
|
1539
|
+
return resolveDisplayValue(value, preferredLanguage) ?? '';
|
|
1540
|
+
}
|
|
1541
|
+
function formatDelegationTargetLabel(target, preferredLanguage = 'en') {
|
|
1542
|
+
return resolveDisplayOrHumanizedKey(target, ['name', 'displayName', 'displayLabel', 'label'], target.targetKey, preferredLanguage);
|
|
1543
|
+
}
|
|
1544
|
+
function formatDelegationActionLabel(action, preferredLanguage = 'en') {
|
|
1545
|
+
return resolveDisplayOrHumanizedKey(action, [
|
|
1546
|
+
'name',
|
|
1547
|
+
'displayName',
|
|
1548
|
+
'displayLabel',
|
|
1549
|
+
'operationDisplayName',
|
|
1550
|
+
'operationLabel',
|
|
1551
|
+
'label',
|
|
1552
|
+
], action.operationKey, preferredLanguage);
|
|
1553
|
+
}
|
|
1554
|
+
function formatDelegationScopeSummary(value, preferredLanguage = 'en') {
|
|
1555
|
+
return formatDelegationDisplayValue(value, preferredLanguage);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1561
1558
|
const DEFAULT_SORT_ORDER = Number.MAX_SAFE_INTEGER;
|
|
1562
1559
|
function toArray(value) {
|
|
1563
1560
|
return Array.isArray(value) ? value : [];
|
|
@@ -1852,7 +1849,7 @@ function hasDelegationGrantableScope(options) {
|
|
|
1852
1849
|
return (getDelegationPermissionTree(options).length > 0 ||
|
|
1853
1850
|
getDelegationGrantableGroups(options).length > 0);
|
|
1854
1851
|
}
|
|
1855
|
-
/** Stable selection key for an operation leaf
|
|
1852
|
+
/** Stable selection key for an operation leaf, independent of accessibilities. */
|
|
1856
1853
|
function delegationOperationNodeKey(grant) {
|
|
1857
1854
|
return `op:${targetIdentity(grant.target)}::${grant.action.operationKey}`;
|
|
1858
1855
|
}
|
|
@@ -2842,7 +2839,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2842
2839
|
}], 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 }] }] } });
|
|
2843
2840
|
|
|
2844
2841
|
/**
|
|
2845
|
-
* Read-only drawer that shows
|
|
2842
|
+
* Read-only drawer that shows `DelegationDetail` row/status plus saved scope
|
|
2843
|
+
* from `scopeView`. The persisted `scope.grants` shape is not parsed for
|
|
2844
|
+
* display; it remains a backend validation/persistence shape.
|
|
2846
2845
|
*/
|
|
2847
2846
|
class DelegationDetailDrawer {
|
|
2848
2847
|
delegationId = input.required(...(ngDevMode ? [{ debugName: "delegationId" }] : /* istanbul ignore next */ []));
|
|
@@ -2873,6 +2872,10 @@ class DelegationDetailDrawer {
|
|
|
2873
2872
|
isLoading = this.facade.isLoadingDetail;
|
|
2874
2873
|
detail = this.facade.detail;
|
|
2875
2874
|
row = computed(() => this.detail()?.row ?? null, ...(ngDevMode ? [{ debugName: "row" }] : /* istanbul ignore next */ []));
|
|
2875
|
+
scopeNodes = computed(() => this.buildScopeViewTree(this.detail()?.scopeView?.templates), ...(ngDevMode ? [{ debugName: "scopeNodes" }] : /* istanbul ignore next */ []));
|
|
2876
|
+
scopeVisibleNodes = computed(() => this.flattenScopeNodes(this.scopeNodes()), ...(ngDevMode ? [{ debugName: "scopeVisibleNodes" }] : /* istanbul ignore next */ []));
|
|
2877
|
+
selectedOperationCount = computed(() => this.scopeVisibleNodes().filter((node) => node.kind === 'operation')
|
|
2878
|
+
.length, ...(ngDevMode ? [{ debugName: "selectedOperationCount" }] : /* istanbul ignore next */ []));
|
|
2876
2879
|
ngOnInit() {
|
|
2877
2880
|
this.facade.getDetail(this.delegationId(), this.adminMode());
|
|
2878
2881
|
}
|
|
@@ -2889,20 +2892,104 @@ class DelegationDetailDrawer {
|
|
|
2889
2892
|
const s = this.row()?.approval?.approvalStatus ?? 'NotRequired';
|
|
2890
2893
|
return this.transloco.translate(`delegations.approvalStatus.${s}`);
|
|
2891
2894
|
}
|
|
2892
|
-
|
|
2893
|
-
return
|
|
2895
|
+
userEntity(party, label) {
|
|
2896
|
+
return toDelegationUserEntity(party, { label });
|
|
2897
|
+
}
|
|
2898
|
+
hasChildren(node) {
|
|
2899
|
+
return 'children' in node && node.children.length > 0;
|
|
2894
2900
|
}
|
|
2895
|
-
|
|
2896
|
-
return
|
|
2901
|
+
trackScopeNode(_index, node) {
|
|
2902
|
+
return node.key;
|
|
2897
2903
|
}
|
|
2898
|
-
|
|
2899
|
-
return
|
|
2904
|
+
buildScopeViewTree(templates) {
|
|
2905
|
+
return this.toArray(templates)
|
|
2906
|
+
.map((template) => this.toTemplateNode(template))
|
|
2907
|
+
.filter((node) => this.hasScopeChildren(node));
|
|
2900
2908
|
}
|
|
2901
|
-
|
|
2902
|
-
|
|
2909
|
+
flattenScopeNodes(nodes) {
|
|
2910
|
+
const out = [];
|
|
2911
|
+
const walk = (items) => {
|
|
2912
|
+
for (const node of items) {
|
|
2913
|
+
out.push(node);
|
|
2914
|
+
if ('children' in node) {
|
|
2915
|
+
walk(node.children);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
};
|
|
2919
|
+
walk(nodes);
|
|
2920
|
+
return out;
|
|
2921
|
+
}
|
|
2922
|
+
toTemplateNode(template) {
|
|
2923
|
+
const key = `tpl:${template.groupKey}`;
|
|
2924
|
+
return {
|
|
2925
|
+
kind: 'template',
|
|
2926
|
+
key,
|
|
2927
|
+
label: this.displayLabel(template.name, template.groupKey),
|
|
2928
|
+
fallbackKey: template.groupKey,
|
|
2929
|
+
isAvailable: template.isAvailable !== false,
|
|
2930
|
+
depth: 0,
|
|
2931
|
+
children: this.toArray(template.levels).flatMap((level) => this.toLevelNodes(level)),
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
toLevelNodes(level) {
|
|
2935
|
+
const operationNodes = this.toArray(level.operations)
|
|
2936
|
+
.filter((operation) => operation.selected !== false)
|
|
2937
|
+
.map((operation) => this.toOperationNode(operation, level.targetKey, 2));
|
|
2938
|
+
const moduleNodes = this.toArray(level.modules)
|
|
2939
|
+
.map((module) => this.toModuleNode(module))
|
|
2940
|
+
.filter((node) => this.hasScopeChildren(node));
|
|
2941
|
+
const children = [...operationNodes, ...moduleNodes];
|
|
2942
|
+
if (children.length === 0) {
|
|
2943
|
+
return [];
|
|
2944
|
+
}
|
|
2945
|
+
return [
|
|
2946
|
+
{
|
|
2947
|
+
kind: 'level',
|
|
2948
|
+
key: `lvl:${level.applicationKey}:${level.targetKey}`,
|
|
2949
|
+
label: this.displayLabel(level.name, level.targetKey),
|
|
2950
|
+
fallbackKey: level.targetKey,
|
|
2951
|
+
isAvailable: level.isAvailable !== false,
|
|
2952
|
+
depth: 1,
|
|
2953
|
+
children,
|
|
2954
|
+
},
|
|
2955
|
+
];
|
|
2956
|
+
}
|
|
2957
|
+
toModuleNode(module) {
|
|
2958
|
+
return {
|
|
2959
|
+
kind: 'module',
|
|
2960
|
+
key: `mod:${module.applicationKey}:${module.targetKey}`,
|
|
2961
|
+
label: this.displayLabel(module.name, module.targetKey),
|
|
2962
|
+
fallbackKey: module.targetKey,
|
|
2963
|
+
isAvailable: module.isAvailable !== false,
|
|
2964
|
+
depth: 2,
|
|
2965
|
+
children: this.toArray(module.operations)
|
|
2966
|
+
.filter((operation) => operation.selected !== false)
|
|
2967
|
+
.map((operation) => this.toOperationNode(operation, module.targetKey, 3)),
|
|
2968
|
+
};
|
|
2969
|
+
}
|
|
2970
|
+
toOperationNode(operation, parentKey, depth) {
|
|
2971
|
+
return {
|
|
2972
|
+
kind: 'operation',
|
|
2973
|
+
key: `op:${parentKey}:${operation.operationKey}`,
|
|
2974
|
+
label: this.displayLabel(operation.name ?? operation.displayName, operation.operationKey),
|
|
2975
|
+
fallbackKey: operation.operationKey,
|
|
2976
|
+
isAvailable: operation.isAvailable !== false,
|
|
2977
|
+
isHighRisk: operation.isHighRisk ?? false,
|
|
2978
|
+
depth,
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
displayLabel(value, fallbackKey) {
|
|
2982
|
+
return (formatDelegationDisplayValue(value, this.transloco.getActiveLang()) ||
|
|
2983
|
+
humanizeDelegationKey(fallbackKey));
|
|
2984
|
+
}
|
|
2985
|
+
toArray(value) {
|
|
2986
|
+
return Array.isArray(value) ? value : [];
|
|
2987
|
+
}
|
|
2988
|
+
hasScopeChildren(node) {
|
|
2989
|
+
return 'children' in node && node.children.length > 0;
|
|
2903
2990
|
}
|
|
2904
2991
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationDetailDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2905
|
-
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 }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <div class=\"flex flex-col h-full\">\r\n <!-- Tabs -->\r\n <div class=\"border-b border-surface-200 px-4 pt-2\">\r\n <mt-tabs\r\n mode=\"underline\"\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n fluid\r\n ></mt-tabs>\r\n </div>\r\n\r\n <!-- Body -->\r\n <div class=\"flex-1 overflow-y-auto p-4\">\r\n @if (isLoading() && !detail()) {\r\n <p-skeleton height=\"2rem\" class=\"mb-3\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" class=\"mb-3\"></p-skeleton>\r\n <p-skeleton height=\"6rem\"></p-skeleton>\r\n } @else if (detail(); as d) {\r\n @if (activeTab() === \"overview\") {\r\n <div class=\"flex flex-col gap-4\">\r\n <div class=\"flex items-center justify-between gap-3\">\r\n <div class=\"flex items-center gap-3 min-w-0\">\r\n <mt-entity-preview\r\n [data]=\"\r\n userEntity(\r\n d.row.delegator,\r\n t('delegations.column.delegatorName')\r\n )\r\n \"\r\n ></mt-entity-preview>\r\n </div>\r\n <mt-delegation-status-chip\r\n [status]=\"d.status.effectiveStatus\"\r\n ></mt-delegation-status-chip>\r\n </div>\r\n\r\n <div class=\"grid grid-cols-2 gap-4\">\r\n <div class=\"flex flex-col\">\r\n <mt-entity-preview\r\n [data]=\"\r\n userEntity(\r\n d.row.delegatedUser,\r\n t('delegations.column.delegatedTo')\r\n )\r\n \"\r\n ></mt-entity-preview>\r\n </div>\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-xs text-surface-500\">\r\n {{ t(\"delegations.column.approval\") }}\r\n </span>\r\n <span class=\"text-sm text-surface-900\">{{\r\n approvalLabel()\r\n }}</span>\r\n </div>\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-xs text-surface-500\">\r\n {{ t(\"delegations.column.startDate\") }}\r\n </span>\r\n <span class=\"text-sm text-surface-900\">\r\n {{ d.row.startsAtUtc | date: \"medium\" }}\r\n </span>\r\n </div>\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-xs text-surface-500\">\r\n {{ t(\"delegations.column.endDate\") }}\r\n </span>\r\n <span class=\"text-sm text-surface-900\">\r\n {{ d.row.endsAtUtc | date: \"medium\" }}\r\n </span>\r\n </div>\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-xs text-surface-500\">\r\n {{ t(\"delegations.form.timeZone\") }}\r\n </span>\r\n <span class=\"text-sm text-surface-900\">{{\r\n d.row.timeZoneId\r\n }}</span>\r\n </div>\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-xs text-surface-500\">\r\n {{ t(\"delegations.column.days\") }}\r\n </span>\r\n <span class=\"text-sm text-surface-900\">\r\n @if (d.row.dayRuleMode === \"FullRange\") {\r\n {{ t(\"delegations.form.fullRange\") }}\r\n } @else {\r\n {{ formatSpecificDays(d.row.specificDays) }}\r\n }\r\n </span>\r\n </div>\r\n </div>\r\n\r\n @if (d.row.cancellation?.cancellationReason) {\r\n <div\r\n class=\"rounded-md border border-surface-200 bg-surface-50 p-3 text-sm text-surface-800\"\r\n >\r\n <div class=\"font-medium\">\r\n {{ t(\"delegations.form.cancellationReason\") }}\r\n </div>\r\n <div>{{ d.row.cancellation.cancellationReason }}</div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- Scope tab -->\r\n <div class=\"flex flex-col gap-3\">\r\n <div class=\"text-sm text-surface-900\">\r\n {{\r\n formatScopeSummary(d.row.scopeSummary) ||\r\n t(\"delegations.column.scopeSummary\")\r\n }}\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n @for (grant of d.scope.grants; track $index) {\r\n <div\r\n class=\"border border-surface-200 rounded-md px-3 py-2 flex flex-col gap-1\"\r\n >\r\n <div class=\"flex items-center justify-between gap-2\">\r\n <span class=\"text-sm font-medium text-surface-900\">\r\n {{ getScopeTargetLabel(grant.target) }}\r\n </span>\r\n <span class=\"text-xs text-surface-500\">\r\n {{ grant.target.targetType }}\r\n </span>\r\n </div>\r\n <span\r\n class=\"text-xs px-2 py-0.5 rounded-md bg-primary-50 text-primary w-fit\"\r\n >\r\n {{ getScopeActionLabel(grant.action) }}\r\n </span>\r\n </div>\r\n }\r\n @if (d.scope.grants.length === 0) {\r\n <p class=\"text-xs text-surface-500\">\r\n {{ t(\"delegations.scope.noSelection\") }}\r\n </p>\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div\r\n class=\"border-t border-surface-200 px-4 py-3 flex items-center justify-end\"\r\n >\r\n <mt-button\r\n [label]=\"t('delegations.common.cancel')\"\r\n variant=\"outlined\"\r\n (click)=\"ref.close()\"\r\n ></mt-button>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}\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: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { 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: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2992
|
+
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 }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col h-full\">\n <!-- Tabs -->\n <div class=\"border-b border-surface-200 px-4 pt-2\">\n <mt-tabs\n mode=\"underline\"\n [(active)]=\"activeTab\"\n [options]=\"tabOptions()\"\n fluid\n ></mt-tabs>\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-entity-preview\n [data]=\"\n userEntity(\n d.row.delegator,\n t('delegations.column.delegatorName')\n )\n \"\n ></mt-entity-preview>\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 <mt-entity-preview\n [data]=\"\n userEntity(\n d.row.delegatedUser,\n t('delegations.column.delegatedTo')\n )\n \"\n ></mt-entity-preview>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.approval\") }}\n </span>\n <span class=\"text-sm text-surface-900\">{{\n approvalLabel()\n }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.startDate\") }}\n </span>\n <span class=\"text-sm text-surface-900\">\n {{ d.row.startsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.endDate\") }}\n </span>\n <span class=\"text-sm text-surface-900\">\n {{ d.row.endsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.form.timeZone\") }}\n </span>\n <span class=\"text-sm text-surface-900\">{{\n d.row.timeZoneId\n }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.days\") }}\n </span>\n <span class=\"text-sm text-surface-900\">\n @if (d.row.dayRuleMode === \"FullRange\") {\n {{ t(\"delegations.form.fullRange\") }}\n } @else {\n {{ formatSpecificDays(d.row.specificDays) }}\n }\n </span>\n </div>\n </div>\n\n @if (d.row.cancellation?.cancellationReason) {\n <div\n class=\"rounded-md border border-surface-200 bg-surface-50 p-3 text-sm text-surface-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\n class=\"flex flex-col overflow-hidden rounded-lg border border-surface\"\n >\n <div\n class=\"flex items-center justify-between gap-2 border-b border-surface bg-surface-50 px-3 py-2\"\n >\n <span class=\"text-xs font-semibold uppercase text-surface-500\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </span>\n @if (selectedOperationCount() > 0) {\n <span class=\"text-xs font-medium text-surface-500\">\n {{ selectedOperationCount() }}\n {{ t(\"delegations.scope.selected\") }}\n </span>\n }\n </div>\n\n @if (scopeVisibleNodes().length > 0) {\n <div class=\"flex max-h-[34rem] flex-col overflow-y-auto\">\n @for (\n node of scopeVisibleNodes();\n track trackScopeNode($index, node)\n ) {\n <div\n class=\"group flex min-h-10 items-center gap-2 pe-3 transition-colors hover:bg-surface-50\"\n [style.padding-inline-start.rem]=\"0.75 + node.depth * 1.25\"\n >\n @if (hasChildren(node)) {\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md text-surface-400\"\n aria-hidden=\"true\"\n >\n <svg\n viewBox=\"0 0 20 20\"\n class=\"size-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M5 7L10 12L15 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n } @else {\n <span class=\"size-6 shrink-0\"></span>\n }\n\n <span\n class=\"flex size-[18px] shrink-0 items-center justify-center rounded-[5px] border border-primary-500 bg-primary-500 text-white\"\n aria-hidden=\"true\"\n >\n <svg\n viewBox=\"0 0 16 16\"\n class=\"size-3\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <span\n class=\"min-w-0 flex-1 truncate text-sm\"\n [class.font-semibold]=\"node.kind === 'template'\"\n [class.text-surface-900]=\"node.kind === 'template'\"\n [class.font-medium]=\"\n node.kind === 'level' || node.kind === 'module'\n \"\n [class.text-surface-800]=\"\n node.kind === 'level' || node.kind === 'module'\n \"\n [class.text-surface-600]=\"node.kind === 'operation'\"\n >\n {{ node.label }}\n </span>\n\n @if (node.kind === \"operation\" && node.isHighRisk) {\n <span\n class=\"shrink-0 rounded-full bg-amber-100 px-2 py-0.5 text-[0.625rem] font-medium text-amber-700\"\n >\n {{ t(\"delegations.scope.highRisk\") }}\n </span>\n }\n\n @if (!node.isAvailable) {\n <span\n class=\"shrink-0 rounded-full bg-surface-100 px-2 py-0.5 text-[0.625rem] font-medium text-surface-500\"\n >\n {{ t(\"delegations.scope.unavailable\") }}\n </span>\n }\n </div>\n }\n </div>\n } @else {\n <p class=\"px-3 py-8 text-center text-sm text-surface-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </p>\n }\n </div>\n }\n }\n </div>\n\n <!-- Footer -->\n <div\n class=\"border-t border-surface-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: 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: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { 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: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2906
2993
|
}
|
|
2907
2994
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationDetailDrawer, decorators: [{
|
|
2908
2995
|
type: Component,
|
|
@@ -2914,7 +3001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2914
3001
|
Tabs,
|
|
2915
3002
|
TranslocoDirective,
|
|
2916
3003
|
DelegationStatusChip,
|
|
2917
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\
|
|
3004
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\n <div class=\"flex flex-col h-full\">\n <!-- Tabs -->\n <div class=\"border-b border-surface-200 px-4 pt-2\">\n <mt-tabs\n mode=\"underline\"\n [(active)]=\"activeTab\"\n [options]=\"tabOptions()\"\n fluid\n ></mt-tabs>\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-entity-preview\n [data]=\"\n userEntity(\n d.row.delegator,\n t('delegations.column.delegatorName')\n )\n \"\n ></mt-entity-preview>\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 <mt-entity-preview\n [data]=\"\n userEntity(\n d.row.delegatedUser,\n t('delegations.column.delegatedTo')\n )\n \"\n ></mt-entity-preview>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.approval\") }}\n </span>\n <span class=\"text-sm text-surface-900\">{{\n approvalLabel()\n }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.startDate\") }}\n </span>\n <span class=\"text-sm text-surface-900\">\n {{ d.row.startsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.endDate\") }}\n </span>\n <span class=\"text-sm text-surface-900\">\n {{ d.row.endsAtUtc | date: \"medium\" }}\n </span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.form.timeZone\") }}\n </span>\n <span class=\"text-sm text-surface-900\">{{\n d.row.timeZoneId\n }}</span>\n </div>\n <div class=\"flex flex-col\">\n <span class=\"text-xs text-surface-500\">\n {{ t(\"delegations.column.days\") }}\n </span>\n <span class=\"text-sm text-surface-900\">\n @if (d.row.dayRuleMode === \"FullRange\") {\n {{ t(\"delegations.form.fullRange\") }}\n } @else {\n {{ formatSpecificDays(d.row.specificDays) }}\n }\n </span>\n </div>\n </div>\n\n @if (d.row.cancellation?.cancellationReason) {\n <div\n class=\"rounded-md border border-surface-200 bg-surface-50 p-3 text-sm text-surface-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\n class=\"flex flex-col overflow-hidden rounded-lg border border-surface\"\n >\n <div\n class=\"flex items-center justify-between gap-2 border-b border-surface bg-surface-50 px-3 py-2\"\n >\n <span class=\"text-xs font-semibold uppercase text-surface-500\">\n {{ t(\"delegations.scope.permissionsTitle\") }}\n </span>\n @if (selectedOperationCount() > 0) {\n <span class=\"text-xs font-medium text-surface-500\">\n {{ selectedOperationCount() }}\n {{ t(\"delegations.scope.selected\") }}\n </span>\n }\n </div>\n\n @if (scopeVisibleNodes().length > 0) {\n <div class=\"flex max-h-[34rem] flex-col overflow-y-auto\">\n @for (\n node of scopeVisibleNodes();\n track trackScopeNode($index, node)\n ) {\n <div\n class=\"group flex min-h-10 items-center gap-2 pe-3 transition-colors hover:bg-surface-50\"\n [style.padding-inline-start.rem]=\"0.75 + node.depth * 1.25\"\n >\n @if (hasChildren(node)) {\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md text-surface-400\"\n aria-hidden=\"true\"\n >\n <svg\n viewBox=\"0 0 20 20\"\n class=\"size-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M5 7L10 12L15 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n } @else {\n <span class=\"size-6 shrink-0\"></span>\n }\n\n <span\n class=\"flex size-[18px] shrink-0 items-center justify-center rounded-[5px] border border-primary-500 bg-primary-500 text-white\"\n aria-hidden=\"true\"\n >\n <svg\n viewBox=\"0 0 16 16\"\n class=\"size-3\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <span\n class=\"min-w-0 flex-1 truncate text-sm\"\n [class.font-semibold]=\"node.kind === 'template'\"\n [class.text-surface-900]=\"node.kind === 'template'\"\n [class.font-medium]=\"\n node.kind === 'level' || node.kind === 'module'\n \"\n [class.text-surface-800]=\"\n node.kind === 'level' || node.kind === 'module'\n \"\n [class.text-surface-600]=\"node.kind === 'operation'\"\n >\n {{ node.label }}\n </span>\n\n @if (node.kind === \"operation\" && node.isHighRisk) {\n <span\n class=\"shrink-0 rounded-full bg-amber-100 px-2 py-0.5 text-[0.625rem] font-medium text-amber-700\"\n >\n {{ t(\"delegations.scope.highRisk\") }}\n </span>\n }\n\n @if (!node.isAvailable) {\n <span\n class=\"shrink-0 rounded-full bg-surface-100 px-2 py-0.5 text-[0.625rem] font-medium text-surface-500\"\n >\n {{ t(\"delegations.scope.unavailable\") }}\n </span>\n }\n </div>\n }\n </div>\n } @else {\n <p class=\"px-3 py-8 text-center text-sm text-surface-500\">\n {{ t(\"delegations.scope.noSelection\") }}\n </p>\n }\n </div>\n }\n }\n </div>\n\n <!-- Footer -->\n <div\n class=\"border-t border-surface-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"] }]
|
|
2918
3005
|
}], propDecorators: { delegationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "delegationId", required: true }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }] } });
|
|
2919
3006
|
|
|
2920
3007
|
function defaultTrueBooleanAttribute(value) {
|
|
@@ -2986,6 +3073,13 @@ class DelegationsList {
|
|
|
2986
3073
|
tab = input(null, { ...(ngDevMode ? { debugName: "tab" } : /* istanbul ignore next */ {}), transform: normalizeTab });
|
|
2987
3074
|
/** Bound from the `?view=<id>` query param (detail drawer). */
|
|
2988
3075
|
view = input(null, { ...(ngDevMode ? { debugName: "view" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
3076
|
+
/** Back-compatible notification deep-link aliases for opening details. */
|
|
3077
|
+
selected = input(null, { ...(ngDevMode ? { debugName: "selected" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
3078
|
+
itemSelected = input(null, { ...(ngDevMode ? { debugName: "itemSelected" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
3079
|
+
selectedItemId = input(null, { ...(ngDevMode ? { debugName: "selectedItemId" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
3080
|
+
selectedItem = input(null, { ...(ngDevMode ? { debugName: "selectedItem" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
3081
|
+
itemId = input(null, { ...(ngDevMode ? { debugName: "itemId" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
3082
|
+
delegationId = input(null, { ...(ngDevMode ? { debugName: "delegationId" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
2989
3083
|
/** Bound from the `?edit=<id>` query param (edit drawer). */
|
|
2990
3084
|
edit = input(null, { ...(ngDevMode ? { debugName: "edit" } : /* istanbul ignore next */ {}), transform: toNullableNumber });
|
|
2991
3085
|
facade = inject(DelegationsFacade);
|
|
@@ -3038,6 +3132,13 @@ class DelegationsList {
|
|
|
3038
3132
|
: this.activeTab() === 'approvals'
|
|
3039
3133
|
? this.approvalEmptyStateKey()
|
|
3040
3134
|
: this.assignedEmptyStateKey(), ...(ngDevMode ? [{ debugName: "emptyStateKey" }] : /* istanbul ignore next */ []));
|
|
3135
|
+
detailQueryId = computed(() => this.view() ??
|
|
3136
|
+
this.selected() ??
|
|
3137
|
+
this.itemSelected() ??
|
|
3138
|
+
this.selectedItemId() ??
|
|
3139
|
+
this.selectedItem() ??
|
|
3140
|
+
this.itemId() ??
|
|
3141
|
+
this.delegationId(), ...(ngDevMode ? [{ debugName: "detailQueryId" }] : /* istanbul ignore next */ []));
|
|
3041
3142
|
tableActions = computed(() => [
|
|
3042
3143
|
{
|
|
3043
3144
|
icon: 'general.plus',
|
|
@@ -3232,7 +3333,7 @@ class DelegationsList {
|
|
|
3232
3333
|
effect(() => {
|
|
3233
3334
|
if (!this.routed())
|
|
3234
3335
|
return;
|
|
3235
|
-
const id = this.
|
|
3336
|
+
const id = this.detailQueryId();
|
|
3236
3337
|
untracked(() => this.syncDetailDrawer(id));
|
|
3237
3338
|
});
|
|
3238
3339
|
// Edit (`?edit=`) drawer ↔ route. `view` takes precedence: while a view is
|
|
@@ -3241,7 +3342,7 @@ class DelegationsList {
|
|
|
3241
3342
|
if (!this.routed())
|
|
3242
3343
|
return;
|
|
3243
3344
|
const id = this.edit();
|
|
3244
|
-
const hasView = this.
|
|
3345
|
+
const hasView = this.detailQueryId() != null;
|
|
3245
3346
|
untracked(() => this.syncEditDrawer(hasView ? null : id));
|
|
3246
3347
|
});
|
|
3247
3348
|
}
|
|
@@ -3381,8 +3482,8 @@ class DelegationsList {
|
|
|
3381
3482
|
this.detailRef = null;
|
|
3382
3483
|
this.detailOpenId = null;
|
|
3383
3484
|
// Route still points here ⇒ the user dismissed the drawer; clear it.
|
|
3384
|
-
if (this.
|
|
3385
|
-
this.
|
|
3485
|
+
if (this.detailQueryId() === openingId)
|
|
3486
|
+
this.clearDetailQuery();
|
|
3386
3487
|
});
|
|
3387
3488
|
}
|
|
3388
3489
|
else if (id == null) {
|
|
@@ -3438,6 +3539,21 @@ class DelegationsList {
|
|
|
3438
3539
|
queryParamsHandling: 'merge',
|
|
3439
3540
|
});
|
|
3440
3541
|
}
|
|
3542
|
+
clearDetailQuery() {
|
|
3543
|
+
void this.router.navigate([], {
|
|
3544
|
+
relativeTo: this.route,
|
|
3545
|
+
queryParams: {
|
|
3546
|
+
view: null,
|
|
3547
|
+
selected: null,
|
|
3548
|
+
itemSelected: null,
|
|
3549
|
+
selectedItemId: null,
|
|
3550
|
+
selectedItem: null,
|
|
3551
|
+
itemId: null,
|
|
3552
|
+
delegationId: null,
|
|
3553
|
+
},
|
|
3554
|
+
queryParamsHandling: 'merge',
|
|
3555
|
+
});
|
|
3556
|
+
}
|
|
3441
3557
|
approve(row) {
|
|
3442
3558
|
this.mark(`approve:${row.delegationId}`, true);
|
|
3443
3559
|
this.facade
|
|
@@ -3482,7 +3598,7 @@ class DelegationsList {
|
|
|
3482
3598
|
this.busyIds.update((ids) => on ? [...ids, key] : ids.filter((id) => id !== key));
|
|
3483
3599
|
}
|
|
3484
3600
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3485
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationsList, isStandalone: true, selector: "mt-delegations-list", inputs: { showBreadcrumb: { classPropertyName: "showBreadcrumb", publicName: "showBreadcrumb", isSignal: true, isRequired: false, transformFunction: null }, showPageShell: { classPropertyName: "showPageShell", publicName: "showPageShell", isSignal: true, isRequired: false, transformFunction: null }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null }, surfaceTitleKey: { classPropertyName: "surfaceTitleKey", publicName: "surfaceTitleKey", isSignal: true, isRequired: false, transformFunction: null }, assignedTabLabelKey: { classPropertyName: "assignedTabLabelKey", publicName: "assignedTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, assignedDecisionTab: { classPropertyName: "assignedDecisionTab", publicName: "assignedDecisionTab", isSignal: true, isRequired: false, transformFunction: null }, assignedEmptyStateKey: { classPropertyName: "assignedEmptyStateKey", publicName: "assignedEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, assignedStatus: { classPropertyName: "assignedStatus", publicName: "assignedStatus", isSignal: true, isRequired: false, transformFunction: null }, showApprovalTab: { classPropertyName: "showApprovalTab", publicName: "showApprovalTab", isSignal: true, isRequired: false, transformFunction: null }, approvalTabLabelKey: { classPropertyName: "approvalTabLabelKey", publicName: "approvalTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, approvalEmptyStateKey: { classPropertyName: "approvalEmptyStateKey", publicName: "approvalEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, approvalStatus: { classPropertyName: "approvalStatus", publicName: "approvalStatus", isSignal: true, isRequired: false, transformFunction: null }, routed: { classPropertyName: "routed", publicName: "routed", isSignal: true, isRequired: false, transformFunction: null }, tab: { classPropertyName: "tab", publicName: "tab", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <ng-template #tableContent>\r\n <div class=\"flex flex-col gap-4\">\r\n @if (!adminMode()) {\r\n @let assignedLabel =\r\n assignedDecisionTab()\r\n ? t(\"delegations.action.approve\") +\r\n \" / \" +\r\n t(\"delegations.action.reject\")\r\n : t(assignedTabLabelKey());\r\n\r\n <mt-tabs\r\n mode=\"underline\"\r\n [active]=\"activeTab()\"\r\n [options]=\"\r\n showApprovalTab()\r\n ? [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n { value: 'approvals', label: t(approvalTabLabelKey()) },\r\n ]\r\n : [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n ]\r\n \"\r\n fluid\r\n (onChange)=\"switchTab($event)\"\r\n ></mt-tabs>\r\n }\r\n\r\n <mt-table\r\n [data]=\"tableRows()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"isLoading()\"\r\n [noCard]=\"true\"\r\n >\r\n <ng-template #empty>\r\n <div\r\n class=\"flex min-h-64 flex-col items-center justify-center gap-4 px-6 py-10 text-center\"\r\n >\r\n <div\r\n class=\"flex size-16 items-center justify-center rounded-3xl bg-surface-0 text-primary shadow-sm\"\r\n >\r\n <svg\r\n viewBox=\"0 0 64 64\"\r\n class=\"size-9\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n aria-hidden=\"true\"\r\n >\r\n <rect\r\n x=\"10\"\r\n y=\"14\"\r\n width=\"44\"\r\n height=\"36\"\r\n rx=\"12\"\r\n class=\"fill-primary/10 stroke-primary/35\"\r\n stroke-width=\"2\"\r\n />\r\n <path\r\n d=\"M21 28H43\"\r\n class=\"stroke-primary\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n <path\r\n d=\"M21 36H35\"\r\n class=\"stroke-primary/70\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <p class=\"max-w-sm text-sm text-surface-500\">\r\n {{ t(emptyStateKey()) }}\r\n </p>\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #adminContent>\r\n <div class=\"flex min-h-full flex-col gap-4\">\r\n @if (showBreadcrumb()) {\r\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\r\n }\r\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\r\n </div>\r\n </ng-template>\r\n\r\n @if (adminMode()) {\r\n @if (showPageShell()) {\r\n <mt-page\r\n [title]=\"surfaceTitle()\"\r\n [avatarIcon]=\"'custom.hierarchy-structure'\"\r\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-indigo-50)',\r\n '--p-avatar-color': 'var(--p-indigo-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n </mt-page>\r\n } @else {\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n }\r\n } @else {\r\n <div class=\"flex h-full flex-col gap-4
|
|
3601
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DelegationsList, isStandalone: true, selector: "mt-delegations-list", inputs: { showBreadcrumb: { classPropertyName: "showBreadcrumb", publicName: "showBreadcrumb", isSignal: true, isRequired: false, transformFunction: null }, showPageShell: { classPropertyName: "showPageShell", publicName: "showPageShell", isSignal: true, isRequired: false, transformFunction: null }, adminMode: { classPropertyName: "adminMode", publicName: "adminMode", isSignal: true, isRequired: false, transformFunction: null }, surfaceTitleKey: { classPropertyName: "surfaceTitleKey", publicName: "surfaceTitleKey", isSignal: true, isRequired: false, transformFunction: null }, assignedTabLabelKey: { classPropertyName: "assignedTabLabelKey", publicName: "assignedTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, assignedDecisionTab: { classPropertyName: "assignedDecisionTab", publicName: "assignedDecisionTab", isSignal: true, isRequired: false, transformFunction: null }, assignedEmptyStateKey: { classPropertyName: "assignedEmptyStateKey", publicName: "assignedEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, assignedStatus: { classPropertyName: "assignedStatus", publicName: "assignedStatus", isSignal: true, isRequired: false, transformFunction: null }, showApprovalTab: { classPropertyName: "showApprovalTab", publicName: "showApprovalTab", isSignal: true, isRequired: false, transformFunction: null }, approvalTabLabelKey: { classPropertyName: "approvalTabLabelKey", publicName: "approvalTabLabelKey", isSignal: true, isRequired: false, transformFunction: null }, approvalEmptyStateKey: { classPropertyName: "approvalEmptyStateKey", publicName: "approvalEmptyStateKey", isSignal: true, isRequired: false, transformFunction: null }, approvalStatus: { classPropertyName: "approvalStatus", publicName: "approvalStatus", isSignal: true, isRequired: false, transformFunction: null }, routed: { classPropertyName: "routed", publicName: "routed", isSignal: true, isRequired: false, transformFunction: null }, tab: { classPropertyName: "tab", publicName: "tab", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, itemSelected: { classPropertyName: "itemSelected", publicName: "itemSelected", isSignal: true, isRequired: false, transformFunction: null }, selectedItemId: { classPropertyName: "selectedItemId", publicName: "selectedItemId", isSignal: true, isRequired: false, transformFunction: null }, selectedItem: { classPropertyName: "selectedItem", publicName: "selectedItem", isSignal: true, isRequired: false, transformFunction: null }, itemId: { classPropertyName: "itemId", publicName: "itemId", isSignal: true, isRequired: false, transformFunction: null }, delegationId: { classPropertyName: "delegationId", publicName: "delegationId", isSignal: true, isRequired: false, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <ng-template #tableContent>\r\n <div class=\"flex flex-col gap-4\">\r\n @if (!adminMode()) {\r\n @let assignedLabel =\r\n assignedDecisionTab()\r\n ? t(\"delegations.action.approve\") +\r\n \" / \" +\r\n t(\"delegations.action.reject\")\r\n : t(assignedTabLabelKey());\r\n\r\n <mt-tabs\r\n mode=\"underline\"\r\n [active]=\"activeTab()\"\r\n [options]=\"\r\n showApprovalTab()\r\n ? [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n { value: 'approvals', label: t(approvalTabLabelKey()) },\r\n ]\r\n : [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n ]\r\n \"\r\n fluid\r\n (onChange)=\"switchTab($event)\"\r\n ></mt-tabs>\r\n }\r\n\r\n <mt-table\r\n [data]=\"tableRows()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"isLoading()\"\r\n [noCard]=\"true\"\r\n >\r\n <ng-template #empty>\r\n <div\r\n class=\"flex min-h-64 flex-col items-center justify-center gap-4 px-6 py-10 text-center\"\r\n >\r\n <div\r\n class=\"flex size-16 items-center justify-center rounded-3xl bg-surface-0 text-primary shadow-sm\"\r\n >\r\n <svg\r\n viewBox=\"0 0 64 64\"\r\n class=\"size-9\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n aria-hidden=\"true\"\r\n >\r\n <rect\r\n x=\"10\"\r\n y=\"14\"\r\n width=\"44\"\r\n height=\"36\"\r\n rx=\"12\"\r\n class=\"fill-primary/10 stroke-primary/35\"\r\n stroke-width=\"2\"\r\n />\r\n <path\r\n d=\"M21 28H43\"\r\n class=\"stroke-primary\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n <path\r\n d=\"M21 36H35\"\r\n class=\"stroke-primary/70\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <p class=\"max-w-sm text-sm text-surface-500\">\r\n {{ t(emptyStateKey()) }}\r\n </p>\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #adminContent>\r\n <div class=\"flex min-h-full flex-col gap-4\">\r\n @if (showBreadcrumb()) {\r\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\r\n }\r\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\r\n </div>\r\n </ng-template>\r\n\r\n @if (adminMode()) {\r\n @if (showPageShell()) {\r\n <mt-page\r\n [title]=\"surfaceTitle()\"\r\n [avatarIcon]=\"'custom.hierarchy-structure'\"\r\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-indigo-50)',\r\n '--p-avatar-color': 'var(--p-indigo-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n </mt-page>\r\n } @else {\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n }\r\n } @else {\r\n <div class=\"flex h-full flex-col gap-4 ps-4 pt-4\">\r\n <mt-card class=\"rounded-e-none!\" [title]=\"surfaceTitle()\">\r\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\r\n </mt-card>\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3486
3602
|
}
|
|
3487
3603
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DelegationsList, decorators: [{
|
|
3488
3604
|
type: Component,
|
|
@@ -3494,8 +3610,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
3494
3610
|
Table,
|
|
3495
3611
|
Tabs,
|
|
3496
3612
|
TranslocoDirective,
|
|
3497
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\r\n <ng-template #tableContent>\r\n <div class=\"flex flex-col gap-4\">\r\n @if (!adminMode()) {\r\n @let assignedLabel =\r\n assignedDecisionTab()\r\n ? t(\"delegations.action.approve\") +\r\n \" / \" +\r\n t(\"delegations.action.reject\")\r\n : t(assignedTabLabelKey());\r\n\r\n <mt-tabs\r\n mode=\"underline\"\r\n [active]=\"activeTab()\"\r\n [options]=\"\r\n showApprovalTab()\r\n ? [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n { value: 'approvals', label: t(approvalTabLabelKey()) },\r\n ]\r\n : [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n ]\r\n \"\r\n fluid\r\n (onChange)=\"switchTab($event)\"\r\n ></mt-tabs>\r\n }\r\n\r\n <mt-table\r\n [data]=\"tableRows()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"isLoading()\"\r\n [noCard]=\"true\"\r\n >\r\n <ng-template #empty>\r\n <div\r\n class=\"flex min-h-64 flex-col items-center justify-center gap-4 px-6 py-10 text-center\"\r\n >\r\n <div\r\n class=\"flex size-16 items-center justify-center rounded-3xl bg-surface-0 text-primary shadow-sm\"\r\n >\r\n <svg\r\n viewBox=\"0 0 64 64\"\r\n class=\"size-9\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n aria-hidden=\"true\"\r\n >\r\n <rect\r\n x=\"10\"\r\n y=\"14\"\r\n width=\"44\"\r\n height=\"36\"\r\n rx=\"12\"\r\n class=\"fill-primary/10 stroke-primary/35\"\r\n stroke-width=\"2\"\r\n />\r\n <path\r\n d=\"M21 28H43\"\r\n class=\"stroke-primary\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n <path\r\n d=\"M21 36H35\"\r\n class=\"stroke-primary/70\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <p class=\"max-w-sm text-sm text-surface-500\">\r\n {{ t(emptyStateKey()) }}\r\n </p>\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #adminContent>\r\n <div class=\"flex min-h-full flex-col gap-4\">\r\n @if (showBreadcrumb()) {\r\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\r\n }\r\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\r\n </div>\r\n </ng-template>\r\n\r\n @if (adminMode()) {\r\n @if (showPageShell()) {\r\n <mt-page\r\n [title]=\"surfaceTitle()\"\r\n [avatarIcon]=\"'custom.hierarchy-structure'\"\r\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-indigo-50)',\r\n '--p-avatar-color': 'var(--p-indigo-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n </mt-page>\r\n } @else {\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n }\r\n } @else {\r\n <div class=\"flex h-full flex-col gap-4
|
|
3498
|
-
}], ctorParameters: () => [], propDecorators: { showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", required: false }] }], showPageShell: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageShell", required: false }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }], surfaceTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceTitleKey", required: false }] }], assignedTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedTabLabelKey", required: false }] }], assignedDecisionTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedDecisionTab", required: false }] }], assignedEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedEmptyStateKey", required: false }] }], assignedStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedStatus", required: false }] }], showApprovalTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "showApprovalTab", required: false }] }], approvalTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalTabLabelKey", required: false }] }], approvalEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalEmptyStateKey", required: false }] }], approvalStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalStatus", required: false }] }], routed: [{ type: i0.Input, args: [{ isSignal: true, alias: "routed", required: false }] }], tab: [{ type: i0.Input, args: [{ isSignal: true, alias: "tab", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }] } });
|
|
3613
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\r\n <ng-template #tableContent>\r\n <div class=\"flex flex-col gap-4\">\r\n @if (!adminMode()) {\r\n @let assignedLabel =\r\n assignedDecisionTab()\r\n ? t(\"delegations.action.approve\") +\r\n \" / \" +\r\n t(\"delegations.action.reject\")\r\n : t(assignedTabLabelKey());\r\n\r\n <mt-tabs\r\n mode=\"underline\"\r\n [active]=\"activeTab()\"\r\n [options]=\"\r\n showApprovalTab()\r\n ? [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n { value: 'approvals', label: t(approvalTabLabelKey()) },\r\n ]\r\n : [\r\n { value: 'my', label: t('delegations.myDelegations') },\r\n { value: 'assigned', label: assignedLabel },\r\n ]\r\n \"\r\n fluid\r\n (onChange)=\"switchTab($event)\"\r\n ></mt-tabs>\r\n }\r\n\r\n <mt-table\r\n [data]=\"tableRows()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"isLoading()\"\r\n [noCard]=\"true\"\r\n >\r\n <ng-template #empty>\r\n <div\r\n class=\"flex min-h-64 flex-col items-center justify-center gap-4 px-6 py-10 text-center\"\r\n >\r\n <div\r\n class=\"flex size-16 items-center justify-center rounded-3xl bg-surface-0 text-primary shadow-sm\"\r\n >\r\n <svg\r\n viewBox=\"0 0 64 64\"\r\n class=\"size-9\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n aria-hidden=\"true\"\r\n >\r\n <rect\r\n x=\"10\"\r\n y=\"14\"\r\n width=\"44\"\r\n height=\"36\"\r\n rx=\"12\"\r\n class=\"fill-primary/10 stroke-primary/35\"\r\n stroke-width=\"2\"\r\n />\r\n <path\r\n d=\"M21 28H43\"\r\n class=\"stroke-primary\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n <path\r\n d=\"M21 36H35\"\r\n class=\"stroke-primary/70\"\r\n stroke-width=\"3\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <p class=\"max-w-sm text-sm text-surface-500\">\r\n {{ t(emptyStateKey()) }}\r\n </p>\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #adminContent>\r\n <div class=\"flex min-h-full flex-col gap-4\">\r\n @if (showBreadcrumb()) {\r\n <mt-breadcrumb [items]=\"breadcrumbItems()\"></mt-breadcrumb>\r\n }\r\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\r\n </div>\r\n </ng-template>\r\n\r\n @if (adminMode()) {\r\n @if (showPageShell()) {\r\n <mt-page\r\n [title]=\"surfaceTitle()\"\r\n [avatarIcon]=\"'custom.hierarchy-structure'\"\r\n [contentClass]=\"'max-[1025px]:p-4 max-[640px]:p-3'\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-indigo-50)',\r\n '--p-avatar-color': 'var(--p-indigo-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n >\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n </mt-page>\r\n } @else {\r\n <ng-container *ngTemplateOutlet=\"adminContent\"></ng-container>\r\n }\r\n } @else {\r\n <div class=\"flex h-full flex-col gap-4 ps-4 pt-4\">\r\n <mt-card class=\"rounded-e-none!\" [title]=\"surfaceTitle()\">\r\n <ng-container *ngTemplateOutlet=\"tableContent\"></ng-container>\r\n </mt-card>\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [":host{display:block;min-width:0}:host ::ng-deep mt-table td.mt-actions-column>div{flex-wrap:nowrap;justify-content:flex-end;white-space:nowrap}\n"] }]
|
|
3614
|
+
}], ctorParameters: () => [], propDecorators: { showBreadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBreadcrumb", required: false }] }], showPageShell: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageShell", required: false }] }], adminMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "adminMode", required: false }] }], surfaceTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceTitleKey", required: false }] }], assignedTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedTabLabelKey", required: false }] }], assignedDecisionTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedDecisionTab", required: false }] }], assignedEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedEmptyStateKey", required: false }] }], assignedStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedStatus", required: false }] }], showApprovalTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "showApprovalTab", required: false }] }], approvalTabLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalTabLabelKey", required: false }] }], approvalEmptyStateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalEmptyStateKey", required: false }] }], approvalStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "approvalStatus", required: false }] }], routed: [{ type: i0.Input, args: [{ isSignal: true, alias: "routed", required: false }] }], tab: [{ type: i0.Input, args: [{ isSignal: true, alias: "tab", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], itemSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSelected", required: false }] }], selectedItemId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemId", required: false }] }], selectedItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItem", required: false }] }], itemId: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemId", required: false }] }], delegationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "delegationId", required: false }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }] } });
|
|
3499
3615
|
|
|
3500
3616
|
/**
|
|
3501
3617
|
* Endpoints that must NEVER carry the `app-delegation` header.
|