@masterteam/work-center 0.0.3 → 0.0.4
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,6 +1,6 @@
|
|
|
1
1
|
import { CommonModule } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, Injectable, computed, input, output, Component, signal, effect, untracked } from '@angular/core';
|
|
3
|
+
import { inject, Injectable, computed, input, output, Component, signal, effect, untracked, viewChild } from '@angular/core';
|
|
4
4
|
import { ClientPage } from '@masterteam/components/client-page';
|
|
5
5
|
import { ModalService } from '@masterteam/components/modal';
|
|
6
6
|
import { PropertyFilterBuilder } from '@masterteam/components/property-filter-builder';
|
|
@@ -10,15 +10,21 @@ import * as i1 from 'primeng/skeleton';
|
|
|
10
10
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
11
11
|
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
12
12
|
import { HttpClient } from '@angular/common/http';
|
|
13
|
-
import { handleApiRequest } from '@masterteam/components';
|
|
14
|
-
import { catchError, EMPTY, map } from 'rxjs';
|
|
13
|
+
import { handleApiRequest, ValidatorConfig } from '@masterteam/components';
|
|
14
|
+
import { catchError, EMPTY, map, take } from 'rxjs';
|
|
15
15
|
import { EntitiesPreview } from '@masterteam/components/entities';
|
|
16
16
|
import { Tabs } from '@masterteam/components/tabs';
|
|
17
|
+
import { DiscussionThread } from '@masterteam/discussion';
|
|
17
18
|
import { StructureBuilder } from '@masterteam/structure-builder';
|
|
18
|
-
import { ClientModulePreview } from '@masterteam/client-components/client-module-preview';
|
|
19
19
|
import { ClientForm } from '@masterteam/forms/client-form';
|
|
20
20
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
21
21
|
import { Drawer } from '@masterteam/components/drawer';
|
|
22
|
+
import { Button } from '@masterteam/components/button';
|
|
23
|
+
import { ToastService } from '@masterteam/components/toast';
|
|
24
|
+
import * as i1$1 from '@angular/forms';
|
|
25
|
+
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
26
|
+
import { ModalRef } from '@masterteam/components/dialog';
|
|
27
|
+
import { DynamicForm } from '@masterteam/forms/dynamic-form';
|
|
22
28
|
|
|
23
29
|
class EnterArea {
|
|
24
30
|
area;
|
|
@@ -762,8 +768,8 @@ class WorkCenterPage {
|
|
|
762
768
|
area = input('MyInbox', ...(ngDevMode ? [{ debugName: "area" }] : []));
|
|
763
769
|
pageTitle = input('Work Center', ...(ngDevMode ? [{ debugName: "pageTitle" }] : []));
|
|
764
770
|
menuIcon = input('communication.inbox-01', ...(ngDevMode ? [{ debugName: "menuIcon" }] : []));
|
|
765
|
-
|
|
766
|
-
|
|
771
|
+
openItemsInModal = input(true, ...(ngDevMode ? [{ debugName: "openItemsInModal" }] : []));
|
|
772
|
+
itemModal = input(null, ...(ngDevMode ? [{ debugName: "itemModal" }] : []));
|
|
767
773
|
runtimeFiltersChanged = output();
|
|
768
774
|
itemClicked = output();
|
|
769
775
|
context = this.facade.context;
|
|
@@ -805,8 +811,11 @@ class WorkCenterPage {
|
|
|
805
811
|
allowedOperators: fallbackOperators,
|
|
806
812
|
};
|
|
807
813
|
}, ...(ngDevMode ? [{ debugName: "propertyFilterSchema" }] : []));
|
|
808
|
-
|
|
814
|
+
defaultModalStyleClass = '!w-[96vw] xl:!w-[calc(100%-8rem)] 2xl:!w-[calc(100%-12rem)] !absolute !shadow-none';
|
|
809
815
|
onMenuItemClick(item) {
|
|
816
|
+
if (item.key === this.context().selectedCardKey) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
810
819
|
this.facade.selectCardAndLoad(this.area(), item.key);
|
|
811
820
|
}
|
|
812
821
|
onLazyLoad(event) {
|
|
@@ -833,31 +842,31 @@ class WorkCenterPage {
|
|
|
833
842
|
console.log('[work-center-debug] page row click', {
|
|
834
843
|
contextKey,
|
|
835
844
|
row,
|
|
836
|
-
|
|
837
|
-
|
|
845
|
+
openItemsInModal: this.openItemsInModal(),
|
|
846
|
+
hasModalComponent: !!this.itemModal()?.component,
|
|
838
847
|
});
|
|
839
848
|
if (!contextKey) {
|
|
840
849
|
return;
|
|
841
850
|
}
|
|
842
851
|
this.itemClicked.emit(contextKey);
|
|
843
|
-
if (!this.
|
|
852
|
+
if (!this.openItemsInModal()) {
|
|
844
853
|
return;
|
|
845
854
|
}
|
|
846
|
-
const
|
|
847
|
-
if (!
|
|
855
|
+
const modalOptions = this.itemModal();
|
|
856
|
+
if (!modalOptions?.component) {
|
|
848
857
|
return;
|
|
849
858
|
}
|
|
850
|
-
this.modal.openModal(
|
|
851
|
-
header:
|
|
852
|
-
styleClass:
|
|
853
|
-
position:
|
|
859
|
+
this.modal.openModal(modalOptions.component, 'drawer', {
|
|
860
|
+
header: modalOptions?.header ?? 'Item Details',
|
|
861
|
+
styleClass: modalOptions?.styleClass ?? this.defaultModalStyleClass,
|
|
862
|
+
position: modalOptions?.position ?? 'end',
|
|
854
863
|
dismissible: true,
|
|
855
864
|
modal: true,
|
|
856
|
-
...(
|
|
865
|
+
...(modalOptions?.appendTo ? { appendTo: modalOptions.appendTo } : {}),
|
|
857
866
|
inputValues: { contextKey },
|
|
858
867
|
});
|
|
859
868
|
}
|
|
860
|
-
rowsClickable = computed(() => this.
|
|
869
|
+
rowsClickable = computed(() => this.openItemsInModal(), ...(ngDevMode ? [{ debugName: "rowsClickable" }] : []));
|
|
861
870
|
resolveRowContextKey(row) {
|
|
862
871
|
const value = row['contextKey'];
|
|
863
872
|
if (typeof value !== 'string') {
|
|
@@ -867,7 +876,7 @@ class WorkCenterPage {
|
|
|
867
876
|
return normalized.length ? normalized : null;
|
|
868
877
|
}
|
|
869
878
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
870
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterPage, isStandalone: true, selector: "mt-work-center-page", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, menuIcon: { classPropertyName: "menuIcon", publicName: "menuIcon", isSignal: true, isRequired: false, transformFunction: null },
|
|
879
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterPage, isStandalone: true, selector: "mt-work-center-page", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, menuIcon: { classPropertyName: "menuIcon", publicName: "menuIcon", isSignal: true, isRequired: false, transformFunction: null }, openItemsInModal: { classPropertyName: "openItemsInModal", publicName: "openItemsInModal", isSignal: true, isRequired: false, transformFunction: null }, itemModal: { classPropertyName: "itemModal", publicName: "itemModal", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeFiltersChanged: "runtimeFiltersChanged", itemClicked: "itemClicked" }, ngImport: i0, template: "<mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"pageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n>\r\n <ng-template #headerClientPageEnd>\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"context().runtimeFilters\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n @if (loading()) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\r\n <p-skeleton height=\"6.5rem\" borderRadius=\"1rem\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n [data]=\"rows()\"\r\n [columns]=\"columns()\"\r\n [lazy]=\"true\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"tableCurrentPage()\"\r\n [first]=\"tableFirst()\"\r\n (lazyLoad)=\"onLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</mt-client-page>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ClientPage, selector: "mt-client-page", inputs: ["menuIcon", "menuTitle", "menuItems", "menuItemsLoading", "activeItem", "collapsed"], outputs: ["collapsedChange", "menuItemClick"] }, { kind: "component", type: PropertyFilterBuilder, selector: "mt-property-filter-builder", inputs: ["schema", "filters", "title", "buttonLabel", "disabled"], outputs: ["filtersChange", "applied", "cleared"] }, { kind: "component", type: StatisticCard, selector: "mt-statistic-card", inputs: ["data"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "showFilters", "loading", "updating", "lazy", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
|
|
871
880
|
}
|
|
872
881
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, decorators: [{
|
|
873
882
|
type: Component,
|
|
@@ -879,7 +888,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
879
888
|
Table,
|
|
880
889
|
SkeletonModule,
|
|
881
890
|
], template: "<mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"pageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n>\r\n <ng-template #headerClientPageEnd>\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"context().runtimeFilters\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n @if (loading()) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\r\n <p-skeleton height=\"6.5rem\" borderRadius=\"1rem\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n [data]=\"rows()\"\r\n [columns]=\"columns()\"\r\n [lazy]=\"true\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"tableCurrentPage()\"\r\n [first]=\"tableFirst()\"\r\n (lazyLoad)=\"onLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</mt-client-page>\r\n" }]
|
|
882
|
-
}], propDecorators: { area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], menuIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuIcon", required: false }] }],
|
|
891
|
+
}], propDecorators: { area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], menuIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuIcon", required: false }] }], openItemsInModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemsInModal", required: false }] }], itemModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemModal", required: false }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
883
892
|
|
|
884
893
|
function readItemContext(details) {
|
|
885
894
|
const item = details.item;
|
|
@@ -912,6 +921,7 @@ class WorkCenterEscalationInstanceType {
|
|
|
912
921
|
loadSub;
|
|
913
922
|
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
914
923
|
activeTab = signal('escalationDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
924
|
+
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
915
925
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
916
926
|
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
917
927
|
preview = signal(null, ...(ngDevMode ? [{ debugName: "preview" }] : []));
|
|
@@ -920,6 +930,10 @@ class WorkCenterEscalationInstanceType {
|
|
|
920
930
|
label: 'Escalation Details',
|
|
921
931
|
value: 'escalationDetails',
|
|
922
932
|
},
|
|
933
|
+
{
|
|
934
|
+
label: 'Discussion',
|
|
935
|
+
value: 'discussion',
|
|
936
|
+
},
|
|
923
937
|
{
|
|
924
938
|
label: 'Schema',
|
|
925
939
|
value: 'schema',
|
|
@@ -959,7 +973,7 @@ class WorkCenterEscalationInstanceType {
|
|
|
959
973
|
{
|
|
960
974
|
key: 'attachments',
|
|
961
975
|
name: 'Attachments',
|
|
962
|
-
value:
|
|
976
|
+
value: preview.attachments ?? [],
|
|
963
977
|
viewType: 'Attachment',
|
|
964
978
|
order: 4,
|
|
965
979
|
configuration: { size: 24 },
|
|
@@ -982,6 +996,7 @@ class WorkCenterEscalationInstanceType {
|
|
|
982
996
|
readNumber(this.itemContext(), 'instanceId'), ...(ngDevMode ? [{ debugName: "instanceId" }] : []));
|
|
983
997
|
resolvedInstanceId = computed(() => this.instanceId() ?? 0, ...(ngDevMode ? [{ debugName: "resolvedInstanceId" }] : []));
|
|
984
998
|
canRenderDetails = computed(() => this.resolvedInstanceId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDetails" }] : []));
|
|
999
|
+
canRenderDiscussion = computed(() => this.resolvedInstanceId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDiscussion" }] : []));
|
|
985
1000
|
constructor() {
|
|
986
1001
|
effect(() => {
|
|
987
1002
|
const instanceId = this.resolvedInstanceId();
|
|
@@ -996,6 +1011,12 @@ class WorkCenterEscalationInstanceType {
|
|
|
996
1011
|
ngOnDestroy() {
|
|
997
1012
|
this.loadSub?.unsubscribe();
|
|
998
1013
|
}
|
|
1014
|
+
onDiscussionReadStateChanged(state) {
|
|
1015
|
+
const resolvedUserId = state?.userId?.trim();
|
|
1016
|
+
if (resolvedUserId) {
|
|
1017
|
+
this.currentUserId.set(resolvedUserId);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
999
1020
|
loadPreview(instanceId) {
|
|
1000
1021
|
this.loadSub?.unsubscribe();
|
|
1001
1022
|
this.loading.set(true);
|
|
@@ -1017,11 +1038,17 @@ class WorkCenterEscalationInstanceType {
|
|
|
1017
1038
|
});
|
|
1018
1039
|
}
|
|
1019
1040
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterEscalationInstanceType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1020
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterEscalationInstanceType, isStandalone: true, selector: "mt-work-center-escalation-instance-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'escalationDetails'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation details...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (preview()) {\n <mt-entities-preview [entities]=\"detailEntities()\" />\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation details context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation schema...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (hasSchema()) {\n <div class=\"h-[70vh] overflow-hidden rounded-2xl\">\n <mt-structure-builder\n class=\"h-full\"\n [readonly]=\"true\"\n [nodes]=\"schemaNodes()\"\n [connections]=\"schemaConnections()\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema is not available for this item yet.\n </p>\n </div>\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "nodeForm", "connectionForm", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
|
|
1041
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterEscalationInstanceType, isStandalone: true, selector: "mt-work-center-escalation-instance-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'escalationDetails'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation details...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (preview()) {\n <mt-entities-preview [entities]=\"detailEntities()\" />\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation details context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'discussion'\">\n @if (canRenderDiscussion()) {\n <div class=\"h-[70vh] min-h-[32rem]\">\n <mt-discussion-thread\n [moduleType]=\"'EscalationInstance'\"\n [recordId]=\"resolvedInstanceId()\"\n [currentUserId]=\"currentUserId()\"\n [mentionSearchEndpoint]=\"'Identity/users'\"\n [mentionSearchParam]=\"'query'\"\n [mentionSearchDataPath]=\"'data'\"\n [uploadEndpoint]=\"'uploader'\"\n [attachmentDownloadEndpoint]=\"'uploader'\"\n [showParticipants]=\"true\"\n [autoMarkRead]=\"true\"\n [refreshIntervalMs]=\"0\"\n [styleClass]=\"'h-full'\"\n (readStateChanged)=\"onDiscussionReadStateChanged($event)\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Discussion context is not available for this escalation yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation schema...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (hasSchema()) {\n <div class=\"h-[70vh] overflow-hidden rounded-2xl\">\n <mt-structure-builder\n class=\"h-full\"\n [readonly]=\"true\"\n [nodes]=\"schemaNodes()\"\n [connections]=\"schemaConnections()\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema is not available for this item yet.\n </p>\n </div>\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DiscussionThread, selector: "mt-discussion-thread", inputs: ["moduleType", "recordId", "title", "subtitle", "placeholder", "pageSize", "currentUserId", "requestContext", "mentionableUsers", "mentionSearchEndpoint", "mentionSearchParam", "mentionSearchDataPath", "allowAttachments", "uploadEndpoint", "attachmentDownloadEndpoint", "showParticipants", "autoMarkRead", "refreshIntervalMs", "styleClass", "disabled"], outputs: ["loaded", "errored", "commentCreated", "commentUpdated", "commentDeleted", "readStateChanged"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "nodeForm", "connectionForm", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
|
|
1021
1042
|
}
|
|
1022
1043
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterEscalationInstanceType, decorators: [{
|
|
1023
1044
|
type: Component,
|
|
1024
|
-
args: [{ selector: 'mt-work-center-escalation-instance-type', standalone: true, imports: [
|
|
1045
|
+
args: [{ selector: 'mt-work-center-escalation-instance-type', standalone: true, imports: [
|
|
1046
|
+
CommonModule,
|
|
1047
|
+
Tabs,
|
|
1048
|
+
DiscussionThread,
|
|
1049
|
+
EntitiesPreview,
|
|
1050
|
+
StructureBuilder,
|
|
1051
|
+
], template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'escalationDetails'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation details...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (preview()) {\n <mt-entities-preview [entities]=\"detailEntities()\" />\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation details context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'discussion'\">\n @if (canRenderDiscussion()) {\n <div class=\"h-[70vh] min-h-[32rem]\">\n <mt-discussion-thread\n [moduleType]=\"'EscalationInstance'\"\n [recordId]=\"resolvedInstanceId()\"\n [currentUserId]=\"currentUserId()\"\n [mentionSearchEndpoint]=\"'Identity/users'\"\n [mentionSearchParam]=\"'query'\"\n [mentionSearchDataPath]=\"'data'\"\n [uploadEndpoint]=\"'uploader'\"\n [attachmentDownloadEndpoint]=\"'uploader'\"\n [showParticipants]=\"true\"\n [autoMarkRead]=\"true\"\n [refreshIntervalMs]=\"0\"\n [styleClass]=\"'h-full'\"\n (readStateChanged)=\"onDiscussionReadStateChanged($event)\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Discussion context is not available for this escalation yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation schema...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (hasSchema()) {\n <div class=\"h-[70vh] overflow-hidden rounded-2xl\">\n <mt-structure-builder\n class=\"h-full\"\n [readonly]=\"true\"\n [nodes]=\"schemaNodes()\"\n [connections]=\"schemaConnections()\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema is not available for this item yet.\n </p>\n </div>\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n</div>\n" }]
|
|
1025
1052
|
}], ctorParameters: () => [], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
|
|
1026
1053
|
function mapUserValue(value) {
|
|
1027
1054
|
if (!value || typeof value !== 'object') {
|
|
@@ -1042,16 +1069,6 @@ function mapUserValue(value) {
|
|
|
1042
1069
|
email: readString(value, 'email') ?? readString(value, 'emailAddress'),
|
|
1043
1070
|
};
|
|
1044
1071
|
}
|
|
1045
|
-
function mapAttachments(attachments) {
|
|
1046
|
-
return (attachments ?? []).map((attachment) => ({
|
|
1047
|
-
id: attachment.id,
|
|
1048
|
-
name: attachment.name,
|
|
1049
|
-
fileName: attachment.fileName,
|
|
1050
|
-
contentType: attachment.contentType,
|
|
1051
|
-
extension: attachment.extension,
|
|
1052
|
-
size: attachment.size,
|
|
1053
|
-
}));
|
|
1054
|
-
}
|
|
1055
1072
|
function resolveSchemaSteps(preview) {
|
|
1056
1073
|
return preview?.schema?.stepsSchema ?? preview?.schemaSteps ?? [];
|
|
1057
1074
|
}
|
|
@@ -1086,30 +1103,147 @@ function readString(value, key) {
|
|
|
1086
1103
|
return typeof result === 'string' && result.length ? result : undefined;
|
|
1087
1104
|
}
|
|
1088
1105
|
|
|
1106
|
+
class WorkCenterProcessPreviewJson {
|
|
1107
|
+
http = inject(HttpClient);
|
|
1108
|
+
loadSub;
|
|
1109
|
+
requestId = input(null, ...(ngDevMode ? [{ debugName: "requestId" }] : []));
|
|
1110
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1111
|
+
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
1112
|
+
preview = signal(null, ...(ngDevMode ? [{ debugName: "preview" }] : []));
|
|
1113
|
+
canRenderPreview = computed(() => (this.requestId() ?? 0) > 0, ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
|
|
1114
|
+
previewJson = computed(() => {
|
|
1115
|
+
const preview = this.preview();
|
|
1116
|
+
return preview == null ? '' : JSON.stringify(preview, null, 2);
|
|
1117
|
+
}, ...(ngDevMode ? [{ debugName: "previewJson" }] : []));
|
|
1118
|
+
constructor() {
|
|
1119
|
+
effect(() => {
|
|
1120
|
+
const requestId = this.requestId() ?? 0;
|
|
1121
|
+
if (requestId > 0) {
|
|
1122
|
+
untracked(() => this.loadPreview(requestId));
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
this.loadSub?.unsubscribe();
|
|
1126
|
+
this.loading.set(false);
|
|
1127
|
+
this.error.set(null);
|
|
1128
|
+
this.preview.set(null);
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
ngOnDestroy() {
|
|
1132
|
+
this.loadSub?.unsubscribe();
|
|
1133
|
+
}
|
|
1134
|
+
loadPreview(requestId) {
|
|
1135
|
+
this.loadSub?.unsubscribe();
|
|
1136
|
+
this.loading.set(true);
|
|
1137
|
+
this.error.set(null);
|
|
1138
|
+
this.loadSub = this.http
|
|
1139
|
+
.get(`processes/${requestId}/preview`)
|
|
1140
|
+
.subscribe({
|
|
1141
|
+
next: (response) => {
|
|
1142
|
+
this.loading.set(false);
|
|
1143
|
+
this.preview.set(response.data ?? null);
|
|
1144
|
+
},
|
|
1145
|
+
error: (error) => {
|
|
1146
|
+
this.loading.set(false);
|
|
1147
|
+
this.preview.set(null);
|
|
1148
|
+
this.error.set(error?.error?.message ??
|
|
1149
|
+
error?.message ??
|
|
1150
|
+
'Failed to load process preview');
|
|
1151
|
+
},
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessPreviewJson, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1155
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterProcessPreviewJson, isStandalone: true, selector: "mt-work-center-process-preview-json", inputs: { requestId: { classPropertyName: "requestId", publicName: "requestId", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (!canRenderPreview()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview is not available for this item yet.\n </p>\n </div>\n} @else if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"text-sm text-surface-500\">Loading process preview...</p>\n </div>\n} @else if (error()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">{{ error() }}</p>\n </div>\n} @else if (previewJson()) {\n <div class=\"overflow-hidden rounded-2xl border border-surface-200 bg-surface-50\">\n <pre\n class=\"max-h-[70vh] overflow-auto whitespace-pre-wrap break-all p-4 text-xs leading-6 text-surface-700\"\n ><code>{{ previewJson() }}</code></pre>\n </div>\n} @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview returned no data.\n </p>\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
1156
|
+
}
|
|
1157
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessPreviewJson, decorators: [{
|
|
1158
|
+
type: Component,
|
|
1159
|
+
args: [{ selector: 'mt-work-center-process-preview-json', standalone: true, imports: [CommonModule], template: "@if (!canRenderPreview()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview is not available for this item yet.\n </p>\n </div>\n} @else if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"text-sm text-surface-500\">Loading process preview...</p>\n </div>\n} @else if (error()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">{{ error() }}</p>\n </div>\n} @else if (previewJson()) {\n <div class=\"overflow-hidden rounded-2xl border border-surface-200 bg-surface-50\">\n <pre\n class=\"max-h-[70vh] overflow-auto whitespace-pre-wrap break-all p-4 text-xs leading-6 text-surface-700\"\n ><code>{{ previewJson() }}</code></pre>\n </div>\n} @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview returned no data.\n </p>\n </div>\n}\n" }]
|
|
1160
|
+
}], ctorParameters: () => [], propDecorators: { requestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestId", required: false }] }] } });
|
|
1161
|
+
|
|
1089
1162
|
class WorkCenterProcessRequestType {
|
|
1090
1163
|
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
1164
|
+
activeTab = signal('requestDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
1165
|
+
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
1166
|
+
tabOptions = [
|
|
1167
|
+
{
|
|
1168
|
+
label: 'Request Details',
|
|
1169
|
+
value: 'requestDetails',
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
label: 'Discussion',
|
|
1173
|
+
value: 'discussion',
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
label: 'Preview',
|
|
1177
|
+
value: 'preview',
|
|
1178
|
+
},
|
|
1179
|
+
];
|
|
1180
|
+
itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
|
|
1181
|
+
requestId = computed(() => readNumber(this.itemContext(), 'requestId') ??
|
|
1182
|
+
readNumber(this.itemContext(), 'draftProcessId'), ...(ngDevMode ? [{ debugName: "requestId" }] : []));
|
|
1183
|
+
discussionRecordId = computed(() => this.requestId() ?? 0, ...(ngDevMode ? [{ debugName: "discussionRecordId" }] : []));
|
|
1184
|
+
canRenderDiscussion = computed(() => this.discussionRecordId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDiscussion" }] : []));
|
|
1185
|
+
canRenderPreview = computed(() => (this.requestId() ?? 0) > 0, ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
|
|
1186
|
+
onDiscussionReadStateChanged(state) {
|
|
1187
|
+
const resolvedUserId = state?.userId?.trim();
|
|
1188
|
+
if (resolvedUserId) {
|
|
1189
|
+
this.currentUserId.set(resolvedUserId);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1091
1192
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1092
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
1193
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterProcessRequestType, isStandalone: true, selector: "mt-work-center-process-request-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'requestDetails'\">\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process request details view will be added here.\n </p>\n </div>\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'discussion'\">\n @if (canRenderDiscussion()) {\n <div class=\"h-[70vh] min-h-[32rem]\">\n <mt-discussion-thread\n [moduleType]=\"'ProcessRequest'\"\n [recordId]=\"discussionRecordId()\"\n [currentUserId]=\"currentUserId()\"\n [mentionSearchEndpoint]=\"'Identity/users'\"\n [mentionSearchParam]=\"'query'\"\n [mentionSearchDataPath]=\"'data'\"\n [uploadEndpoint]=\"'uploader'\"\n [attachmentDownloadEndpoint]=\"'uploader'\"\n [showParticipants]=\"true\"\n [autoMarkRead]=\"true\"\n [refreshIntervalMs]=\"0\"\n [styleClass]=\"'h-full'\"\n (readStateChanged)=\"onDiscussionReadStateChanged($event)\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Discussion context is not available for this process request yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'preview'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json [requestId]=\"requestId()\" />\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview is not available for this process request yet.\n </p>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DiscussionThread, selector: "mt-discussion-thread", inputs: ["moduleType", "recordId", "title", "subtitle", "placeholder", "pageSize", "currentUserId", "requestContext", "mentionableUsers", "mentionSearchEndpoint", "mentionSearchParam", "mentionSearchDataPath", "allowAttachments", "uploadEndpoint", "attachmentDownloadEndpoint", "showParticipants", "autoMarkRead", "refreshIntervalMs", "styleClass", "disabled"], outputs: ["loaded", "errored", "commentCreated", "commentUpdated", "commentDeleted", "readStateChanged"] }, { kind: "component", type: WorkCenterProcessPreviewJson, selector: "mt-work-center-process-preview-json", inputs: ["requestId"] }] });
|
|
1093
1194
|
}
|
|
1094
1195
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, decorators: [{
|
|
1095
1196
|
type: Component,
|
|
1096
|
-
args: [{ selector: 'mt-work-center-process-request-type', standalone: true, imports: [CommonModule], template: "<div class=\"mt-modal-content flex h-full items-center justify-center p-
|
|
1197
|
+
args: [{ selector: 'mt-work-center-process-request-type', standalone: true, imports: [CommonModule, Tabs, DiscussionThread, WorkCenterProcessPreviewJson], template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'requestDetails'\">\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process request details view will be added here.\n </p>\n </div>\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'discussion'\">\n @if (canRenderDiscussion()) {\n <div class=\"h-[70vh] min-h-[32rem]\">\n <mt-discussion-thread\n [moduleType]=\"'ProcessRequest'\"\n [recordId]=\"discussionRecordId()\"\n [currentUserId]=\"currentUserId()\"\n [mentionSearchEndpoint]=\"'Identity/users'\"\n [mentionSearchParam]=\"'query'\"\n [mentionSearchDataPath]=\"'data'\"\n [uploadEndpoint]=\"'uploader'\"\n [attachmentDownloadEndpoint]=\"'uploader'\"\n [showParticipants]=\"true\"\n [autoMarkRead]=\"true\"\n [refreshIntervalMs]=\"0\"\n [styleClass]=\"'h-full'\"\n (readStateChanged)=\"onDiscussionReadStateChanged($event)\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Discussion context is not available for this process request yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'preview'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json [requestId]=\"requestId()\" />\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview is not available for this process request yet.\n </p>\n </div>\n }\n </div>\n</div>\n" }]
|
|
1097
1198
|
}], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
|
|
1098
1199
|
|
|
1200
|
+
class WorkCenterItemActionContextStore {
|
|
1201
|
+
clientForm = signal(null, ...(ngDevMode ? [{ debugName: "clientForm" }] : []));
|
|
1202
|
+
setClientForm(clientForm) {
|
|
1203
|
+
this.clientForm.set(clientForm);
|
|
1204
|
+
}
|
|
1205
|
+
resolveFormValues() {
|
|
1206
|
+
const values = this.clientForm()?.getSubmitValues();
|
|
1207
|
+
return Array.isArray(values)
|
|
1208
|
+
? values.map((value) => ({
|
|
1209
|
+
requestPropertyId: value.requestPropertyId,
|
|
1210
|
+
propertyKey: value.propertyKey,
|
|
1211
|
+
value: value.value,
|
|
1212
|
+
}))
|
|
1213
|
+
: [];
|
|
1214
|
+
}
|
|
1215
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionContextStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1216
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionContextStore });
|
|
1217
|
+
}
|
|
1218
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionContextStore, decorators: [{
|
|
1219
|
+
type: Injectable
|
|
1220
|
+
}] });
|
|
1221
|
+
|
|
1099
1222
|
class WorkCenterProcessStepType {
|
|
1223
|
+
actionContext = inject(WorkCenterItemActionContextStore, {
|
|
1224
|
+
optional: true,
|
|
1225
|
+
});
|
|
1100
1226
|
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
1101
|
-
|
|
1227
|
+
clientForm = viewChild(ClientForm, ...(ngDevMode ? [{ debugName: "clientForm" }] : []));
|
|
1228
|
+
activeTab = signal('form', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
1229
|
+
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
1102
1230
|
tabOptions = [
|
|
1103
1231
|
{
|
|
1104
|
-
label: '
|
|
1105
|
-
value: '
|
|
1232
|
+
label: 'Form',
|
|
1233
|
+
value: 'form',
|
|
1234
|
+
},
|
|
1235
|
+
{
|
|
1236
|
+
label: 'Discussion',
|
|
1237
|
+
value: 'discussion',
|
|
1106
1238
|
},
|
|
1107
1239
|
{
|
|
1108
|
-
label: '
|
|
1109
|
-
value: '
|
|
1240
|
+
label: 'Preview',
|
|
1241
|
+
value: 'preview',
|
|
1110
1242
|
},
|
|
1111
1243
|
];
|
|
1112
1244
|
itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
|
|
1245
|
+
requestId = computed(() => readNumber(this.itemContext(), 'requestId') ??
|
|
1246
|
+
readNumber(this.itemContext(), 'draftProcessId'), ...(ngDevMode ? [{ debugName: "requestId" }] : []));
|
|
1113
1247
|
moduleKey = computed(() => readString$1(this.itemContext(), 'moduleKey') ?? '', ...(ngDevMode ? [{ debugName: "moduleKey" }] : []));
|
|
1114
1248
|
operationKey = computed(() => readString$1(this.itemContext(), 'operationKey') ?? '', ...(ngDevMode ? [{ debugName: "operationKey" }] : []));
|
|
1115
1249
|
moduleId = computed(() => readNumber(this.itemContext(), 'moduleId'), ...(ngDevMode ? [{ debugName: "moduleId" }] : []));
|
|
@@ -1119,70 +1253,480 @@ class WorkCenterProcessStepType {
|
|
|
1119
1253
|
requestSchemaId = computed(() => readNumber(this.itemContext(), 'requestSchemaId'), ...(ngDevMode ? [{ debugName: "requestSchemaId" }] : []));
|
|
1120
1254
|
draftProcessId = computed(() => readNumber(this.itemContext(), 'draftProcessId') ??
|
|
1121
1255
|
readNumber(this.itemContext(), 'requestId'), ...(ngDevMode ? [{ debugName: "draftProcessId" }] : []));
|
|
1256
|
+
discussionRecordId = computed(() => this.requestId() ?? 0, ...(ngDevMode ? [{ debugName: "discussionRecordId" }] : []));
|
|
1122
1257
|
canRenderForm = computed(() => !!this.moduleKey() && !!this.operationKey(), ...(ngDevMode ? [{ debugName: "canRenderForm" }] : []));
|
|
1123
|
-
|
|
1258
|
+
canRenderDiscussion = computed(() => this.discussionRecordId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDiscussion" }] : []));
|
|
1259
|
+
canRenderPreview = computed(() => (this.requestId() ?? 0) > 0, ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
|
|
1260
|
+
constructor() {
|
|
1261
|
+
effect(() => {
|
|
1262
|
+
this.actionContext?.setClientForm(this.clientForm() ?? null);
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
onDiscussionReadStateChanged(state) {
|
|
1266
|
+
const resolvedUserId = state?.userId?.trim();
|
|
1267
|
+
if (resolvedUserId) {
|
|
1268
|
+
this.currentUserId.set(resolvedUserId);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
ngOnDestroy() {
|
|
1272
|
+
this.actionContext?.setClientForm(null);
|
|
1273
|
+
}
|
|
1124
1274
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1125
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterProcessStepType, isStandalone: true, selector: "mt-work-center-process-step-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== '
|
|
1275
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterProcessStepType, isStandalone: true, selector: "mt-work-center-process-step-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "clientForm", first: true, predicate: ClientForm, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1 p-4\" [hidden]=\"activeTab() !== 'form'\">\n <div class=\"flex-1\">\n @if (canRenderForm()) {\n <mt-client-form\n [moduleKey]=\"moduleKey()\"\n [operationKey]=\"operationKey()\"\n [moduleId]=\"moduleId()\"\n [levelId]=\"levelId()\"\n [levelDataId]=\"levelDataId()\"\n [moduleDataId]=\"moduleDataId()\"\n [requestSchemaId]=\"requestSchemaId()\"\n [draftProcessId]=\"draftProcessId()\"\n />\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process form context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'discussion'\">\n @if (canRenderDiscussion()) {\n <div class=\"h-[70vh] min-h-[32rem]\">\n <mt-discussion-thread\n [moduleType]=\"'ProcessRequest'\"\n [recordId]=\"discussionRecordId()\"\n [currentUserId]=\"currentUserId()\"\n [mentionSearchEndpoint]=\"'Identity/users'\"\n [mentionSearchParam]=\"'query'\"\n [mentionSearchDataPath]=\"'data'\"\n [uploadEndpoint]=\"'uploader'\"\n [attachmentDownloadEndpoint]=\"'uploader'\"\n [showParticipants]=\"true\"\n [autoMarkRead]=\"true\"\n [refreshIntervalMs]=\"0\"\n [styleClass]=\"'h-full'\"\n (readStateChanged)=\"onDiscussionReadStateChanged($event)\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Discussion context is not available for this process item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'preview'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json [requestId]=\"requestId()\" />\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview is not available for this process item yet.\n </p>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: ClientForm, selector: "mt-client-form", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "returnUrl", "readonly", "autoLoad", "formMode", "renderMode", "showInternalStepActions", "lang", "lookups"], outputs: ["loaded", "submitted", "errored", "modeDetected", "formSourceDetected"] }, { kind: "component", type: DiscussionThread, selector: "mt-discussion-thread", inputs: ["moduleType", "recordId", "title", "subtitle", "placeholder", "pageSize", "currentUserId", "requestContext", "mentionableUsers", "mentionSearchEndpoint", "mentionSearchParam", "mentionSearchDataPath", "allowAttachments", "uploadEndpoint", "attachmentDownloadEndpoint", "showParticipants", "autoMarkRead", "refreshIntervalMs", "styleClass", "disabled"], outputs: ["loaded", "errored", "commentCreated", "commentUpdated", "commentDeleted", "readStateChanged"] }, { kind: "component", type: WorkCenterProcessPreviewJson, selector: "mt-work-center-process-preview-json", inputs: ["requestId"] }] });
|
|
1126
1276
|
}
|
|
1127
1277
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, decorators: [{
|
|
1128
1278
|
type: Component,
|
|
1129
|
-
args: [{ selector: 'mt-work-center-process-step-type', standalone: true, imports: [
|
|
1130
|
-
|
|
1279
|
+
args: [{ selector: 'mt-work-center-process-step-type', standalone: true, imports: [
|
|
1280
|
+
CommonModule,
|
|
1281
|
+
Tabs,
|
|
1282
|
+
ClientForm,
|
|
1283
|
+
DiscussionThread,
|
|
1284
|
+
WorkCenterProcessPreviewJson,
|
|
1285
|
+
], template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1 p-4\" [hidden]=\"activeTab() !== 'form'\">\n <div class=\"flex-1\">\n @if (canRenderForm()) {\n <mt-client-form\n [moduleKey]=\"moduleKey()\"\n [operationKey]=\"operationKey()\"\n [moduleId]=\"moduleId()\"\n [levelId]=\"levelId()\"\n [levelDataId]=\"levelDataId()\"\n [moduleDataId]=\"moduleDataId()\"\n [requestSchemaId]=\"requestSchemaId()\"\n [draftProcessId]=\"draftProcessId()\"\n />\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process form context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'discussion'\">\n @if (canRenderDiscussion()) {\n <div class=\"h-[70vh] min-h-[32rem]\">\n <mt-discussion-thread\n [moduleType]=\"'ProcessRequest'\"\n [recordId]=\"discussionRecordId()\"\n [currentUserId]=\"currentUserId()\"\n [mentionSearchEndpoint]=\"'Identity/users'\"\n [mentionSearchParam]=\"'query'\"\n [mentionSearchDataPath]=\"'data'\"\n [uploadEndpoint]=\"'uploader'\"\n [attachmentDownloadEndpoint]=\"'uploader'\"\n [showParticipants]=\"true\"\n [autoMarkRead]=\"true\"\n [refreshIntervalMs]=\"0\"\n [styleClass]=\"'h-full'\"\n (readStateChanged)=\"onDiscussionReadStateChanged($event)\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Discussion context is not available for this process item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'preview'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json [requestId]=\"requestId()\" />\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Process preview is not available for this process item yet.\n </p>\n </div>\n }\n </div>\n</div>\n" }]
|
|
1286
|
+
}], ctorParameters: () => [], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }], clientForm: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ClientForm), { isSignal: true }] }] } });
|
|
1131
1287
|
|
|
1132
|
-
class
|
|
1288
|
+
class WorkCenterItemModal {
|
|
1133
1289
|
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
1134
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type:
|
|
1135
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type:
|
|
1290
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1291
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterItemModal, isStandalone: true, selector: "mt-work-center-item-modal", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (details().type === \"ProcessStep\") {\n <mt-work-center-process-step-type [details]=\"details()\" />\n} @else if (details().type === \"ProcessRequest\") {\n <mt-work-center-process-request-type [details]=\"details()\" />\n} @else if (details().type === \"EscalationInstance\") {\n <mt-work-center-escalation-instance-type [details]=\"details()\" />\n} @else {\n <div class=\"mt-modal-content flex h-full items-center justify-center p-4\">\n <p class=\"text-sm text-surface-500\">This item type is not supported yet.</p>\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: WorkCenterProcessStepType, selector: "mt-work-center-process-step-type", inputs: ["details"] }, { kind: "component", type: WorkCenterProcessRequestType, selector: "mt-work-center-process-request-type", inputs: ["details"] }, { kind: "component", type: WorkCenterEscalationInstanceType, selector: "mt-work-center-escalation-instance-type", inputs: ["details"] }] });
|
|
1136
1292
|
}
|
|
1137
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type:
|
|
1293
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModal, decorators: [{
|
|
1138
1294
|
type: Component,
|
|
1139
|
-
args: [{ selector: 'mt-work-center-item-
|
|
1295
|
+
args: [{ selector: 'mt-work-center-item-modal', standalone: true, imports: [
|
|
1140
1296
|
CommonModule,
|
|
1141
1297
|
WorkCenterProcessStepType,
|
|
1142
1298
|
WorkCenterProcessRequestType,
|
|
1143
1299
|
WorkCenterEscalationInstanceType,
|
|
1144
|
-
], template: "@if (details().type ===
|
|
1300
|
+
], template: "@if (details().type === \"ProcessStep\") {\n <mt-work-center-process-step-type [details]=\"details()\" />\n} @else if (details().type === \"ProcessRequest\") {\n <mt-work-center-process-request-type [details]=\"details()\" />\n} @else if (details().type === \"EscalationInstance\") {\n <mt-work-center-escalation-instance-type [details]=\"details()\" />\n} @else {\n <div class=\"mt-modal-content flex h-full items-center justify-center p-4\">\n <p class=\"text-sm text-surface-500\">This item type is not supported yet.</p>\n </div>\n}\n" }]
|
|
1145
1301
|
}], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
|
|
1146
1302
|
|
|
1147
|
-
class
|
|
1303
|
+
class WorkCenterItemActionConfirmDialog {
|
|
1304
|
+
ref = inject(ModalRef);
|
|
1305
|
+
modal = inject(ModalService);
|
|
1306
|
+
action = input.required(...(ngDevMode ? [{ debugName: "action" }] : []));
|
|
1307
|
+
formControl = new FormControl({});
|
|
1308
|
+
actionLabel = computed(() => this.action().actionName?.display || this.action().actionKey, ...(ngDevMode ? [{ debugName: "actionLabel" }] : []));
|
|
1309
|
+
formConfig = computed(() => ({
|
|
1310
|
+
sections: [
|
|
1311
|
+
{
|
|
1312
|
+
key: 'action-confirmation',
|
|
1313
|
+
type: 'none',
|
|
1314
|
+
fields: buildActionFields(this.action().payloadKeys, this.action().requiredPayloadKeys),
|
|
1315
|
+
},
|
|
1316
|
+
],
|
|
1317
|
+
}), ...(ngDevMode ? [{ debugName: "formConfig" }] : []));
|
|
1318
|
+
hasFormFields = computed(() => this.formConfig().sections[0]?.fields.length > 0, ...(ngDevMode ? [{ debugName: "hasFormFields" }] : []));
|
|
1319
|
+
onCancel() {
|
|
1320
|
+
this.ref.close(null);
|
|
1321
|
+
}
|
|
1322
|
+
onConfirm() {
|
|
1323
|
+
if (this.formControl.invalid) {
|
|
1324
|
+
this.formControl.markAllAsTouched();
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
this.ref.close(this.formControl.getRawValue() ?? {});
|
|
1328
|
+
}
|
|
1329
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionConfirmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1330
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterItemActionConfirmDialog, isStandalone: true, selector: "mt-work-center-item-action-confirm-dialog", inputs: { action: { classPropertyName: "action", publicName: "action", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"modal.contentClass +' p-4'\">\n @if (hasFormFields()) {\n <mt-dynamic-form [formConfig]=\"formConfig()\" [formControl]=\"formControl\" />\n } @else {\n <p class=\"text-sm text-surface-500\">\n Confirm {{ actionLabel() }} for this item.\n </p>\n }\n\n</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button label=\"Cancel\" severity=\"secondary\" variant=\"outlined\" (onClick)=\"onCancel()\" />\n <mt-button [label]=\"actionLabel()\" (onClick)=\"onConfirm()\" />\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { 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"] }] });
|
|
1331
|
+
}
|
|
1332
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionConfirmDialog, decorators: [{
|
|
1333
|
+
type: Component,
|
|
1334
|
+
args: [{ selector: 'mt-work-center-item-action-confirm-dialog', standalone: true, imports: [CommonModule, ReactiveFormsModule, DynamicForm, Button], template: "<div [class]=\"modal.contentClass +' p-4'\">\n @if (hasFormFields()) {\n <mt-dynamic-form [formConfig]=\"formConfig()\" [formControl]=\"formControl\" />\n } @else {\n <p class=\"text-sm text-surface-500\">\n Confirm {{ actionLabel() }} for this item.\n </p>\n }\n\n</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button label=\"Cancel\" severity=\"secondary\" variant=\"outlined\" (onClick)=\"onCancel()\" />\n <mt-button [label]=\"actionLabel()\" (onClick)=\"onConfirm()\" />\n</div>\n" }]
|
|
1335
|
+
}], propDecorators: { action: [{ type: i0.Input, args: [{ isSignal: true, alias: "action", required: true }] }] } });
|
|
1336
|
+
function buildActionFields(payloadKeys, requiredPayloadKeys) {
|
|
1337
|
+
const requestedKeys = new Set(payloadKeys ?? []);
|
|
1338
|
+
const requiredKeys = new Set(requiredPayloadKeys ?? []);
|
|
1339
|
+
const fields = [];
|
|
1340
|
+
if (requestedKeys.has('delegatedUser')) {
|
|
1341
|
+
fields.push({
|
|
1342
|
+
key: 'delegatedUser',
|
|
1343
|
+
type: 'user-search',
|
|
1344
|
+
label: 'Delegated User',
|
|
1345
|
+
placeholder: 'Search user',
|
|
1346
|
+
apiUrl: 'Identity/users',
|
|
1347
|
+
optionLabel: 'displayName',
|
|
1348
|
+
optionValue: 'id',
|
|
1349
|
+
validators: buildRequiredValidators(requiredKeys.has('delegatedUser')),
|
|
1350
|
+
colSpan: 12,
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
if (requestedKeys.has('reason')) {
|
|
1354
|
+
fields.push({
|
|
1355
|
+
key: 'reason',
|
|
1356
|
+
type: 'textarea',
|
|
1357
|
+
label: 'Reason',
|
|
1358
|
+
placeholder: 'Enter reason',
|
|
1359
|
+
rows: 4,
|
|
1360
|
+
validators: buildRequiredValidators(requiredKeys.has('reason')),
|
|
1361
|
+
colSpan: 12,
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
if (requestedKeys.has('note')) {
|
|
1365
|
+
fields.push({
|
|
1366
|
+
key: 'note',
|
|
1367
|
+
type: 'textarea',
|
|
1368
|
+
label: 'Note',
|
|
1369
|
+
placeholder: 'Enter note',
|
|
1370
|
+
rows: 4,
|
|
1371
|
+
validators: buildRequiredValidators(requiredKeys.has('note')),
|
|
1372
|
+
colSpan: 12,
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
if (requestedKeys.has('attachments')) {
|
|
1376
|
+
fields.push({
|
|
1377
|
+
key: 'attachments',
|
|
1378
|
+
type: 'upload-file',
|
|
1379
|
+
label: 'Attachments',
|
|
1380
|
+
endPoint: 'uploader',
|
|
1381
|
+
multiple: true,
|
|
1382
|
+
title: 'Upload Attachment',
|
|
1383
|
+
description: 'Click or drop a file to upload',
|
|
1384
|
+
validators: buildRequiredValidators(requiredKeys.has('attachments')),
|
|
1385
|
+
colSpan: 12,
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
return fields;
|
|
1389
|
+
}
|
|
1390
|
+
function buildRequiredValidators(required) {
|
|
1391
|
+
return required ? [ValidatorConfig.required()] : [];
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
class WorkCenterItemModalFooterActions {
|
|
1395
|
+
http = inject(HttpClient);
|
|
1396
|
+
modal = inject(ModalService);
|
|
1397
|
+
toast = inject(ToastService);
|
|
1398
|
+
actionContext = inject(WorkCenterItemActionContextStore);
|
|
1399
|
+
loadSub;
|
|
1400
|
+
executeSub;
|
|
1401
|
+
lastContextKey = null;
|
|
1402
|
+
contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : []));
|
|
1403
|
+
actionExecuted = output();
|
|
1404
|
+
visibilityChange = output();
|
|
1405
|
+
reloadTick = signal(0, ...(ngDevMode ? [{ debugName: "reloadTick" }] : []));
|
|
1406
|
+
hasResolvedLoad = signal(false, ...(ngDevMode ? [{ debugName: "hasResolvedLoad" }] : []));
|
|
1407
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1408
|
+
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
1409
|
+
actions = signal([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
|
|
1410
|
+
pendingActionKey = signal(null, ...(ngDevMode ? [{ debugName: "pendingActionKey" }] : []));
|
|
1411
|
+
displayActions = computed(() => this.actions()
|
|
1412
|
+
.filter((action) => action.isAvailable !== false &&
|
|
1413
|
+
!!action.url &&
|
|
1414
|
+
!!normalizeMethod(action.httpMethod))
|
|
1415
|
+
.map((action, index) => ({
|
|
1416
|
+
...action,
|
|
1417
|
+
label: action.actionName?.display || action.actionKey,
|
|
1418
|
+
severity: resolveActionSeverity(action.actionKey, index),
|
|
1419
|
+
variant: resolveActionVariant(action.actionKey, index),
|
|
1420
|
+
})), ...(ngDevMode ? [{ debugName: "displayActions" }] : []));
|
|
1421
|
+
shouldRender = computed(() => !!this.contextKey() &&
|
|
1422
|
+
(!this.hasResolvedLoad() ||
|
|
1423
|
+
this.loading() ||
|
|
1424
|
+
!!this.error() ||
|
|
1425
|
+
this.displayActions().length > 0 ||
|
|
1426
|
+
!!this.pendingActionKey()), ...(ngDevMode ? [{ debugName: "shouldRender" }] : []));
|
|
1427
|
+
constructor() {
|
|
1428
|
+
effect(() => {
|
|
1429
|
+
const contextKey = this.contextKey();
|
|
1430
|
+
this.reloadTick();
|
|
1431
|
+
this.error.set(null);
|
|
1432
|
+
if (!contextKey) {
|
|
1433
|
+
this.lastContextKey = null;
|
|
1434
|
+
this.actions.set([]);
|
|
1435
|
+
this.loading.set(false);
|
|
1436
|
+
this.hasResolvedLoad.set(false);
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
if (contextKey !== this.lastContextKey) {
|
|
1440
|
+
this.actions.set([]);
|
|
1441
|
+
this.lastContextKey = contextKey;
|
|
1442
|
+
}
|
|
1443
|
+
untracked(() => this.loadActions(contextKey));
|
|
1444
|
+
});
|
|
1445
|
+
effect(() => {
|
|
1446
|
+
this.visibilityChange.emit(this.shouldRender());
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
ngOnDestroy() {
|
|
1450
|
+
this.loadSub?.unsubscribe();
|
|
1451
|
+
this.executeSub?.unsubscribe();
|
|
1452
|
+
}
|
|
1453
|
+
executeAction(action) {
|
|
1454
|
+
const contextKey = this.contextKey();
|
|
1455
|
+
const method = normalizeMethod(action.httpMethod);
|
|
1456
|
+
const url = action.url?.trim();
|
|
1457
|
+
if (!contextKey ||
|
|
1458
|
+
!method ||
|
|
1459
|
+
!url ||
|
|
1460
|
+
action.isAvailable === false ||
|
|
1461
|
+
!!this.pendingActionKey()) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
if (action.needConfirmation) {
|
|
1465
|
+
this.openConfirmationDialog(action);
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
const payload = this.buildActionPayload(action);
|
|
1469
|
+
if (!this.ensurePayloadIsReady(action, payload)) {
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
this.runActionRequest(action, method, url, payload);
|
|
1473
|
+
}
|
|
1474
|
+
openConfirmationDialog(action) {
|
|
1475
|
+
const ref = this.modal.openModal(WorkCenterItemActionConfirmDialog, 'dialog', {
|
|
1476
|
+
header: action.label,
|
|
1477
|
+
width: '40rem',
|
|
1478
|
+
dismissableMask: true,
|
|
1479
|
+
inputValues: {
|
|
1480
|
+
action,
|
|
1481
|
+
},
|
|
1482
|
+
});
|
|
1483
|
+
ref.onClose
|
|
1484
|
+
.pipe(take(1))
|
|
1485
|
+
.subscribe((formValue) => {
|
|
1486
|
+
if (formValue == null) {
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
const method = normalizeMethod(action.httpMethod);
|
|
1490
|
+
const url = action.url?.trim();
|
|
1491
|
+
if (!method || !url) {
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
const payload = this.buildActionPayload(action, formValue);
|
|
1495
|
+
if (!this.ensurePayloadIsReady(action, payload)) {
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
this.runActionRequest(action, method, url, payload);
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
runActionRequest(action, method, url, payload) {
|
|
1502
|
+
this.error.set(null);
|
|
1503
|
+
this.pendingActionKey.set(action.actionKey);
|
|
1504
|
+
this.executeSub?.unsubscribe();
|
|
1505
|
+
this.executeSub = this.http
|
|
1506
|
+
.request(method, url, buildRequestOptions(method, payload))
|
|
1507
|
+
.pipe(map((response) => resolveActionSuccessMessage(response, `${action.label} completed successfully.`)))
|
|
1508
|
+
.subscribe({
|
|
1509
|
+
next: (message) => {
|
|
1510
|
+
this.pendingActionKey.set(null);
|
|
1511
|
+
this.toast.success(message);
|
|
1512
|
+
this.reloadTick.update((value) => value + 1);
|
|
1513
|
+
this.actionExecuted.emit();
|
|
1514
|
+
},
|
|
1515
|
+
error: (error) => {
|
|
1516
|
+
const message = resolveHttpErrorMessage(error, `Failed to execute ${action.label}.`);
|
|
1517
|
+
this.pendingActionKey.set(null);
|
|
1518
|
+
this.error.set(message);
|
|
1519
|
+
this.toast.error(message);
|
|
1520
|
+
},
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1523
|
+
buildActionPayload(action, formValue) {
|
|
1524
|
+
const payloadKeys = action.payloadKeys ?? [];
|
|
1525
|
+
if (!payloadKeys.length) {
|
|
1526
|
+
return undefined;
|
|
1527
|
+
}
|
|
1528
|
+
const payload = {};
|
|
1529
|
+
for (const key of payloadKeys) {
|
|
1530
|
+
const formFieldValue = formValue?.[key];
|
|
1531
|
+
if (formFieldValue !== undefined) {
|
|
1532
|
+
payload[key] = normalizePayloadValue(key, formFieldValue);
|
|
1533
|
+
continue;
|
|
1534
|
+
}
|
|
1535
|
+
const externalValue = this.resolveExternalPayloadValue(key, action);
|
|
1536
|
+
if (externalValue !== undefined) {
|
|
1537
|
+
payload[key] = externalValue;
|
|
1538
|
+
continue;
|
|
1539
|
+
}
|
|
1540
|
+
const defaultValue = resolveDefaultPayloadValue(key);
|
|
1541
|
+
if (defaultValue !== undefined) {
|
|
1542
|
+
payload[key] = defaultValue;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return Object.keys(payload).length ? payload : undefined;
|
|
1546
|
+
}
|
|
1547
|
+
ensurePayloadIsReady(action, payload) {
|
|
1548
|
+
const missingRequiredKeys = (action.requiredPayloadKeys ?? []).filter((key) => isMissingPayloadValue(payload?.[key]));
|
|
1549
|
+
if (!missingRequiredKeys.length) {
|
|
1550
|
+
return true;
|
|
1551
|
+
}
|
|
1552
|
+
const message = `Cannot execute ${action.label}. Missing: ${missingRequiredKeys.join(', ')}.`;
|
|
1553
|
+
this.error.set(message);
|
|
1554
|
+
this.toast.error(message);
|
|
1555
|
+
return false;
|
|
1556
|
+
}
|
|
1557
|
+
resolveExternalPayloadValue(key, action) {
|
|
1558
|
+
switch (key) {
|
|
1559
|
+
case 'stepId':
|
|
1560
|
+
return action.stepIds?.[0];
|
|
1561
|
+
case 'values':
|
|
1562
|
+
return this.actionContext.resolveFormValues();
|
|
1563
|
+
default:
|
|
1564
|
+
return undefined;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
loadActions(contextKey) {
|
|
1568
|
+
this.loadSub?.unsubscribe();
|
|
1569
|
+
this.loading.set(true);
|
|
1570
|
+
this.hasResolvedLoad.set(false);
|
|
1571
|
+
this.loadSub = this.http
|
|
1572
|
+
.get('workcenter/runtime/item-actions', {
|
|
1573
|
+
params: { contextKey },
|
|
1574
|
+
})
|
|
1575
|
+
.pipe(map((response) => {
|
|
1576
|
+
if (response.code === 1) {
|
|
1577
|
+
return response.data.actions ?? [];
|
|
1578
|
+
}
|
|
1579
|
+
throw new Error(resolveEnvelopeErrorMessage(response, 'Failed to load item actions.'));
|
|
1580
|
+
}))
|
|
1581
|
+
.subscribe({
|
|
1582
|
+
next: (actions) => {
|
|
1583
|
+
this.actions.set(actions);
|
|
1584
|
+
this.loading.set(false);
|
|
1585
|
+
this.hasResolvedLoad.set(true);
|
|
1586
|
+
},
|
|
1587
|
+
error: (error) => {
|
|
1588
|
+
this.actions.set([]);
|
|
1589
|
+
this.loading.set(false);
|
|
1590
|
+
this.hasResolvedLoad.set(true);
|
|
1591
|
+
this.error.set(resolveHttpErrorMessage(error, 'Failed to load item actions.'));
|
|
1592
|
+
},
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalFooterActions, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1596
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterItemModalFooterActions, isStandalone: true, selector: "mt-work-center-item-modal-footer-actions", inputs: { contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionExecuted: "actionExecuted", visibilityChange: "visibilityChange" }, host: { classAttribute: "flex w-full flex-1 flex-wrap items-center justify-end gap-2" }, ngImport: i0, template: "@if (shouldRender()) {\n @if (error(); as error) {\n <span class=\"me-auto max-w-md text-sm text-red-600\">\n {{ error }}\n </span>\n } @else if (loading() && !displayActions().length) {\n <span class=\"me-auto text-sm text-surface-500\">Loading actions...</span>\n }\n\n @for (action of displayActions(); track action.actionKey + action.url) {\n <mt-button\n [label]=\"action.label\"\n [severity]=\"action.severity\"\n [variant]=\"action.variant\"\n [disabled]=\"loading() || !!pendingActionKey()\"\n [loading]=\"pendingActionKey() === action.actionKey\"\n (onClick)=\"executeAction(action)\"\n />\n }\n}\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"] }] });
|
|
1597
|
+
}
|
|
1598
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalFooterActions, decorators: [{
|
|
1599
|
+
type: Component,
|
|
1600
|
+
args: [{ selector: 'mt-work-center-item-modal-footer-actions', standalone: true, imports: [CommonModule, Button], host: {
|
|
1601
|
+
class: 'flex w-full flex-1 flex-wrap items-center justify-end gap-2',
|
|
1602
|
+
}, template: "@if (shouldRender()) {\n @if (error(); as error) {\n <span class=\"me-auto max-w-md text-sm text-red-600\">\n {{ error }}\n </span>\n } @else if (loading() && !displayActions().length) {\n <span class=\"me-auto text-sm text-surface-500\">Loading actions...</span>\n }\n\n @for (action of displayActions(); track action.actionKey + action.url) {\n <mt-button\n [label]=\"action.label\"\n [severity]=\"action.severity\"\n [variant]=\"action.variant\"\n [disabled]=\"loading() || !!pendingActionKey()\"\n [loading]=\"pendingActionKey() === action.actionKey\"\n (onClick)=\"executeAction(action)\"\n />\n }\n}\n" }]
|
|
1603
|
+
}], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }], actionExecuted: [{ type: i0.Output, args: ["actionExecuted"] }], visibilityChange: [{ type: i0.Output, args: ["visibilityChange"] }] } });
|
|
1604
|
+
function buildRequestOptions(method, payload) {
|
|
1605
|
+
if (!payload || !methodSupportsBody(method)) {
|
|
1606
|
+
return { observe: 'body' };
|
|
1607
|
+
}
|
|
1608
|
+
return {
|
|
1609
|
+
body: payload,
|
|
1610
|
+
observe: 'body',
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function methodSupportsBody(method) {
|
|
1614
|
+
return ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method);
|
|
1615
|
+
}
|
|
1616
|
+
function normalizeMethod(value) {
|
|
1617
|
+
if (!value || typeof value !== 'string') {
|
|
1618
|
+
return null;
|
|
1619
|
+
}
|
|
1620
|
+
const method = value.trim().toUpperCase();
|
|
1621
|
+
return method.length ? method : null;
|
|
1622
|
+
}
|
|
1623
|
+
function normalizePayloadValue(key, value) {
|
|
1624
|
+
if (key === 'attachments') {
|
|
1625
|
+
if (value == null) {
|
|
1626
|
+
return [];
|
|
1627
|
+
}
|
|
1628
|
+
return Array.isArray(value) ? value : [value];
|
|
1629
|
+
}
|
|
1630
|
+
return value;
|
|
1631
|
+
}
|
|
1632
|
+
function resolveDefaultPayloadValue(key) {
|
|
1633
|
+
switch (key) {
|
|
1634
|
+
case 'attachments':
|
|
1635
|
+
return [];
|
|
1636
|
+
case 'delegatedUser':
|
|
1637
|
+
case 'note':
|
|
1638
|
+
case 'reason':
|
|
1639
|
+
return null;
|
|
1640
|
+
case 'values':
|
|
1641
|
+
return [];
|
|
1642
|
+
default:
|
|
1643
|
+
return undefined;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
function isMissingPayloadValue(value) {
|
|
1647
|
+
if (value == null) {
|
|
1648
|
+
return true;
|
|
1649
|
+
}
|
|
1650
|
+
if (typeof value === 'string') {
|
|
1651
|
+
return value.trim().length === 0;
|
|
1652
|
+
}
|
|
1653
|
+
if (Array.isArray(value)) {
|
|
1654
|
+
return value.length === 0;
|
|
1655
|
+
}
|
|
1656
|
+
return false;
|
|
1657
|
+
}
|
|
1658
|
+
function resolveActionSeverity(actionKey, index) {
|
|
1659
|
+
const normalized = actionKey.trim().toLowerCase();
|
|
1660
|
+
if (normalized === 'close' ||
|
|
1661
|
+
normalized === 'delete' ||
|
|
1662
|
+
normalized === 'reject' ||
|
|
1663
|
+
normalized === 'cancel') {
|
|
1664
|
+
return 'danger';
|
|
1665
|
+
}
|
|
1666
|
+
return index === 0 ? 'primary' : 'secondary';
|
|
1667
|
+
}
|
|
1668
|
+
function resolveActionVariant(actionKey, index) {
|
|
1669
|
+
const severity = resolveActionSeverity(actionKey, index);
|
|
1670
|
+
return severity === 'primary' ? undefined : 'outlined';
|
|
1671
|
+
}
|
|
1672
|
+
function resolveEnvelopeErrorMessage(response, fallback) {
|
|
1673
|
+
return (response?.errors?.message ??
|
|
1674
|
+
response?.message ??
|
|
1675
|
+
fallback);
|
|
1676
|
+
}
|
|
1677
|
+
function resolveActionSuccessMessage(response, fallback) {
|
|
1678
|
+
if (!response || typeof response !== 'object') {
|
|
1679
|
+
return fallback;
|
|
1680
|
+
}
|
|
1681
|
+
const apiResponse = response;
|
|
1682
|
+
if (typeof apiResponse.code === 'number' && apiResponse.code !== 1) {
|
|
1683
|
+
throw new Error(resolveEnvelopeErrorMessage(apiResponse, fallback));
|
|
1684
|
+
}
|
|
1685
|
+
return apiResponse.message?.trim() || fallback;
|
|
1686
|
+
}
|
|
1687
|
+
function resolveHttpErrorMessage(error, fallback) {
|
|
1688
|
+
if (!error || typeof error !== 'object') {
|
|
1689
|
+
return fallback;
|
|
1690
|
+
}
|
|
1691
|
+
const httpError = error;
|
|
1692
|
+
return httpError.error?.message ?? httpError.message ?? fallback;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
class WorkCenterItemModalRoute {
|
|
1148
1696
|
http = inject(HttpClient);
|
|
1149
1697
|
router = inject(Router);
|
|
1150
1698
|
route = inject(ActivatedRoute);
|
|
1699
|
+
modal = inject(ModalService);
|
|
1151
1700
|
contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : []));
|
|
1152
1701
|
drawerVisible = signal(true, ...(ngDevMode ? [{ debugName: "drawerVisible" }] : []));
|
|
1153
1702
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1154
1703
|
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
1155
1704
|
details = signal(null, ...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
1705
|
+
detailsReloadTick = signal(0, ...(ngDevMode ? [{ debugName: "detailsReloadTick" }] : []));
|
|
1706
|
+
footerActionsMounted = signal(false, ...(ngDevMode ? [{ debugName: "footerActionsMounted" }] : []));
|
|
1156
1707
|
resolvedContextKey = computed(() => this.decodeContextKey(this.contextKey()), ...(ngDevMode ? [{ debugName: "resolvedContextKey" }] : []));
|
|
1157
1708
|
drawerTitle = computed(() => this.readDisplayField(this.details()?.item, 'title') ?? 'Item Details', ...(ngDevMode ? [{ debugName: "drawerTitle" }] : []));
|
|
1158
1709
|
drawerSubtitle = computed(() => this.readDisplayField(this.details()?.item, 'subtitle') ?? '', ...(ngDevMode ? [{ debugName: "drawerSubtitle" }] : []));
|
|
1159
1710
|
constructor() {
|
|
1160
1711
|
effect(() => {
|
|
1161
|
-
|
|
1162
|
-
rawContextKey: this.contextKey(),
|
|
1163
|
-
resolvedContextKey: this.resolvedContextKey(),
|
|
1164
|
-
visible: this.drawerVisible(),
|
|
1165
|
-
loading: this.loading(),
|
|
1166
|
-
hasDetails: !!this.details(),
|
|
1167
|
-
error: this.error(),
|
|
1168
|
-
currentUrl: this.router.url,
|
|
1169
|
-
outlet: this.route.outlet,
|
|
1170
|
-
});
|
|
1712
|
+
this.footerActionsMounted.set(!!this.resolvedContextKey());
|
|
1171
1713
|
});
|
|
1172
1714
|
effect((onCleanup) => {
|
|
1173
1715
|
const contextKey = this.resolvedContextKey();
|
|
1174
|
-
|
|
1716
|
+
const reloadTick = this.detailsReloadTick();
|
|
1717
|
+
console.log('[work-center-debug] modal route load effect', {
|
|
1175
1718
|
contextKey,
|
|
1719
|
+
reloadTick,
|
|
1176
1720
|
});
|
|
1177
1721
|
this.error.set(null);
|
|
1178
1722
|
this.details.set(null);
|
|
1179
1723
|
if (!contextKey) {
|
|
1180
1724
|
this.loading.set(false);
|
|
1181
|
-
console.log('[work-center-debug]
|
|
1725
|
+
console.log('[work-center-debug] modal route load skipped, no context key');
|
|
1182
1726
|
return;
|
|
1183
1727
|
}
|
|
1184
1728
|
this.loading.set(true);
|
|
1185
|
-
console.log('[work-center-debug]
|
|
1729
|
+
console.log('[work-center-debug] modal route fetch start', {
|
|
1186
1730
|
endpoint: 'workcenter/runtime/item-basic-info',
|
|
1187
1731
|
contextKey,
|
|
1188
1732
|
});
|
|
@@ -1198,7 +1742,7 @@ class WorkCenterItemDrawerRoute {
|
|
|
1198
1742
|
}))
|
|
1199
1743
|
.subscribe({
|
|
1200
1744
|
next: (details) => {
|
|
1201
|
-
console.log('[work-center-debug]
|
|
1745
|
+
console.log('[work-center-debug] modal route fetch success', {
|
|
1202
1746
|
contextKey,
|
|
1203
1747
|
details,
|
|
1204
1748
|
});
|
|
@@ -1206,7 +1750,7 @@ class WorkCenterItemDrawerRoute {
|
|
|
1206
1750
|
this.loading.set(false);
|
|
1207
1751
|
},
|
|
1208
1752
|
error: (error) => {
|
|
1209
|
-
console.error('[work-center-debug]
|
|
1753
|
+
console.error('[work-center-debug] modal route fetch failed', {
|
|
1210
1754
|
contextKey,
|
|
1211
1755
|
error,
|
|
1212
1756
|
});
|
|
@@ -1219,16 +1763,22 @@ class WorkCenterItemDrawerRoute {
|
|
|
1219
1763
|
onCleanup(() => subscription.unsubscribe());
|
|
1220
1764
|
});
|
|
1221
1765
|
}
|
|
1766
|
+
onActionExecuted() {
|
|
1767
|
+
this.detailsReloadTick.update((value) => value + 1);
|
|
1768
|
+
}
|
|
1769
|
+
onFooterVisibilityChange(visible) {
|
|
1770
|
+
this.footerActionsMounted.set(visible);
|
|
1771
|
+
}
|
|
1222
1772
|
async onVisibleChange(visible) {
|
|
1223
1773
|
this.drawerVisible.set(visible);
|
|
1224
|
-
console.log('[work-center-debug]
|
|
1774
|
+
console.log('[work-center-debug] modal route visible change', { visible });
|
|
1225
1775
|
if (visible) {
|
|
1226
1776
|
return;
|
|
1227
1777
|
}
|
|
1228
|
-
await this.
|
|
1778
|
+
await this.closeRouteOutlet();
|
|
1229
1779
|
}
|
|
1230
|
-
|
|
1231
|
-
console.log('[work-center-debug]
|
|
1780
|
+
closeRouteOutlet() {
|
|
1781
|
+
console.log('[work-center-debug] modal route closing', {
|
|
1232
1782
|
outlet: this.route.outlet || 'sidebar',
|
|
1233
1783
|
parentUrl: this.route.parent?.snapshot.url.map((segment) => segment.path),
|
|
1234
1784
|
});
|
|
@@ -1239,7 +1789,7 @@ class WorkCenterItemDrawerRoute {
|
|
|
1239
1789
|
replaceUrl: true,
|
|
1240
1790
|
})
|
|
1241
1791
|
.then((success) => {
|
|
1242
|
-
console.log('[work-center-debug]
|
|
1792
|
+
console.log('[work-center-debug] modal route close navigate result', {
|
|
1243
1793
|
success,
|
|
1244
1794
|
currentUrl: this.router.url,
|
|
1245
1795
|
});
|
|
@@ -1276,12 +1826,18 @@ class WorkCenterItemDrawerRoute {
|
|
|
1276
1826
|
? display
|
|
1277
1827
|
: null;
|
|
1278
1828
|
}
|
|
1279
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type:
|
|
1280
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type:
|
|
1829
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalRoute, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1830
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterItemModalRoute, isStandalone: true, selector: "mt-work-center-item-modal-route", inputs: { contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null } }, providers: [WorkCenterItemActionContextStore], ngImport: i0, template: "<mt-drawer\n [visible]=\"drawerVisible()\"\n [loadingHeader]=\"loading()\"\n [title]=\"drawerTitle()\"\n [subtitle]=\"drawerSubtitle()\"\n [appendTo]=\"'system-content'\"\n styleClass=\"!w-[90%] !absolute \"\n position=\"right\"\n (visibleChange)=\"onVisibleChange($event)\"\n>\n <ng-container content>\n @if (loading()) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] flex-col gap-5\">\n <div class=\"flex items-center gap-3\">\n <p-skeleton shape=\"circle\" size=\"3rem\" />\n <div class=\"flex flex-1 flex-col gap-2\">\n <p-skeleton width=\"12rem\" height=\"1rem\" />\n <p-skeleton width=\"8rem\" height=\"0.875rem\" />\n </div>\n </div>\n\n <div class=\"grid gap-3 md:grid-cols-2\">\n @for (_ of [1, 2, 3, 4]; track $index) {\n <p-skeleton height=\"5rem\" borderRadius=\"1rem\" />\n }\n </div>\n\n <p-skeleton height=\"16rem\" borderRadius=\"1rem\" />\n </div>\n </div>\n } @else if (error(); as errorMessage) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"max-w-xl text-sm font-medium text-red-600\">\n {{ errorMessage }}\n </p>\n </div>\n </div>\n } @else if (details(); as details) {\n <mt-work-center-item-modal [details]=\"details\" />\n } @else {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"text-sm font-medium text-surface-500\">No item selected.</p>\n </div>\n </div>\n }\n </ng-container>\n\n @if (footerActionsMounted()) {\n <div footer [class]=\"modal.footerClass\">\n <mt-work-center-item-modal-footer-actions\n [contextKey]=\"resolvedContextKey()\"\n (actionExecuted)=\"onActionExecuted()\"\n (visibilityChange)=\"onFooterVisibilityChange($event)\"\n />\n </div>\n }\n</mt-drawer>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Drawer, selector: "mt-drawer", inputs: ["visible", "position", "fullScreen", "closeOnEscape", "blockScroll", "dismissible", "title", "subtitle", "loadingHeader", "styleClass", "transitionOptions", "appendTo", "modal"], outputs: ["visibleChange", "onShow", "onHide"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: WorkCenterItemModal, selector: "mt-work-center-item-modal", inputs: ["details"] }, { kind: "component", type: WorkCenterItemModalFooterActions, selector: "mt-work-center-item-modal-footer-actions", inputs: ["contextKey"], outputs: ["actionExecuted", "visibilityChange"] }] });
|
|
1281
1831
|
}
|
|
1282
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type:
|
|
1832
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalRoute, decorators: [{
|
|
1283
1833
|
type: Component,
|
|
1284
|
-
args: [{ selector: 'mt-work-center-item-
|
|
1834
|
+
args: [{ selector: 'mt-work-center-item-modal-route', standalone: true, imports: [
|
|
1835
|
+
CommonModule,
|
|
1836
|
+
Drawer,
|
|
1837
|
+
SkeletonModule,
|
|
1838
|
+
WorkCenterItemModal,
|
|
1839
|
+
WorkCenterItemModalFooterActions,
|
|
1840
|
+
], providers: [WorkCenterItemActionContextStore], template: "<mt-drawer\n [visible]=\"drawerVisible()\"\n [loadingHeader]=\"loading()\"\n [title]=\"drawerTitle()\"\n [subtitle]=\"drawerSubtitle()\"\n [appendTo]=\"'system-content'\"\n styleClass=\"!w-[90%] !absolute \"\n position=\"right\"\n (visibleChange)=\"onVisibleChange($event)\"\n>\n <ng-container content>\n @if (loading()) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] flex-col gap-5\">\n <div class=\"flex items-center gap-3\">\n <p-skeleton shape=\"circle\" size=\"3rem\" />\n <div class=\"flex flex-1 flex-col gap-2\">\n <p-skeleton width=\"12rem\" height=\"1rem\" />\n <p-skeleton width=\"8rem\" height=\"0.875rem\" />\n </div>\n </div>\n\n <div class=\"grid gap-3 md:grid-cols-2\">\n @for (_ of [1, 2, 3, 4]; track $index) {\n <p-skeleton height=\"5rem\" borderRadius=\"1rem\" />\n }\n </div>\n\n <p-skeleton height=\"16rem\" borderRadius=\"1rem\" />\n </div>\n </div>\n } @else if (error(); as errorMessage) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"max-w-xl text-sm font-medium text-red-600\">\n {{ errorMessage }}\n </p>\n </div>\n </div>\n } @else if (details(); as details) {\n <mt-work-center-item-modal [details]=\"details\" />\n } @else {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"text-sm font-medium text-surface-500\">No item selected.</p>\n </div>\n </div>\n }\n </ng-container>\n\n @if (footerActionsMounted()) {\n <div footer [class]=\"modal.footerClass\">\n <mt-work-center-item-modal-footer-actions\n [contextKey]=\"resolvedContextKey()\"\n (actionExecuted)=\"onActionExecuted()\"\n (visibilityChange)=\"onFooterVisibilityChange($event)\"\n />\n </div>\n }\n</mt-drawer>\n" }]
|
|
1285
1841
|
}], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }] } });
|
|
1286
1842
|
|
|
1287
1843
|
const APP_STATES = [WorkCenterState];
|
|
@@ -1290,5 +1846,5 @@ const APP_STATES = [WorkCenterState];
|
|
|
1290
1846
|
* Generated bundle index. Do not edit.
|
|
1291
1847
|
*/
|
|
1292
1848
|
|
|
1293
|
-
export { APP_STATES, EnterArea, HydrateFromContext, LoadRuntime, SetParams, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterFacade,
|
|
1849
|
+
export { APP_STATES, EnterArea, HydrateFromContext, LoadRuntime, SetParams, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterFacade, WorkCenterItemModal, WorkCenterItemModalRoute, WorkCenterPage, WorkCenterState };
|
|
1294
1850
|
//# sourceMappingURL=masterteam-work-center.mjs.map
|