@masterteam/work-center 0.0.2 → 0.0.3

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 } 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';
@@ -11,6 +12,13 @@ import { Action, Selector, State, Store, select } from '@ngxs/store';
11
12
  import { HttpClient } from '@angular/common/http';
12
13
  import { handleApiRequest } from '@masterteam/components';
13
14
  import { catchError, EMPTY, map } from 'rxjs';
15
+ import { EntitiesPreview } from '@masterteam/components/entities';
16
+ import { Tabs } from '@masterteam/components/tabs';
17
+ import { StructureBuilder } from '@masterteam/structure-builder';
18
+ import { ClientModulePreview } from '@masterteam/client-components/client-module-preview';
19
+ import { ClientForm } from '@masterteam/forms/client-form';
20
+ import { Router, ActivatedRoute } from '@angular/router';
21
+ import { Drawer } from '@masterteam/components/drawer';
14
22
 
15
23
  class EnterArea {
16
24
  area;
@@ -150,26 +158,42 @@ function toLabel$1(value) {
150
158
  .trim()
151
159
  .replace(/\b\w/g, (char) => char.toUpperCase());
152
160
  }
153
- function toColumnType(key) {
154
- return key.toLowerCase().includes('date') ? 'date' : 'text';
161
+ function toViewType(viewType, key) {
162
+ if (viewType?.trim()) {
163
+ return viewType;
164
+ }
165
+ return key.toLowerCase().includes('date') ? 'Date' : 'Text';
166
+ }
167
+ function getValue(record, key) {
168
+ return key.split('.').reduce((current, part) => {
169
+ if (!current || typeof current !== 'object') {
170
+ return undefined;
171
+ }
172
+ return current[part];
173
+ }, record);
155
174
  }
156
- function mapViewTypeToColumnType(viewType, key) {
157
- const normalized = viewType?.toLowerCase();
158
- if (normalized === 'date' || key.toLowerCase().includes('date')) {
159
- return 'date';
175
+ function toDisplayValue(value, column) {
176
+ if (column.viewType !== 'Text') {
177
+ return value;
160
178
  }
161
- return 'text';
179
+ if (!value || typeof value !== 'object') {
180
+ return value;
181
+ }
182
+ const display = value['display'];
183
+ return typeof display === 'string' ? display : value;
162
184
  }
163
185
  function buildColumnsFromProperties(properties) {
164
186
  return properties
165
187
  .filter((property) => typeof property?.key === 'string' && property.key.length > 0)
166
188
  .map((property) => ({
189
+ ...property,
167
190
  key: property.key,
168
191
  label: property.name?.display ||
169
192
  property.name?.en ||
170
193
  property.name?.ar ||
171
194
  toLabel$1(property.key),
172
- type: mapViewTypeToColumnType(property.viewType, property.key),
195
+ type: 'entity',
196
+ viewType: toViewType(property.viewType, property.key),
173
197
  }));
174
198
  }
175
199
  function buildColumns(columnsConfig) {
@@ -181,9 +205,23 @@ function buildColumns(columnsConfig) {
181
205
  return keys.map((key) => ({
182
206
  key,
183
207
  label: toLabel$1(key),
184
- type: toColumnType(key),
208
+ type: 'entity',
209
+ viewType: toViewType(undefined, key),
185
210
  }));
186
211
  }
212
+ function toDisplayRows(rows, columns) {
213
+ return rows.map((row) => {
214
+ const displayRow = { ...row };
215
+ for (const column of columns) {
216
+ const value = getValue(row, column.key);
217
+ displayRow[column.key] = {
218
+ ...column,
219
+ value: toDisplayValue(value, column),
220
+ };
221
+ }
222
+ return displayRow;
223
+ });
224
+ }
187
225
  function buildMenuItems(cards) {
188
226
  const mapped = cards.map((card, index) => ({
189
227
  key: card.key,
@@ -270,10 +308,14 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
270
308
  templateId: parsedTemplateId ?? currentContext.templateId,
271
309
  sort: hasParamValue(inputs.sort)
272
310
  ? parseSortInput(inputs.sort)
273
- : currentContext.sort,
311
+ : inputs.sort === null
312
+ ? []
313
+ : currentContext.sort,
274
314
  runtimeFilters: hasParamValue(inputs.filters)
275
315
  ? parseFiltersInput(inputs.filters)
276
- : currentContext.runtimeFilters,
316
+ : inputs.filters === null
317
+ ? []
318
+ : currentContext.runtimeFilters,
277
319
  });
278
320
  }
279
321
  function isSameContext(left, right) {
@@ -288,7 +330,6 @@ function isSameContext(left, right) {
288
330
  }
289
331
  function mapRuntimeResponse(current, response) {
290
332
  const selectedCard = response.selectedCard;
291
- const rows = selectedCard?.items ?? [];
292
333
  const menuItems = buildMenuItems(response.cards);
293
334
  const requestedCardKey = selectedCard?.key ?? current.context.selectedCardKey ?? null;
294
335
  const selectedCardKey = requestedCardKey &&
@@ -300,6 +341,7 @@ function mapRuntimeResponse(current, response) {
300
341
  : null;
301
342
  const selectedMenuItem = menuItems.find((item) => item.key === selectedCardKey);
302
343
  const columns = buildColumns(selectedCard?.columnsConfig ?? selectedCardFromList?.columnsConfig);
344
+ const rows = toDisplayRows(selectedCard?.items ?? [], columns);
303
345
  const kpis = buildKpis(selectedCard?.stats ?? [], selectedMenuItem?.icon ?? null);
304
346
  return {
305
347
  ...current,
@@ -716,10 +758,14 @@ function mapAllowedOperators(schema) {
716
758
  }
717
759
  class WorkCenterPage {
718
760
  facade = inject(WorkCenterFacade);
761
+ modal = inject(ModalService);
719
762
  area = input('MyInbox', ...(ngDevMode ? [{ debugName: "area" }] : []));
720
763
  pageTitle = input('Work Center', ...(ngDevMode ? [{ debugName: "pageTitle" }] : []));
721
764
  menuIcon = input('communication.inbox-01', ...(ngDevMode ? [{ debugName: "menuIcon" }] : []));
765
+ openItemsInDrawer = input(true, ...(ngDevMode ? [{ debugName: "openItemsInDrawer" }] : []));
766
+ itemDrawer = input(null, ...(ngDevMode ? [{ debugName: "itemDrawer" }] : []));
722
767
  runtimeFiltersChanged = output();
768
+ itemClicked = output();
723
769
  context = this.facade.context;
724
770
  menuItems = this.facade.menuItems;
725
771
  rows = this.facade.rows;
@@ -759,6 +805,7 @@ class WorkCenterPage {
759
805
  allowedOperators: fallbackOperators,
760
806
  };
761
807
  }, ...(ngDevMode ? [{ debugName: "propertyFilterSchema" }] : []));
808
+ defaultDrawerStyleClass = '!w-[96vw] xl:!w-[calc(100%-8rem)] 2xl:!w-[calc(100%-12rem)] !absolute !shadow-none';
762
809
  onMenuItemClick(item) {
763
810
  this.facade.selectCardAndLoad(this.area(), item.key);
764
811
  }
@@ -766,20 +813,61 @@ class WorkCenterPage {
766
813
  this.facade.applyTableLazyLoadAndLoad(this.area(), event);
767
814
  }
768
815
  onRuntimeFiltersApplied(filters) {
769
- this.runtimeFiltersChanged.emit(filters.map((filter) => ({
816
+ const mappedFilters = filters.map((filter) => ({
770
817
  field: filter.field,
771
818
  op: filter.op,
772
819
  value: filter.value,
773
820
  values: filter.values,
774
821
  from: filter.from,
775
822
  to: filter.to,
776
- })));
823
+ }));
824
+ this.facade.applyRuntimeFiltersAndLoad(this.area(), mappedFilters);
825
+ this.runtimeFiltersChanged.emit(mappedFilters);
777
826
  }
778
827
  onRuntimeFiltersCleared() {
828
+ this.facade.applyRuntimeFiltersAndLoad(this.area(), []);
779
829
  this.runtimeFiltersChanged.emit([]);
780
830
  }
831
+ onRowClick(row) {
832
+ const contextKey = this.resolveRowContextKey(row);
833
+ console.log('[work-center-debug] page row click', {
834
+ contextKey,
835
+ row,
836
+ openItemsInDrawer: this.openItemsInDrawer(),
837
+ hasDrawerComponent: !!this.itemDrawer()?.component,
838
+ });
839
+ if (!contextKey) {
840
+ return;
841
+ }
842
+ this.itemClicked.emit(contextKey);
843
+ if (!this.openItemsInDrawer()) {
844
+ return;
845
+ }
846
+ const drawerOptions = this.itemDrawer();
847
+ if (!drawerOptions?.component) {
848
+ return;
849
+ }
850
+ this.modal.openModal(drawerOptions.component, 'drawer', {
851
+ header: drawerOptions?.header ?? 'Item Details',
852
+ styleClass: drawerOptions?.styleClass ?? this.defaultDrawerStyleClass,
853
+ position: drawerOptions?.position ?? 'end',
854
+ dismissible: true,
855
+ modal: true,
856
+ ...(drawerOptions?.appendTo ? { appendTo: drawerOptions.appendTo } : {}),
857
+ inputValues: { contextKey },
858
+ });
859
+ }
860
+ rowsClickable = computed(() => this.openItemsInDrawer(), ...(ngDevMode ? [{ debugName: "rowsClickable" }] : []));
861
+ resolveRowContextKey(row) {
862
+ const value = row['contextKey'];
863
+ if (typeof value !== 'string') {
864
+ return null;
865
+ }
866
+ const normalized = value.trim();
867
+ return normalized.length ? normalized : null;
868
+ }
781
869
  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: " <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 class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3\">\r\n @for (_ of [1, 2, 3, 4]; 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 class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3\">\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 [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 />\r\n </div>\r\n </mt-client-page>\r\n\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", "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", "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"] }] });
870
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterPage, isStandalone: true, selector: "mt-work-center-page", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, menuIcon: { classPropertyName: "menuIcon", publicName: "menuIcon", isSignal: true, isRequired: false, transformFunction: null }, openItemsInDrawer: { classPropertyName: "openItemsInDrawer", publicName: "openItemsInDrawer", isSignal: true, isRequired: false, transformFunction: null }, itemDrawer: { classPropertyName: "itemDrawer", publicName: "itemDrawer", 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
871
  }
784
872
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, decorators: [{
785
873
  type: Component,
@@ -790,8 +878,411 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
790
878
  StatisticCard,
791
879
  Table,
792
880
  SkeletonModule,
793
- ], 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 class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3\">\r\n @for (_ of [1, 2, 3, 4]; 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 class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3\">\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 [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 />\r\n </div>\r\n </mt-client-page>\r\n\r\n" }]
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"] }] } });
881
+ ], template: "<mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"pageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n>\r\n <ng-template #headerClientPageEnd>\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"context().runtimeFilters\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n @if (loading()) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\r\n <p-skeleton height=\"6.5rem\" borderRadius=\"1rem\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n [data]=\"rows()\"\r\n [columns]=\"columns()\"\r\n [lazy]=\"true\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"tableCurrentPage()\"\r\n [first]=\"tableFirst()\"\r\n (lazyLoad)=\"onLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</mt-client-page>\r\n" }]
882
+ }], propDecorators: { area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], menuIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuIcon", required: false }] }], openItemsInDrawer: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemsInDrawer", required: false }] }], itemDrawer: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemDrawer", required: false }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
883
+
884
+ function readItemContext(details) {
885
+ const item = details.item;
886
+ if (!item || typeof item !== 'object') {
887
+ return null;
888
+ }
889
+ const context = item['context'];
890
+ return context && typeof context === 'object'
891
+ ? context
892
+ : null;
893
+ }
894
+ function readNumber(source, key) {
895
+ const value = source?.[key];
896
+ if (typeof value === 'number') {
897
+ return Number.isFinite(value) ? value : undefined;
898
+ }
899
+ if (typeof value === 'string' && value.trim().length) {
900
+ const parsed = Number(value);
901
+ return Number.isFinite(parsed) ? parsed : undefined;
902
+ }
903
+ return undefined;
904
+ }
905
+ function readString$1(source, key) {
906
+ const value = source?.[key];
907
+ return typeof value === 'string' && value.trim().length ? value : undefined;
908
+ }
909
+
910
+ class WorkCenterEscalationInstanceType {
911
+ http = inject(HttpClient);
912
+ loadSub;
913
+ details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
914
+ activeTab = signal('escalationDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
915
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
916
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
917
+ preview = signal(null, ...(ngDevMode ? [{ debugName: "preview" }] : []));
918
+ tabOptions = [
919
+ {
920
+ label: 'Escalation Details',
921
+ value: 'escalationDetails',
922
+ },
923
+ {
924
+ label: 'Schema',
925
+ value: 'schema',
926
+ },
927
+ ];
928
+ detailEntities = computed(() => {
929
+ const preview = this.preview();
930
+ if (!preview) {
931
+ return [];
932
+ }
933
+ return [
934
+ {
935
+ key: 'initiatedBy',
936
+ name: 'Initiated By',
937
+ value: mapUserValue(preview.initiatedBy),
938
+ viewType: 'User',
939
+ order: 1,
940
+ configuration: { size: 12 },
941
+ },
942
+ {
943
+ key: 'startedAt',
944
+ name: 'Started At',
945
+ value: resolveDisplayValue(preview.startedAt),
946
+ rawValue: resolveRawValue(preview.startedAt),
947
+ viewType: 'DateTime',
948
+ order: 2,
949
+ configuration: { size: 12 },
950
+ },
951
+ {
952
+ key: 'reason',
953
+ name: 'Reason',
954
+ value: preview.reason ?? '',
955
+ viewType: 'LongText',
956
+ order: 3,
957
+ configuration: { size: 24 },
958
+ },
959
+ {
960
+ key: 'attachments',
961
+ name: 'Attachments',
962
+ value: mapAttachments(preview.attachments),
963
+ viewType: 'Attachment',
964
+ order: 4,
965
+ configuration: { size: 24 },
966
+ },
967
+ ];
968
+ }, ...(ngDevMode ? [{ debugName: "detailEntities" }] : []));
969
+ schemaNodes = computed(() => resolveSchemaSteps(this.preview()).map((step) => ({
970
+ id: String(step.id),
971
+ name: resolveTranslatable(step.name) || `Step ${step.id}`,
972
+ color: step.isFinal ? '#059669' : step.isInitial ? '#2563eb' : '#0f172a',
973
+ })), ...(ngDevMode ? [{ debugName: "schemaNodes" }] : []));
974
+ schemaConnections = computed(() => (this.preview()?.schema?.connections ?? []).map((connection, index) => ({
975
+ id: String(connection.id ?? `${connection.source}-${connection.target}-${index}`),
976
+ from: String(connection.source),
977
+ to: String(connection.target),
978
+ })), ...(ngDevMode ? [{ debugName: "schemaConnections" }] : []));
979
+ hasSchema = computed(() => this.schemaNodes().length > 0, ...(ngDevMode ? [{ debugName: "hasSchema" }] : []));
980
+ itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
981
+ instanceId = computed(() => readNumber(this.itemContext(), 'escalationInstanceId') ??
982
+ readNumber(this.itemContext(), 'instanceId'), ...(ngDevMode ? [{ debugName: "instanceId" }] : []));
983
+ resolvedInstanceId = computed(() => this.instanceId() ?? 0, ...(ngDevMode ? [{ debugName: "resolvedInstanceId" }] : []));
984
+ canRenderDetails = computed(() => this.resolvedInstanceId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDetails" }] : []));
985
+ constructor() {
986
+ effect(() => {
987
+ const instanceId = this.resolvedInstanceId();
988
+ if (instanceId > 0) {
989
+ untracked(() => this.loadPreview(instanceId));
990
+ return;
991
+ }
992
+ this.preview.set(null);
993
+ this.error.set(null);
994
+ });
995
+ }
996
+ ngOnDestroy() {
997
+ this.loadSub?.unsubscribe();
998
+ }
999
+ loadPreview(instanceId) {
1000
+ this.loadSub?.unsubscribe();
1001
+ this.loading.set(true);
1002
+ this.error.set(null);
1003
+ this.loadSub = this.http
1004
+ .get(`escalations/${instanceId}/preview`)
1005
+ .subscribe({
1006
+ next: (response) => {
1007
+ this.loading.set(false);
1008
+ this.preview.set(response.data ?? null);
1009
+ },
1010
+ error: (error) => {
1011
+ this.loading.set(false);
1012
+ this.preview.set(null);
1013
+ this.error.set(error?.error?.message ??
1014
+ error?.message ??
1015
+ 'Failed to load escalation preview');
1016
+ },
1017
+ });
1018
+ }
1019
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterEscalationInstanceType, deps: [], target: i0.ɵɵFactoryTarget.Component });
1020
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterEscalationInstanceType, isStandalone: true, selector: "mt-work-center-escalation-instance-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'escalationDetails'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation details...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (preview()) {\n <mt-entities-preview [entities]=\"detailEntities()\" />\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation details context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation schema...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (hasSchema()) {\n <div class=\"h-[70vh] overflow-hidden rounded-2xl\">\n <mt-structure-builder\n class=\"h-full\"\n [readonly]=\"true\"\n [nodes]=\"schemaNodes()\"\n [connections]=\"schemaConnections()\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema is not available for this item yet.\n </p>\n </div>\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "nodeForm", "connectionForm", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
1021
+ }
1022
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterEscalationInstanceType, decorators: [{
1023
+ type: Component,
1024
+ args: [{ selector: 'mt-work-center-escalation-instance-type', standalone: true, imports: [CommonModule, Tabs, EntitiesPreview, StructureBuilder], template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'escalationDetails'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation details...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (preview()) {\n <mt-entities-preview [entities]=\"detailEntities()\" />\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation details context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderDetails()) {\n @if (loading()) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Loading escalation schema...\n </p>\n </div>\n } @else if (error(); as error) {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-red-300 bg-red-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-red-600\">\n {{ error }}\n </p>\n </div>\n } @else if (hasSchema()) {\n <div class=\"h-[70vh] overflow-hidden rounded-2xl\">\n <mt-structure-builder\n class=\"h-full\"\n [readonly]=\"true\"\n [nodes]=\"schemaNodes()\"\n [connections]=\"schemaConnections()\"\n />\n </div>\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema is not available for this item yet.\n </p>\n </div>\n }\n } @else {\n <div\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\n >\n <p class=\"max-w-md text-center text-sm text-surface-500\">\n Escalation schema context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n</div>\n" }]
1025
+ }], ctorParameters: () => [], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
1026
+ function mapUserValue(value) {
1027
+ if (!value || typeof value !== 'object') {
1028
+ return {
1029
+ displayName: '',
1030
+ userName: '',
1031
+ };
1032
+ }
1033
+ return {
1034
+ id: readString(value, 'id'),
1035
+ userName: readString(value, 'userName'),
1036
+ displayName: readString(value, 'displayName') ??
1037
+ readString(value, 'fullName') ??
1038
+ readString(value, 'userName') ??
1039
+ '',
1040
+ photoUrl: readString(value, 'photoUrl'),
1041
+ phoneNumber: readString(value, 'phoneNumber') ?? readString(value, 'mobileNumber'),
1042
+ email: readString(value, 'email') ?? readString(value, 'emailAddress'),
1043
+ };
1044
+ }
1045
+ function mapAttachments(attachments) {
1046
+ return (attachments ?? []).map((attachment) => ({
1047
+ id: attachment.id,
1048
+ name: attachment.name,
1049
+ fileName: attachment.fileName,
1050
+ contentType: attachment.contentType,
1051
+ extension: attachment.extension,
1052
+ size: attachment.size,
1053
+ }));
1054
+ }
1055
+ function resolveSchemaSteps(preview) {
1056
+ return preview?.schema?.stepsSchema ?? preview?.schemaSteps ?? [];
1057
+ }
1058
+ function resolveTranslatable(value) {
1059
+ if (!value || typeof value !== 'object') {
1060
+ return '';
1061
+ }
1062
+ return value.display ?? value.en ?? value.ar ?? '';
1063
+ }
1064
+ function resolveDisplayValue(value) {
1065
+ if (!value || typeof value !== 'object') {
1066
+ return typeof value === 'string' ? value : '';
1067
+ }
1068
+ return (readString(value, 'displayValue') ??
1069
+ readString(value, 'display') ??
1070
+ readString(value, 'actualValue') ??
1071
+ '');
1072
+ }
1073
+ function resolveRawValue(value) {
1074
+ if (!value || typeof value !== 'object') {
1075
+ return typeof value === 'string' ? value : undefined;
1076
+ }
1077
+ return (readString(value, 'actualValue') ??
1078
+ readString(value, 'displayValue') ??
1079
+ undefined);
1080
+ }
1081
+ function readString(value, key) {
1082
+ if (!value || typeof value !== 'object') {
1083
+ return undefined;
1084
+ }
1085
+ const result = value[key];
1086
+ return typeof result === 'string' && result.length ? result : undefined;
1087
+ }
1088
+
1089
+ class WorkCenterProcessRequestType {
1090
+ details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
1091
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, deps: [], target: i0.ɵɵFactoryTarget.Component });
1092
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.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 items-center justify-center p-4\">\n <p class=\"text-sm text-surface-500\">\n Process request content will be added here.\n </p>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1093
+ }
1094
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, decorators: [{
1095
+ type: Component,
1096
+ args: [{ selector: 'mt-work-center-process-request-type', standalone: true, imports: [CommonModule], template: "<div class=\"mt-modal-content flex h-full items-center justify-center p-4\">\n <p class=\"text-sm text-surface-500\">\n Process request content will be added here.\n </p>\n</div>\n" }]
1097
+ }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
1098
+
1099
+ class WorkCenterProcessStepType {
1100
+ details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
1101
+ activeTab = signal('processForm', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
1102
+ tabOptions = [
1103
+ {
1104
+ label: 'Process Form',
1105
+ value: 'processForm',
1106
+ },
1107
+ {
1108
+ label: 'Module Preview',
1109
+ value: 'modulePreview',
1110
+ },
1111
+ ];
1112
+ itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
1113
+ moduleKey = computed(() => readString$1(this.itemContext(), 'moduleKey') ?? '', ...(ngDevMode ? [{ debugName: "moduleKey" }] : []));
1114
+ operationKey = computed(() => readString$1(this.itemContext(), 'operationKey') ?? '', ...(ngDevMode ? [{ debugName: "operationKey" }] : []));
1115
+ moduleId = computed(() => readNumber(this.itemContext(), 'moduleId'), ...(ngDevMode ? [{ debugName: "moduleId" }] : []));
1116
+ levelId = computed(() => readNumber(this.itemContext(), 'levelId'), ...(ngDevMode ? [{ debugName: "levelId" }] : []));
1117
+ levelDataId = computed(() => readNumber(this.itemContext(), 'levelDataId'), ...(ngDevMode ? [{ debugName: "levelDataId" }] : []));
1118
+ moduleDataId = computed(() => readNumber(this.itemContext(), 'moduleDataId'), ...(ngDevMode ? [{ debugName: "moduleDataId" }] : []));
1119
+ requestSchemaId = computed(() => readNumber(this.itemContext(), 'requestSchemaId'), ...(ngDevMode ? [{ debugName: "requestSchemaId" }] : []));
1120
+ draftProcessId = computed(() => readNumber(this.itemContext(), 'draftProcessId') ??
1121
+ readNumber(this.itemContext(), 'requestId'), ...(ngDevMode ? [{ debugName: "draftProcessId" }] : []));
1122
+ canRenderForm = computed(() => !!this.moduleKey() && !!this.operationKey(), ...(ngDevMode ? [{ debugName: "canRenderForm" }] : []));
1123
+ canRenderPreview = computed(() => !!this.moduleKey() && !!this.operationKey(), ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
1124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, deps: [], target: i0.ɵɵFactoryTarget.Component });
1125
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterProcessStepType, isStandalone: true, selector: "mt-work-center-process-step-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"mt-modal-content flex h-full flex-col gap-4 p-4\">\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" />\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'processForm'\">\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 [renderMode]=\"'steps'\"\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\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'modulePreview'\">\n @if (canRenderPreview()) {\n <mt-client-module-preview\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 [formMode]=\"'edit'\"\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 Module preview 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: 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: ClientModulePreview, selector: "mt-client-module-preview", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "autoLoad", "lang", "formMode"], outputs: ["loaded", "errored"] }] });
1126
+ }
1127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, decorators: [{
1128
+ type: Component,
1129
+ args: [{ selector: 'mt-work-center-process-step-type', standalone: true, imports: [CommonModule, Tabs, ClientForm, ClientModulePreview], 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() !== 'processForm'\">\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 [renderMode]=\"'steps'\"\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\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'modulePreview'\">\n @if (canRenderPreview()) {\n <mt-client-module-preview\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 [formMode]=\"'edit'\"\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 Module preview context is not available for this item yet.\n </p>\n </div>\n }\n </div>\n</div>\n" }]
1130
+ }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
1131
+
1132
+ class WorkCenterItemDrawer {
1133
+ details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
1134
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
1135
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterItemDrawer, isStandalone: true, selector: "mt-work-center-item-drawer", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (details().type === 'ProcessStep') {\n <mt-work-center-process-step-type [details]=\"details()\" />\n} @else if (details().type === 'ProcessRequest') {\n <mt-work-center-process-request-type [details]=\"details()\" />\n} @else if (details().type === 'EscalationInstance') {\n <mt-work-center-escalation-instance-type [details]=\"details()\" />\n} @else {\n <div class=\"mt-modal-content flex h-full items-center justify-center p-4\">\n <p class=\"text-sm text-surface-500\">This item type is not supported yet.</p>\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: WorkCenterProcessStepType, selector: "mt-work-center-process-step-type", inputs: ["details"] }, { kind: "component", type: WorkCenterProcessRequestType, selector: "mt-work-center-process-request-type", inputs: ["details"] }, { kind: "component", type: WorkCenterEscalationInstanceType, selector: "mt-work-center-escalation-instance-type", inputs: ["details"] }] });
1136
+ }
1137
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemDrawer, decorators: [{
1138
+ type: Component,
1139
+ args: [{ selector: 'mt-work-center-item-drawer', standalone: true, imports: [
1140
+ CommonModule,
1141
+ WorkCenterProcessStepType,
1142
+ WorkCenterProcessRequestType,
1143
+ WorkCenterEscalationInstanceType,
1144
+ ], template: "@if (details().type === 'ProcessStep') {\n <mt-work-center-process-step-type [details]=\"details()\" />\n} @else if (details().type === 'ProcessRequest') {\n <mt-work-center-process-request-type [details]=\"details()\" />\n} @else if (details().type === 'EscalationInstance') {\n <mt-work-center-escalation-instance-type [details]=\"details()\" />\n} @else {\n <div class=\"mt-modal-content flex h-full items-center justify-center p-4\">\n <p class=\"text-sm text-surface-500\">This item type is not supported yet.</p>\n </div>\n}\n" }]
1145
+ }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
1146
+
1147
+ class WorkCenterItemDrawerRoute {
1148
+ http = inject(HttpClient);
1149
+ router = inject(Router);
1150
+ route = inject(ActivatedRoute);
1151
+ contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : []));
1152
+ drawerVisible = signal(true, ...(ngDevMode ? [{ debugName: "drawerVisible" }] : []));
1153
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1154
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1155
+ details = signal(null, ...(ngDevMode ? [{ debugName: "details" }] : []));
1156
+ resolvedContextKey = computed(() => this.decodeContextKey(this.contextKey()), ...(ngDevMode ? [{ debugName: "resolvedContextKey" }] : []));
1157
+ drawerTitle = computed(() => this.readDisplayField(this.details()?.item, 'title') ?? 'Item Details', ...(ngDevMode ? [{ debugName: "drawerTitle" }] : []));
1158
+ drawerSubtitle = computed(() => this.readDisplayField(this.details()?.item, 'subtitle') ?? '', ...(ngDevMode ? [{ debugName: "drawerSubtitle" }] : []));
1159
+ constructor() {
1160
+ effect(() => {
1161
+ console.log('[work-center-debug] drawer route state', {
1162
+ rawContextKey: this.contextKey(),
1163
+ resolvedContextKey: this.resolvedContextKey(),
1164
+ visible: this.drawerVisible(),
1165
+ loading: this.loading(),
1166
+ hasDetails: !!this.details(),
1167
+ error: this.error(),
1168
+ currentUrl: this.router.url,
1169
+ outlet: this.route.outlet,
1170
+ });
1171
+ });
1172
+ effect((onCleanup) => {
1173
+ const contextKey = this.resolvedContextKey();
1174
+ console.log('[work-center-debug] drawer route load effect', {
1175
+ contextKey,
1176
+ });
1177
+ this.error.set(null);
1178
+ this.details.set(null);
1179
+ if (!contextKey) {
1180
+ this.loading.set(false);
1181
+ console.log('[work-center-debug] drawer route load skipped, no context key');
1182
+ return;
1183
+ }
1184
+ this.loading.set(true);
1185
+ console.log('[work-center-debug] drawer route fetch start', {
1186
+ endpoint: 'workcenter/runtime/item-basic-info',
1187
+ contextKey,
1188
+ });
1189
+ const subscription = this.http
1190
+ .get('workcenter/runtime/item-basic-info', {
1191
+ params: { contextKey },
1192
+ })
1193
+ .pipe(map((response) => {
1194
+ if (response.code === 1) {
1195
+ return response.data;
1196
+ }
1197
+ throw new Error(this.resolveErrorMessage(response));
1198
+ }))
1199
+ .subscribe({
1200
+ next: (details) => {
1201
+ console.log('[work-center-debug] drawer route fetch success', {
1202
+ contextKey,
1203
+ details,
1204
+ });
1205
+ this.details.set(details);
1206
+ this.loading.set(false);
1207
+ },
1208
+ error: (error) => {
1209
+ console.error('[work-center-debug] drawer route fetch failed', {
1210
+ contextKey,
1211
+ error,
1212
+ });
1213
+ this.error.set(error instanceof Error
1214
+ ? error.message
1215
+ : 'Failed to load item details.');
1216
+ this.loading.set(false);
1217
+ },
1218
+ });
1219
+ onCleanup(() => subscription.unsubscribe());
1220
+ });
1221
+ }
1222
+ async onVisibleChange(visible) {
1223
+ this.drawerVisible.set(visible);
1224
+ console.log('[work-center-debug] drawer visible change', { visible });
1225
+ if (visible) {
1226
+ return;
1227
+ }
1228
+ await this.closeDrawer();
1229
+ }
1230
+ closeDrawer() {
1231
+ console.log('[work-center-debug] drawer closing', {
1232
+ outlet: this.route.outlet || 'sidebar',
1233
+ parentUrl: this.route.parent?.snapshot.url.map((segment) => segment.path),
1234
+ });
1235
+ return this.router
1236
+ .navigate([{ outlets: { [this.route.outlet || 'sidebar']: null } }], {
1237
+ relativeTo: this.route.parent,
1238
+ queryParamsHandling: 'merge',
1239
+ replaceUrl: true,
1240
+ })
1241
+ .then((success) => {
1242
+ console.log('[work-center-debug] drawer close navigate result', {
1243
+ success,
1244
+ currentUrl: this.router.url,
1245
+ });
1246
+ return success;
1247
+ });
1248
+ }
1249
+ decodeContextKey(value) {
1250
+ if (!value) {
1251
+ return null;
1252
+ }
1253
+ try {
1254
+ return decodeURIComponent(value);
1255
+ }
1256
+ catch {
1257
+ return value;
1258
+ }
1259
+ }
1260
+ resolveErrorMessage(response) {
1261
+ const fallbackError = 'Failed to load item details.';
1262
+ return (response.errors?.message ??
1263
+ response.message ??
1264
+ fallbackError);
1265
+ }
1266
+ readDisplayField(item, key) {
1267
+ const field = item?.[key];
1268
+ if (typeof field === 'string' && field.trim().length) {
1269
+ return field;
1270
+ }
1271
+ if (!field || typeof field !== 'object') {
1272
+ return null;
1273
+ }
1274
+ const display = field.display;
1275
+ return typeof display === 'string' && display.trim().length
1276
+ ? display
1277
+ : null;
1278
+ }
1279
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemDrawerRoute, deps: [], target: i0.ɵɵFactoryTarget.Component });
1280
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WorkCenterItemDrawerRoute, isStandalone: true, selector: "mt-work-center-item-drawer-route", inputs: { contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-drawer\r\n [visible]=\"drawerVisible()\"\r\n [loadingHeader]=\"loading()\"\r\n [title]=\"drawerTitle()\"\r\n [subtitle]=\"drawerSubtitle()\"\r\n [appendTo]=\"'system-content'\"\r\n styleClass=\"!w-[84%] !absolute !shadow-none\"\r\n position=\"right\"\r\n (visibleChange)=\"onVisibleChange($event)\"\r\n>\r\n <ng-container content>\r\n @if (loading()) {\r\n <div class=\"mt-modal-content p-4\">\r\n <div class=\"flex min-h-[22rem] flex-col gap-5\">\r\n <div class=\"flex items-center gap-3\">\r\n <p-skeleton shape=\"circle\" size=\"3rem\" />\r\n <div class=\"flex flex-1 flex-col gap-2\">\r\n <p-skeleton width=\"12rem\" height=\"1rem\" />\r\n <p-skeleton width=\"8rem\" height=\"0.875rem\" />\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid gap-3 md:grid-cols-2\">\r\n @for (_ of [1, 2, 3, 4]; track $index) {\r\n <p-skeleton height=\"5rem\" borderRadius=\"1rem\" />\r\n }\r\n </div>\r\n\r\n <p-skeleton height=\"16rem\" borderRadius=\"1rem\" />\r\n </div>\r\n </div>\r\n } @else if (error(); as errorMessage) {\r\n <div class=\"mt-modal-content p-4\">\r\n <div class=\"flex min-h-[22rem] items-center justify-center\">\r\n <p class=\"max-w-xl text-sm font-medium text-red-600\">\r\n {{ errorMessage }}\r\n </p>\r\n </div>\r\n </div>\r\n } @else if (details(); as details) {\r\n <mt-work-center-item-drawer [details]=\"details\" />\r\n } @else {\r\n <div class=\"mt-modal-content p-4\">\r\n <div class=\"flex min-h-[22rem] items-center justify-center\">\r\n <p class=\"text-sm font-medium text-surface-500\">No item selected.</p>\r\n </div>\r\n </div>\r\n }\r\n </ng-container>\r\n</mt-drawer>\r\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: WorkCenterItemDrawer, selector: "mt-work-center-item-drawer", inputs: ["details"] }] });
1281
+ }
1282
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemDrawerRoute, decorators: [{
1283
+ type: Component,
1284
+ args: [{ selector: 'mt-work-center-item-drawer-route', standalone: true, imports: [CommonModule, Drawer, SkeletonModule, WorkCenterItemDrawer], template: "<mt-drawer\r\n [visible]=\"drawerVisible()\"\r\n [loadingHeader]=\"loading()\"\r\n [title]=\"drawerTitle()\"\r\n [subtitle]=\"drawerSubtitle()\"\r\n [appendTo]=\"'system-content'\"\r\n styleClass=\"!w-[84%] !absolute !shadow-none\"\r\n position=\"right\"\r\n (visibleChange)=\"onVisibleChange($event)\"\r\n>\r\n <ng-container content>\r\n @if (loading()) {\r\n <div class=\"mt-modal-content p-4\">\r\n <div class=\"flex min-h-[22rem] flex-col gap-5\">\r\n <div class=\"flex items-center gap-3\">\r\n <p-skeleton shape=\"circle\" size=\"3rem\" />\r\n <div class=\"flex flex-1 flex-col gap-2\">\r\n <p-skeleton width=\"12rem\" height=\"1rem\" />\r\n <p-skeleton width=\"8rem\" height=\"0.875rem\" />\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid gap-3 md:grid-cols-2\">\r\n @for (_ of [1, 2, 3, 4]; track $index) {\r\n <p-skeleton height=\"5rem\" borderRadius=\"1rem\" />\r\n }\r\n </div>\r\n\r\n <p-skeleton height=\"16rem\" borderRadius=\"1rem\" />\r\n </div>\r\n </div>\r\n } @else if (error(); as errorMessage) {\r\n <div class=\"mt-modal-content p-4\">\r\n <div class=\"flex min-h-[22rem] items-center justify-center\">\r\n <p class=\"max-w-xl text-sm font-medium text-red-600\">\r\n {{ errorMessage }}\r\n </p>\r\n </div>\r\n </div>\r\n } @else if (details(); as details) {\r\n <mt-work-center-item-drawer [details]=\"details\" />\r\n } @else {\r\n <div class=\"mt-modal-content p-4\">\r\n <div class=\"flex min-h-[22rem] items-center justify-center\">\r\n <p class=\"text-sm font-medium text-surface-500\">No item selected.</p>\r\n </div>\r\n </div>\r\n }\r\n </ng-container>\r\n</mt-drawer>\r\n" }]
1285
+ }], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }] } });
795
1286
 
796
1287
  const APP_STATES = [WorkCenterState];
797
1288
 
@@ -799,5 +1290,5 @@ const APP_STATES = [WorkCenterState];
799
1290
  * Generated bundle index. Do not edit.
800
1291
  */
801
1292
 
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 };
1293
+ export { APP_STATES, EnterArea, HydrateFromContext, LoadRuntime, SetParams, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterFacade, WorkCenterItemDrawer, WorkCenterItemDrawerRoute, WorkCenterPage, WorkCenterState };
803
1294
  //# sourceMappingURL=masterteam-work-center.mjs.map