@masterteam/work-center 0.0.3 → 0.0.4

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