@masterteam/work-center 0.0.2 → 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,7 +1,8 @@
|
|
|
1
1
|
import { CommonModule } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, Injectable, computed, input, output, Component } 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
|
+
import { ModalService } from '@masterteam/components/modal';
|
|
5
6
|
import { PropertyFilterBuilder } from '@masterteam/components/property-filter-builder';
|
|
6
7
|
import { StatisticCard } from '@masterteam/components/statistic-card';
|
|
7
8
|
import { Table } from '@masterteam/components/table';
|
|
@@ -9,8 +10,21 @@ import * as i1 from 'primeng/skeleton';
|
|
|
9
10
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
10
11
|
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
11
12
|
import { HttpClient } from '@angular/common/http';
|
|
12
|
-
import { handleApiRequest } from '@masterteam/components';
|
|
13
|
-
import { catchError, EMPTY, map } from 'rxjs';
|
|
13
|
+
import { handleApiRequest, ValidatorConfig } from '@masterteam/components';
|
|
14
|
+
import { catchError, EMPTY, map, take } from 'rxjs';
|
|
15
|
+
import { EntitiesPreview } from '@masterteam/components/entities';
|
|
16
|
+
import { Tabs } from '@masterteam/components/tabs';
|
|
17
|
+
import { DiscussionThread } from '@masterteam/discussion';
|
|
18
|
+
import { StructureBuilder } from '@masterteam/structure-builder';
|
|
19
|
+
import { ClientForm } from '@masterteam/forms/client-form';
|
|
20
|
+
import { Router, ActivatedRoute } from '@angular/router';
|
|
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';
|
|
14
28
|
|
|
15
29
|
class EnterArea {
|
|
16
30
|
area;
|
|
@@ -150,26 +164,42 @@ function toLabel$1(value) {
|
|
|
150
164
|
.trim()
|
|
151
165
|
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
152
166
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
167
|
+
function toViewType(viewType, key) {
|
|
168
|
+
if (viewType?.trim()) {
|
|
169
|
+
return viewType;
|
|
170
|
+
}
|
|
171
|
+
return key.toLowerCase().includes('date') ? 'Date' : 'Text';
|
|
172
|
+
}
|
|
173
|
+
function getValue(record, key) {
|
|
174
|
+
return key.split('.').reduce((current, part) => {
|
|
175
|
+
if (!current || typeof current !== 'object') {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
return current[part];
|
|
179
|
+
}, record);
|
|
155
180
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return 'date';
|
|
181
|
+
function toDisplayValue(value, column) {
|
|
182
|
+
if (column.viewType !== 'Text') {
|
|
183
|
+
return value;
|
|
160
184
|
}
|
|
161
|
-
|
|
185
|
+
if (!value || typeof value !== 'object') {
|
|
186
|
+
return value;
|
|
187
|
+
}
|
|
188
|
+
const display = value['display'];
|
|
189
|
+
return typeof display === 'string' ? display : value;
|
|
162
190
|
}
|
|
163
191
|
function buildColumnsFromProperties(properties) {
|
|
164
192
|
return properties
|
|
165
193
|
.filter((property) => typeof property?.key === 'string' && property.key.length > 0)
|
|
166
194
|
.map((property) => ({
|
|
195
|
+
...property,
|
|
167
196
|
key: property.key,
|
|
168
197
|
label: property.name?.display ||
|
|
169
198
|
property.name?.en ||
|
|
170
199
|
property.name?.ar ||
|
|
171
200
|
toLabel$1(property.key),
|
|
172
|
-
type:
|
|
201
|
+
type: 'entity',
|
|
202
|
+
viewType: toViewType(property.viewType, property.key),
|
|
173
203
|
}));
|
|
174
204
|
}
|
|
175
205
|
function buildColumns(columnsConfig) {
|
|
@@ -181,9 +211,23 @@ function buildColumns(columnsConfig) {
|
|
|
181
211
|
return keys.map((key) => ({
|
|
182
212
|
key,
|
|
183
213
|
label: toLabel$1(key),
|
|
184
|
-
type:
|
|
214
|
+
type: 'entity',
|
|
215
|
+
viewType: toViewType(undefined, key),
|
|
185
216
|
}));
|
|
186
217
|
}
|
|
218
|
+
function toDisplayRows(rows, columns) {
|
|
219
|
+
return rows.map((row) => {
|
|
220
|
+
const displayRow = { ...row };
|
|
221
|
+
for (const column of columns) {
|
|
222
|
+
const value = getValue(row, column.key);
|
|
223
|
+
displayRow[column.key] = {
|
|
224
|
+
...column,
|
|
225
|
+
value: toDisplayValue(value, column),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return displayRow;
|
|
229
|
+
});
|
|
230
|
+
}
|
|
187
231
|
function buildMenuItems(cards) {
|
|
188
232
|
const mapped = cards.map((card, index) => ({
|
|
189
233
|
key: card.key,
|
|
@@ -270,10 +314,14 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
|
|
|
270
314
|
templateId: parsedTemplateId ?? currentContext.templateId,
|
|
271
315
|
sort: hasParamValue(inputs.sort)
|
|
272
316
|
? parseSortInput(inputs.sort)
|
|
273
|
-
:
|
|
317
|
+
: inputs.sort === null
|
|
318
|
+
? []
|
|
319
|
+
: currentContext.sort,
|
|
274
320
|
runtimeFilters: hasParamValue(inputs.filters)
|
|
275
321
|
? parseFiltersInput(inputs.filters)
|
|
276
|
-
:
|
|
322
|
+
: inputs.filters === null
|
|
323
|
+
? []
|
|
324
|
+
: currentContext.runtimeFilters,
|
|
277
325
|
});
|
|
278
326
|
}
|
|
279
327
|
function isSameContext(left, right) {
|
|
@@ -288,7 +336,6 @@ function isSameContext(left, right) {
|
|
|
288
336
|
}
|
|
289
337
|
function mapRuntimeResponse(current, response) {
|
|
290
338
|
const selectedCard = response.selectedCard;
|
|
291
|
-
const rows = selectedCard?.items ?? [];
|
|
292
339
|
const menuItems = buildMenuItems(response.cards);
|
|
293
340
|
const requestedCardKey = selectedCard?.key ?? current.context.selectedCardKey ?? null;
|
|
294
341
|
const selectedCardKey = requestedCardKey &&
|
|
@@ -300,6 +347,7 @@ function mapRuntimeResponse(current, response) {
|
|
|
300
347
|
: null;
|
|
301
348
|
const selectedMenuItem = menuItems.find((item) => item.key === selectedCardKey);
|
|
302
349
|
const columns = buildColumns(selectedCard?.columnsConfig ?? selectedCardFromList?.columnsConfig);
|
|
350
|
+
const rows = toDisplayRows(selectedCard?.items ?? [], columns);
|
|
303
351
|
const kpis = buildKpis(selectedCard?.stats ?? [], selectedMenuItem?.icon ?? null);
|
|
304
352
|
return {
|
|
305
353
|
...current,
|
|
@@ -716,10 +764,14 @@ function mapAllowedOperators(schema) {
|
|
|
716
764
|
}
|
|
717
765
|
class WorkCenterPage {
|
|
718
766
|
facade = inject(WorkCenterFacade);
|
|
767
|
+
modal = inject(ModalService);
|
|
719
768
|
area = input('MyInbox', ...(ngDevMode ? [{ debugName: "area" }] : []));
|
|
720
769
|
pageTitle = input('Work Center', ...(ngDevMode ? [{ debugName: "pageTitle" }] : []));
|
|
721
770
|
menuIcon = input('communication.inbox-01', ...(ngDevMode ? [{ debugName: "menuIcon" }] : []));
|
|
771
|
+
openItemsInModal = input(true, ...(ngDevMode ? [{ debugName: "openItemsInModal" }] : []));
|
|
772
|
+
itemModal = input(null, ...(ngDevMode ? [{ debugName: "itemModal" }] : []));
|
|
722
773
|
runtimeFiltersChanged = output();
|
|
774
|
+
itemClicked = output();
|
|
723
775
|
context = this.facade.context;
|
|
724
776
|
menuItems = this.facade.menuItems;
|
|
725
777
|
rows = this.facade.rows;
|
|
@@ -759,27 +811,72 @@ class WorkCenterPage {
|
|
|
759
811
|
allowedOperators: fallbackOperators,
|
|
760
812
|
};
|
|
761
813
|
}, ...(ngDevMode ? [{ debugName: "propertyFilterSchema" }] : []));
|
|
814
|
+
defaultModalStyleClass = '!w-[96vw] xl:!w-[calc(100%-8rem)] 2xl:!w-[calc(100%-12rem)] !absolute !shadow-none';
|
|
762
815
|
onMenuItemClick(item) {
|
|
816
|
+
if (item.key === this.context().selectedCardKey) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
763
819
|
this.facade.selectCardAndLoad(this.area(), item.key);
|
|
764
820
|
}
|
|
765
821
|
onLazyLoad(event) {
|
|
766
822
|
this.facade.applyTableLazyLoadAndLoad(this.area(), event);
|
|
767
823
|
}
|
|
768
824
|
onRuntimeFiltersApplied(filters) {
|
|
769
|
-
|
|
825
|
+
const mappedFilters = filters.map((filter) => ({
|
|
770
826
|
field: filter.field,
|
|
771
827
|
op: filter.op,
|
|
772
828
|
value: filter.value,
|
|
773
829
|
values: filter.values,
|
|
774
830
|
from: filter.from,
|
|
775
831
|
to: filter.to,
|
|
776
|
-
}))
|
|
832
|
+
}));
|
|
833
|
+
this.facade.applyRuntimeFiltersAndLoad(this.area(), mappedFilters);
|
|
834
|
+
this.runtimeFiltersChanged.emit(mappedFilters);
|
|
777
835
|
}
|
|
778
836
|
onRuntimeFiltersCleared() {
|
|
837
|
+
this.facade.applyRuntimeFiltersAndLoad(this.area(), []);
|
|
779
838
|
this.runtimeFiltersChanged.emit([]);
|
|
780
839
|
}
|
|
840
|
+
onRowClick(row) {
|
|
841
|
+
const contextKey = this.resolveRowContextKey(row);
|
|
842
|
+
console.log('[work-center-debug] page row click', {
|
|
843
|
+
contextKey,
|
|
844
|
+
row,
|
|
845
|
+
openItemsInModal: this.openItemsInModal(),
|
|
846
|
+
hasModalComponent: !!this.itemModal()?.component,
|
|
847
|
+
});
|
|
848
|
+
if (!contextKey) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
this.itemClicked.emit(contextKey);
|
|
852
|
+
if (!this.openItemsInModal()) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
const modalOptions = this.itemModal();
|
|
856
|
+
if (!modalOptions?.component) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
this.modal.openModal(modalOptions.component, 'drawer', {
|
|
860
|
+
header: modalOptions?.header ?? 'Item Details',
|
|
861
|
+
styleClass: modalOptions?.styleClass ?? this.defaultModalStyleClass,
|
|
862
|
+
position: modalOptions?.position ?? 'end',
|
|
863
|
+
dismissible: true,
|
|
864
|
+
modal: true,
|
|
865
|
+
...(modalOptions?.appendTo ? { appendTo: modalOptions.appendTo } : {}),
|
|
866
|
+
inputValues: { contextKey },
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
rowsClickable = computed(() => this.openItemsInModal(), ...(ngDevMode ? [{ debugName: "rowsClickable" }] : []));
|
|
870
|
+
resolveRowContextKey(row) {
|
|
871
|
+
const value = row['contextKey'];
|
|
872
|
+
if (typeof value !== 'string') {
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
const normalized = value.trim();
|
|
876
|
+
return normalized.length ? normalized : null;
|
|
877
|
+
}
|
|
781
878
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
782
|
-
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 } }, outputs: { runtimeFiltersChanged: "runtimeFiltersChanged" }, ngImport: i0, template: "
|
|
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"] }] });
|
|
783
880
|
}
|
|
784
881
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, decorators: [{
|
|
785
882
|
type: Component,
|
|
@@ -790,8 +887,958 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
790
887
|
StatisticCard,
|
|
791
888
|
Table,
|
|
792
889
|
SkeletonModule,
|
|
793
|
-
], template: "
|
|
794
|
-
}], 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 }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }] } });
|
|
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" }]
|
|
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"] }] } });
|
|
892
|
+
|
|
893
|
+
function readItemContext(details) {
|
|
894
|
+
const item = details.item;
|
|
895
|
+
if (!item || typeof item !== 'object') {
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
const context = item['context'];
|
|
899
|
+
return context && typeof context === 'object'
|
|
900
|
+
? context
|
|
901
|
+
: null;
|
|
902
|
+
}
|
|
903
|
+
function readNumber(source, key) {
|
|
904
|
+
const value = source?.[key];
|
|
905
|
+
if (typeof value === 'number') {
|
|
906
|
+
return Number.isFinite(value) ? value : undefined;
|
|
907
|
+
}
|
|
908
|
+
if (typeof value === 'string' && value.trim().length) {
|
|
909
|
+
const parsed = Number(value);
|
|
910
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
911
|
+
}
|
|
912
|
+
return undefined;
|
|
913
|
+
}
|
|
914
|
+
function readString$1(source, key) {
|
|
915
|
+
const value = source?.[key];
|
|
916
|
+
return typeof value === 'string' && value.trim().length ? value : undefined;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
class WorkCenterEscalationInstanceType {
|
|
920
|
+
http = inject(HttpClient);
|
|
921
|
+
loadSub;
|
|
922
|
+
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
923
|
+
activeTab = signal('escalationDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
924
|
+
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
925
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
926
|
+
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
927
|
+
preview = signal(null, ...(ngDevMode ? [{ debugName: "preview" }] : []));
|
|
928
|
+
tabOptions = [
|
|
929
|
+
{
|
|
930
|
+
label: 'Escalation Details',
|
|
931
|
+
value: 'escalationDetails',
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
label: 'Discussion',
|
|
935
|
+
value: 'discussion',
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
label: 'Schema',
|
|
939
|
+
value: 'schema',
|
|
940
|
+
},
|
|
941
|
+
];
|
|
942
|
+
detailEntities = computed(() => {
|
|
943
|
+
const preview = this.preview();
|
|
944
|
+
if (!preview) {
|
|
945
|
+
return [];
|
|
946
|
+
}
|
|
947
|
+
return [
|
|
948
|
+
{
|
|
949
|
+
key: 'initiatedBy',
|
|
950
|
+
name: 'Initiated By',
|
|
951
|
+
value: mapUserValue(preview.initiatedBy),
|
|
952
|
+
viewType: 'User',
|
|
953
|
+
order: 1,
|
|
954
|
+
configuration: { size: 12 },
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
key: 'startedAt',
|
|
958
|
+
name: 'Started At',
|
|
959
|
+
value: resolveDisplayValue(preview.startedAt),
|
|
960
|
+
rawValue: resolveRawValue(preview.startedAt),
|
|
961
|
+
viewType: 'DateTime',
|
|
962
|
+
order: 2,
|
|
963
|
+
configuration: { size: 12 },
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
key: 'reason',
|
|
967
|
+
name: 'Reason',
|
|
968
|
+
value: preview.reason ?? '',
|
|
969
|
+
viewType: 'LongText',
|
|
970
|
+
order: 3,
|
|
971
|
+
configuration: { size: 24 },
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
key: 'attachments',
|
|
975
|
+
name: 'Attachments',
|
|
976
|
+
value: preview.attachments ?? [],
|
|
977
|
+
viewType: 'Attachment',
|
|
978
|
+
order: 4,
|
|
979
|
+
configuration: { size: 24 },
|
|
980
|
+
},
|
|
981
|
+
];
|
|
982
|
+
}, ...(ngDevMode ? [{ debugName: "detailEntities" }] : []));
|
|
983
|
+
schemaNodes = computed(() => resolveSchemaSteps(this.preview()).map((step) => ({
|
|
984
|
+
id: String(step.id),
|
|
985
|
+
name: resolveTranslatable(step.name) || `Step ${step.id}`,
|
|
986
|
+
color: step.isFinal ? '#059669' : step.isInitial ? '#2563eb' : '#0f172a',
|
|
987
|
+
})), ...(ngDevMode ? [{ debugName: "schemaNodes" }] : []));
|
|
988
|
+
schemaConnections = computed(() => (this.preview()?.schema?.connections ?? []).map((connection, index) => ({
|
|
989
|
+
id: String(connection.id ?? `${connection.source}-${connection.target}-${index}`),
|
|
990
|
+
from: String(connection.source),
|
|
991
|
+
to: String(connection.target),
|
|
992
|
+
})), ...(ngDevMode ? [{ debugName: "schemaConnections" }] : []));
|
|
993
|
+
hasSchema = computed(() => this.schemaNodes().length > 0, ...(ngDevMode ? [{ debugName: "hasSchema" }] : []));
|
|
994
|
+
itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
|
|
995
|
+
instanceId = computed(() => readNumber(this.itemContext(), 'escalationInstanceId') ??
|
|
996
|
+
readNumber(this.itemContext(), 'instanceId'), ...(ngDevMode ? [{ debugName: "instanceId" }] : []));
|
|
997
|
+
resolvedInstanceId = computed(() => this.instanceId() ?? 0, ...(ngDevMode ? [{ debugName: "resolvedInstanceId" }] : []));
|
|
998
|
+
canRenderDetails = computed(() => this.resolvedInstanceId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDetails" }] : []));
|
|
999
|
+
canRenderDiscussion = computed(() => this.resolvedInstanceId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDiscussion" }] : []));
|
|
1000
|
+
constructor() {
|
|
1001
|
+
effect(() => {
|
|
1002
|
+
const instanceId = this.resolvedInstanceId();
|
|
1003
|
+
if (instanceId > 0) {
|
|
1004
|
+
untracked(() => this.loadPreview(instanceId));
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
this.preview.set(null);
|
|
1008
|
+
this.error.set(null);
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
ngOnDestroy() {
|
|
1012
|
+
this.loadSub?.unsubscribe();
|
|
1013
|
+
}
|
|
1014
|
+
onDiscussionReadStateChanged(state) {
|
|
1015
|
+
const resolvedUserId = state?.userId?.trim();
|
|
1016
|
+
if (resolvedUserId) {
|
|
1017
|
+
this.currentUserId.set(resolvedUserId);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
loadPreview(instanceId) {
|
|
1021
|
+
this.loadSub?.unsubscribe();
|
|
1022
|
+
this.loading.set(true);
|
|
1023
|
+
this.error.set(null);
|
|
1024
|
+
this.loadSub = this.http
|
|
1025
|
+
.get(`escalations/${instanceId}/preview`)
|
|
1026
|
+
.subscribe({
|
|
1027
|
+
next: (response) => {
|
|
1028
|
+
this.loading.set(false);
|
|
1029
|
+
this.preview.set(response.data ?? null);
|
|
1030
|
+
},
|
|
1031
|
+
error: (error) => {
|
|
1032
|
+
this.loading.set(false);
|
|
1033
|
+
this.preview.set(null);
|
|
1034
|
+
this.error.set(error?.error?.message ??
|
|
1035
|
+
error?.message ??
|
|
1036
|
+
'Failed to load escalation preview');
|
|
1037
|
+
},
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterEscalationInstanceType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
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"] }] });
|
|
1042
|
+
}
|
|
1043
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterEscalationInstanceType, decorators: [{
|
|
1044
|
+
type: Component,
|
|
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" }]
|
|
1052
|
+
}], ctorParameters: () => [], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
|
|
1053
|
+
function mapUserValue(value) {
|
|
1054
|
+
if (!value || typeof value !== 'object') {
|
|
1055
|
+
return {
|
|
1056
|
+
displayName: '',
|
|
1057
|
+
userName: '',
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
return {
|
|
1061
|
+
id: readString(value, 'id'),
|
|
1062
|
+
userName: readString(value, 'userName'),
|
|
1063
|
+
displayName: readString(value, 'displayName') ??
|
|
1064
|
+
readString(value, 'fullName') ??
|
|
1065
|
+
readString(value, 'userName') ??
|
|
1066
|
+
'',
|
|
1067
|
+
photoUrl: readString(value, 'photoUrl'),
|
|
1068
|
+
phoneNumber: readString(value, 'phoneNumber') ?? readString(value, 'mobileNumber'),
|
|
1069
|
+
email: readString(value, 'email') ?? readString(value, 'emailAddress'),
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
function resolveSchemaSteps(preview) {
|
|
1073
|
+
return preview?.schema?.stepsSchema ?? preview?.schemaSteps ?? [];
|
|
1074
|
+
}
|
|
1075
|
+
function resolveTranslatable(value) {
|
|
1076
|
+
if (!value || typeof value !== 'object') {
|
|
1077
|
+
return '';
|
|
1078
|
+
}
|
|
1079
|
+
return value.display ?? value.en ?? value.ar ?? '';
|
|
1080
|
+
}
|
|
1081
|
+
function resolveDisplayValue(value) {
|
|
1082
|
+
if (!value || typeof value !== 'object') {
|
|
1083
|
+
return typeof value === 'string' ? value : '';
|
|
1084
|
+
}
|
|
1085
|
+
return (readString(value, 'displayValue') ??
|
|
1086
|
+
readString(value, 'display') ??
|
|
1087
|
+
readString(value, 'actualValue') ??
|
|
1088
|
+
'');
|
|
1089
|
+
}
|
|
1090
|
+
function resolveRawValue(value) {
|
|
1091
|
+
if (!value || typeof value !== 'object') {
|
|
1092
|
+
return typeof value === 'string' ? value : undefined;
|
|
1093
|
+
}
|
|
1094
|
+
return (readString(value, 'actualValue') ??
|
|
1095
|
+
readString(value, 'displayValue') ??
|
|
1096
|
+
undefined);
|
|
1097
|
+
}
|
|
1098
|
+
function readString(value, key) {
|
|
1099
|
+
if (!value || typeof value !== 'object') {
|
|
1100
|
+
return undefined;
|
|
1101
|
+
}
|
|
1102
|
+
const result = value[key];
|
|
1103
|
+
return typeof result === 'string' && result.length ? result : undefined;
|
|
1104
|
+
}
|
|
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
|
+
|
|
1162
|
+
class WorkCenterProcessRequestType {
|
|
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
|
+
}
|
|
1192
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
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"] }] });
|
|
1194
|
+
}
|
|
1195
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, decorators: [{
|
|
1196
|
+
type: Component,
|
|
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" }]
|
|
1198
|
+
}], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
|
|
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
|
+
|
|
1222
|
+
class WorkCenterProcessStepType {
|
|
1223
|
+
actionContext = inject(WorkCenterItemActionContextStore, {
|
|
1224
|
+
optional: true,
|
|
1225
|
+
});
|
|
1226
|
+
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
1227
|
+
clientForm = viewChild(ClientForm, ...(ngDevMode ? [{ debugName: "clientForm" }] : []));
|
|
1228
|
+
activeTab = signal('form', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
1229
|
+
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
1230
|
+
tabOptions = [
|
|
1231
|
+
{
|
|
1232
|
+
label: 'Form',
|
|
1233
|
+
value: 'form',
|
|
1234
|
+
},
|
|
1235
|
+
{
|
|
1236
|
+
label: 'Discussion',
|
|
1237
|
+
value: 'discussion',
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
label: 'Preview',
|
|
1241
|
+
value: 'preview',
|
|
1242
|
+
},
|
|
1243
|
+
];
|
|
1244
|
+
itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
|
|
1245
|
+
requestId = computed(() => readNumber(this.itemContext(), 'requestId') ??
|
|
1246
|
+
readNumber(this.itemContext(), 'draftProcessId'), ...(ngDevMode ? [{ debugName: "requestId" }] : []));
|
|
1247
|
+
moduleKey = computed(() => readString$1(this.itemContext(), 'moduleKey') ?? '', ...(ngDevMode ? [{ debugName: "moduleKey" }] : []));
|
|
1248
|
+
operationKey = computed(() => readString$1(this.itemContext(), 'operationKey') ?? '', ...(ngDevMode ? [{ debugName: "operationKey" }] : []));
|
|
1249
|
+
moduleId = computed(() => readNumber(this.itemContext(), 'moduleId'), ...(ngDevMode ? [{ debugName: "moduleId" }] : []));
|
|
1250
|
+
levelId = computed(() => readNumber(this.itemContext(), 'levelId'), ...(ngDevMode ? [{ debugName: "levelId" }] : []));
|
|
1251
|
+
levelDataId = computed(() => readNumber(this.itemContext(), 'levelDataId'), ...(ngDevMode ? [{ debugName: "levelDataId" }] : []));
|
|
1252
|
+
moduleDataId = computed(() => readNumber(this.itemContext(), 'moduleDataId'), ...(ngDevMode ? [{ debugName: "moduleDataId" }] : []));
|
|
1253
|
+
requestSchemaId = computed(() => readNumber(this.itemContext(), 'requestSchemaId'), ...(ngDevMode ? [{ debugName: "requestSchemaId" }] : []));
|
|
1254
|
+
draftProcessId = computed(() => readNumber(this.itemContext(), 'draftProcessId') ??
|
|
1255
|
+
readNumber(this.itemContext(), 'requestId'), ...(ngDevMode ? [{ debugName: "draftProcessId" }] : []));
|
|
1256
|
+
discussionRecordId = computed(() => this.requestId() ?? 0, ...(ngDevMode ? [{ debugName: "discussionRecordId" }] : []));
|
|
1257
|
+
canRenderForm = computed(() => !!this.moduleKey() && !!this.operationKey(), ...(ngDevMode ? [{ debugName: "canRenderForm" }] : []));
|
|
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
|
+
}
|
|
1274
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
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"] }] });
|
|
1276
|
+
}
|
|
1277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, decorators: [{
|
|
1278
|
+
type: Component,
|
|
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 }] }] } });
|
|
1287
|
+
|
|
1288
|
+
class WorkCenterItemModal {
|
|
1289
|
+
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
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"] }] });
|
|
1292
|
+
}
|
|
1293
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModal, decorators: [{
|
|
1294
|
+
type: Component,
|
|
1295
|
+
args: [{ selector: 'mt-work-center-item-modal', standalone: true, imports: [
|
|
1296
|
+
CommonModule,
|
|
1297
|
+
WorkCenterProcessStepType,
|
|
1298
|
+
WorkCenterProcessRequestType,
|
|
1299
|
+
WorkCenterEscalationInstanceType,
|
|
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" }]
|
|
1301
|
+
}], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
|
|
1302
|
+
|
|
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 {
|
|
1696
|
+
http = inject(HttpClient);
|
|
1697
|
+
router = inject(Router);
|
|
1698
|
+
route = inject(ActivatedRoute);
|
|
1699
|
+
modal = inject(ModalService);
|
|
1700
|
+
contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : []));
|
|
1701
|
+
drawerVisible = signal(true, ...(ngDevMode ? [{ debugName: "drawerVisible" }] : []));
|
|
1702
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1703
|
+
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
1704
|
+
details = signal(null, ...(ngDevMode ? [{ debugName: "details" }] : []));
|
|
1705
|
+
detailsReloadTick = signal(0, ...(ngDevMode ? [{ debugName: "detailsReloadTick" }] : []));
|
|
1706
|
+
footerActionsMounted = signal(false, ...(ngDevMode ? [{ debugName: "footerActionsMounted" }] : []));
|
|
1707
|
+
resolvedContextKey = computed(() => this.decodeContextKey(this.contextKey()), ...(ngDevMode ? [{ debugName: "resolvedContextKey" }] : []));
|
|
1708
|
+
drawerTitle = computed(() => this.readDisplayField(this.details()?.item, 'title') ?? 'Item Details', ...(ngDevMode ? [{ debugName: "drawerTitle" }] : []));
|
|
1709
|
+
drawerSubtitle = computed(() => this.readDisplayField(this.details()?.item, 'subtitle') ?? '', ...(ngDevMode ? [{ debugName: "drawerSubtitle" }] : []));
|
|
1710
|
+
constructor() {
|
|
1711
|
+
effect(() => {
|
|
1712
|
+
this.footerActionsMounted.set(!!this.resolvedContextKey());
|
|
1713
|
+
});
|
|
1714
|
+
effect((onCleanup) => {
|
|
1715
|
+
const contextKey = this.resolvedContextKey();
|
|
1716
|
+
const reloadTick = this.detailsReloadTick();
|
|
1717
|
+
console.log('[work-center-debug] modal route load effect', {
|
|
1718
|
+
contextKey,
|
|
1719
|
+
reloadTick,
|
|
1720
|
+
});
|
|
1721
|
+
this.error.set(null);
|
|
1722
|
+
this.details.set(null);
|
|
1723
|
+
if (!contextKey) {
|
|
1724
|
+
this.loading.set(false);
|
|
1725
|
+
console.log('[work-center-debug] modal route load skipped, no context key');
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
this.loading.set(true);
|
|
1729
|
+
console.log('[work-center-debug] modal route fetch start', {
|
|
1730
|
+
endpoint: 'workcenter/runtime/item-basic-info',
|
|
1731
|
+
contextKey,
|
|
1732
|
+
});
|
|
1733
|
+
const subscription = this.http
|
|
1734
|
+
.get('workcenter/runtime/item-basic-info', {
|
|
1735
|
+
params: { contextKey },
|
|
1736
|
+
})
|
|
1737
|
+
.pipe(map((response) => {
|
|
1738
|
+
if (response.code === 1) {
|
|
1739
|
+
return response.data;
|
|
1740
|
+
}
|
|
1741
|
+
throw new Error(this.resolveErrorMessage(response));
|
|
1742
|
+
}))
|
|
1743
|
+
.subscribe({
|
|
1744
|
+
next: (details) => {
|
|
1745
|
+
console.log('[work-center-debug] modal route fetch success', {
|
|
1746
|
+
contextKey,
|
|
1747
|
+
details,
|
|
1748
|
+
});
|
|
1749
|
+
this.details.set(details);
|
|
1750
|
+
this.loading.set(false);
|
|
1751
|
+
},
|
|
1752
|
+
error: (error) => {
|
|
1753
|
+
console.error('[work-center-debug] modal route fetch failed', {
|
|
1754
|
+
contextKey,
|
|
1755
|
+
error,
|
|
1756
|
+
});
|
|
1757
|
+
this.error.set(error instanceof Error
|
|
1758
|
+
? error.message
|
|
1759
|
+
: 'Failed to load item details.');
|
|
1760
|
+
this.loading.set(false);
|
|
1761
|
+
},
|
|
1762
|
+
});
|
|
1763
|
+
onCleanup(() => subscription.unsubscribe());
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
onActionExecuted() {
|
|
1767
|
+
this.detailsReloadTick.update((value) => value + 1);
|
|
1768
|
+
}
|
|
1769
|
+
onFooterVisibilityChange(visible) {
|
|
1770
|
+
this.footerActionsMounted.set(visible);
|
|
1771
|
+
}
|
|
1772
|
+
async onVisibleChange(visible) {
|
|
1773
|
+
this.drawerVisible.set(visible);
|
|
1774
|
+
console.log('[work-center-debug] modal route visible change', { visible });
|
|
1775
|
+
if (visible) {
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
await this.closeRouteOutlet();
|
|
1779
|
+
}
|
|
1780
|
+
closeRouteOutlet() {
|
|
1781
|
+
console.log('[work-center-debug] modal route closing', {
|
|
1782
|
+
outlet: this.route.outlet || 'sidebar',
|
|
1783
|
+
parentUrl: this.route.parent?.snapshot.url.map((segment) => segment.path),
|
|
1784
|
+
});
|
|
1785
|
+
return this.router
|
|
1786
|
+
.navigate([{ outlets: { [this.route.outlet || 'sidebar']: null } }], {
|
|
1787
|
+
relativeTo: this.route.parent,
|
|
1788
|
+
queryParamsHandling: 'merge',
|
|
1789
|
+
replaceUrl: true,
|
|
1790
|
+
})
|
|
1791
|
+
.then((success) => {
|
|
1792
|
+
console.log('[work-center-debug] modal route close navigate result', {
|
|
1793
|
+
success,
|
|
1794
|
+
currentUrl: this.router.url,
|
|
1795
|
+
});
|
|
1796
|
+
return success;
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
decodeContextKey(value) {
|
|
1800
|
+
if (!value) {
|
|
1801
|
+
return null;
|
|
1802
|
+
}
|
|
1803
|
+
try {
|
|
1804
|
+
return decodeURIComponent(value);
|
|
1805
|
+
}
|
|
1806
|
+
catch {
|
|
1807
|
+
return value;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
resolveErrorMessage(response) {
|
|
1811
|
+
const fallbackError = 'Failed to load item details.';
|
|
1812
|
+
return (response.errors?.message ??
|
|
1813
|
+
response.message ??
|
|
1814
|
+
fallbackError);
|
|
1815
|
+
}
|
|
1816
|
+
readDisplayField(item, key) {
|
|
1817
|
+
const field = item?.[key];
|
|
1818
|
+
if (typeof field === 'string' && field.trim().length) {
|
|
1819
|
+
return field;
|
|
1820
|
+
}
|
|
1821
|
+
if (!field || typeof field !== 'object') {
|
|
1822
|
+
return null;
|
|
1823
|
+
}
|
|
1824
|
+
const display = field.display;
|
|
1825
|
+
return typeof display === 'string' && display.trim().length
|
|
1826
|
+
? display
|
|
1827
|
+
: null;
|
|
1828
|
+
}
|
|
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"] }] });
|
|
1831
|
+
}
|
|
1832
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalRoute, decorators: [{
|
|
1833
|
+
type: Component,
|
|
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" }]
|
|
1841
|
+
}], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }] } });
|
|
795
1842
|
|
|
796
1843
|
const APP_STATES = [WorkCenterState];
|
|
797
1844
|
|
|
@@ -799,5 +1846,5 @@ const APP_STATES = [WorkCenterState];
|
|
|
799
1846
|
* Generated bundle index. Do not edit.
|
|
800
1847
|
*/
|
|
801
1848
|
|
|
802
|
-
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, WorkCenterPage, WorkCenterState };
|
|
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 };
|
|
803
1850
|
//# sourceMappingURL=masterteam-work-center.mjs.map
|