@masterteam/work-center 0.0.1 → 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,8 +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 { Page } from '@masterteam/components/page';
5
+ import { ModalService } from '@masterteam/components/modal';
6
6
  import { PropertyFilterBuilder } from '@masterteam/components/property-filter-builder';
7
7
  import { StatisticCard } from '@masterteam/components/statistic-card';
8
8
  import { Table } from '@masterteam/components/table';
@@ -12,6 +12,13 @@ import { Action, Selector, State, Store, select } from '@ngxs/store';
12
12
  import { HttpClient } from '@angular/common/http';
13
13
  import { handleApiRequest } from '@masterteam/components';
14
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';
15
22
 
16
23
  class EnterArea {
17
24
  area;
@@ -151,26 +158,42 @@ function toLabel$1(value) {
151
158
  .trim()
152
159
  .replace(/\b\w/g, (char) => char.toUpperCase());
153
160
  }
154
- function toColumnType(key) {
155
- 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);
156
174
  }
157
- function mapViewTypeToColumnType(viewType, key) {
158
- const normalized = viewType?.toLowerCase();
159
- if (normalized === 'date' || key.toLowerCase().includes('date')) {
160
- return 'date';
175
+ function toDisplayValue(value, column) {
176
+ if (column.viewType !== 'Text') {
177
+ return value;
161
178
  }
162
- return 'text';
179
+ if (!value || typeof value !== 'object') {
180
+ return value;
181
+ }
182
+ const display = value['display'];
183
+ return typeof display === 'string' ? display : value;
163
184
  }
164
185
  function buildColumnsFromProperties(properties) {
165
186
  return properties
166
187
  .filter((property) => typeof property?.key === 'string' && property.key.length > 0)
167
188
  .map((property) => ({
189
+ ...property,
168
190
  key: property.key,
169
191
  label: property.name?.display ||
170
192
  property.name?.en ||
171
193
  property.name?.ar ||
172
194
  toLabel$1(property.key),
173
- type: mapViewTypeToColumnType(property.viewType, property.key),
195
+ type: 'entity',
196
+ viewType: toViewType(property.viewType, property.key),
174
197
  }));
175
198
  }
176
199
  function buildColumns(columnsConfig) {
@@ -182,9 +205,23 @@ function buildColumns(columnsConfig) {
182
205
  return keys.map((key) => ({
183
206
  key,
184
207
  label: toLabel$1(key),
185
- type: toColumnType(key),
208
+ type: 'entity',
209
+ viewType: toViewType(undefined, key),
186
210
  }));
187
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
+ }
188
225
  function buildMenuItems(cards) {
189
226
  const mapped = cards.map((card, index) => ({
190
227
  key: card.key,
@@ -271,10 +308,14 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
271
308
  templateId: parsedTemplateId ?? currentContext.templateId,
272
309
  sort: hasParamValue(inputs.sort)
273
310
  ? parseSortInput(inputs.sort)
274
- : currentContext.sort,
311
+ : inputs.sort === null
312
+ ? []
313
+ : currentContext.sort,
275
314
  runtimeFilters: hasParamValue(inputs.filters)
276
315
  ? parseFiltersInput(inputs.filters)
277
- : currentContext.runtimeFilters,
316
+ : inputs.filters === null
317
+ ? []
318
+ : currentContext.runtimeFilters,
278
319
  });
279
320
  }
280
321
  function isSameContext(left, right) {
@@ -289,7 +330,6 @@ function isSameContext(left, right) {
289
330
  }
290
331
  function mapRuntimeResponse(current, response) {
291
332
  const selectedCard = response.selectedCard;
292
- const rows = selectedCard?.items ?? [];
293
333
  const menuItems = buildMenuItems(response.cards);
294
334
  const requestedCardKey = selectedCard?.key ?? current.context.selectedCardKey ?? null;
295
335
  const selectedCardKey = requestedCardKey &&
@@ -301,6 +341,7 @@ function mapRuntimeResponse(current, response) {
301
341
  : null;
302
342
  const selectedMenuItem = menuItems.find((item) => item.key === selectedCardKey);
303
343
  const columns = buildColumns(selectedCard?.columnsConfig ?? selectedCardFromList?.columnsConfig);
344
+ const rows = toDisplayRows(selectedCard?.items ?? [], columns);
304
345
  const kpis = buildKpis(selectedCard?.stats ?? [], selectedMenuItem?.icon ?? null);
305
346
  return {
306
347
  ...current,
@@ -717,10 +758,14 @@ function mapAllowedOperators(schema) {
717
758
  }
718
759
  class WorkCenterPage {
719
760
  facade = inject(WorkCenterFacade);
761
+ modal = inject(ModalService);
720
762
  area = input('MyInbox', ...(ngDevMode ? [{ debugName: "area" }] : []));
721
763
  pageTitle = input('Work Center', ...(ngDevMode ? [{ debugName: "pageTitle" }] : []));
722
764
  menuIcon = input('communication.inbox-01', ...(ngDevMode ? [{ debugName: "menuIcon" }] : []));
765
+ openItemsInDrawer = input(true, ...(ngDevMode ? [{ debugName: "openItemsInDrawer" }] : []));
766
+ itemDrawer = input(null, ...(ngDevMode ? [{ debugName: "itemDrawer" }] : []));
723
767
  runtimeFiltersChanged = output();
768
+ itemClicked = output();
724
769
  context = this.facade.context;
725
770
  menuItems = this.facade.menuItems;
726
771
  rows = this.facade.rows;
@@ -760,6 +805,7 @@ class WorkCenterPage {
760
805
  allowedOperators: fallbackOperators,
761
806
  };
762
807
  }, ...(ngDevMode ? [{ debugName: "propertyFilterSchema" }] : []));
808
+ defaultDrawerStyleClass = '!w-[96vw] xl:!w-[calc(100%-8rem)] 2xl:!w-[calc(100%-12rem)] !absolute !shadow-none';
763
809
  onMenuItemClick(item) {
764
810
  this.facade.selectCardAndLoad(this.area(), item.key);
765
811
  }
@@ -767,33 +813,476 @@ class WorkCenterPage {
767
813
  this.facade.applyTableLazyLoadAndLoad(this.area(), event);
768
814
  }
769
815
  onRuntimeFiltersApplied(filters) {
770
- this.runtimeFiltersChanged.emit(filters.map((filter) => ({
816
+ const mappedFilters = filters.map((filter) => ({
771
817
  field: filter.field,
772
818
  op: filter.op,
773
819
  value: filter.value,
774
820
  values: filter.values,
775
821
  from: filter.from,
776
822
  to: filter.to,
777
- })));
823
+ }));
824
+ this.facade.applyRuntimeFiltersAndLoad(this.area(), mappedFilters);
825
+ this.runtimeFiltersChanged.emit(mappedFilters);
778
826
  }
779
827
  onRuntimeFiltersCleared() {
828
+ this.facade.applyRuntimeFiltersAndLoad(this.area(), []);
780
829
  this.runtimeFiltersChanged.emit([]);
781
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
+ }
782
869
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
783
- 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-page [title]=\"pageTitle()\" [avatarIcon]=\"menuIcon()\">\r\n <div class=\"h-full min-h-0\">\r\n <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 </div>\r\n</mt-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: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { 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"] }] });
784
871
  }
785
872
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterPage, decorators: [{
786
873
  type: Component,
787
874
  args: [{ selector: 'mt-work-center-page', standalone: true, imports: [
788
875
  CommonModule,
789
876
  ClientPage,
790
- Page,
791
877
  PropertyFilterBuilder,
792
878
  StatisticCard,
793
879
  Table,
794
880
  SkeletonModule,
795
- ], template: "<mt-page [title]=\"pageTitle()\" [avatarIcon]=\"menuIcon()\">\r\n <div class=\"h-full min-h-0\">\r\n <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 </div>\r\n</mt-page>\r\n" }]
796
- }], 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 }] }] } });
797
1286
 
798
1287
  const APP_STATES = [WorkCenterState];
799
1288
 
@@ -801,5 +1290,5 @@ const APP_STATES = [WorkCenterState];
801
1290
  * Generated bundle index. Do not edit.
802
1291
  */
803
1292
 
804
- 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 };
805
1294
  //# sourceMappingURL=masterteam-work-center.mjs.map