@masterteam/work-center 0.0.3 → 0.0.5

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;
@@ -902,7 +911,7 @@ function readNumber(source, key) {
902
911
  }
903
912
  return undefined;
904
913
  }
905
- function readString$1(source, key) {
914
+ function readString$2(source, key) {
906
915
  const value = source?.[key];
907
916
  return typeof value === 'string' && value.trim().length ? value : undefined;
908
917
  }
@@ -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') {
@@ -1031,27 +1058,17 @@ function mapUserValue(value) {
1031
1058
  };
1032
1059
  }
1033
1060
  return {
1034
- id: readString(value, 'id'),
1035
- userName: readString(value, 'userName'),
1036
- displayName: readString(value, 'displayName') ??
1037
- readString(value, 'fullName') ??
1038
- readString(value, 'userName') ??
1061
+ id: readString$1(value, 'id'),
1062
+ userName: readString$1(value, 'userName'),
1063
+ displayName: readString$1(value, 'displayName') ??
1064
+ readString$1(value, 'fullName') ??
1065
+ readString$1(value, 'userName') ??
1039
1066
  '',
1040
- photoUrl: readString(value, 'photoUrl'),
1041
- phoneNumber: readString(value, 'phoneNumber') ?? readString(value, 'mobileNumber'),
1042
- email: readString(value, 'email') ?? readString(value, 'emailAddress'),
1067
+ photoUrl: readString$1(value, 'photoUrl'),
1068
+ phoneNumber: readString$1(value, 'phoneNumber') ?? readString$1(value, 'mobileNumber'),
1069
+ email: readString$1(value, 'email') ?? readString$1(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
  }
@@ -1065,20 +1082,20 @@ function resolveDisplayValue(value) {
1065
1082
  if (!value || typeof value !== 'object') {
1066
1083
  return typeof value === 'string' ? value : '';
1067
1084
  }
1068
- return (readString(value, 'displayValue') ??
1069
- readString(value, 'display') ??
1070
- readString(value, 'actualValue') ??
1085
+ return (readString$1(value, 'displayValue') ??
1086
+ readString$1(value, 'display') ??
1087
+ readString$1(value, 'actualValue') ??
1071
1088
  '');
1072
1089
  }
1073
1090
  function resolveRawValue(value) {
1074
1091
  if (!value || typeof value !== 'object') {
1075
1092
  return typeof value === 'string' ? value : undefined;
1076
1093
  }
1077
- return (readString(value, 'actualValue') ??
1078
- readString(value, 'displayValue') ??
1094
+ return (readString$1(value, 'actualValue') ??
1095
+ readString$1(value, 'displayValue') ??
1079
1096
  undefined);
1080
1097
  }
1081
- function readString(value, key) {
1098
+ function readString$1(value, key) {
1082
1099
  if (!value || typeof value !== 'object') {
1083
1100
  return undefined;
1084
1101
  }
@@ -1086,32 +1103,209 @@ 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
+ view = input('approvals', ...(ngDevMode ? [{ debugName: "view" }] : []));
1111
+ approvalColumns = [
1112
+ { key: 'stepName', label: 'Name' },
1113
+ { key: 'status', label: 'Status' },
1114
+ { key: 'user', label: 'User', type: 'entity' },
1115
+ { key: 'createdAt', label: 'Initiation Date', type: 'entity' },
1116
+ { key: 'actionDate', label: 'Action Date', type: 'entity' },
1117
+ ];
1118
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1119
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1120
+ preview = signal(null, ...(ngDevMode ? [{ debugName: "preview" }] : []));
1121
+ canRenderPreview = computed(() => (this.requestId() ?? 0) > 0, ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
1122
+ approvalRows = computed(() => (this.preview()?.steps ?? []).map((step) => ({
1123
+ stepName: readDisplay(step.stepName) || String(step.stepId ?? '--'),
1124
+ status: readDisplay(step.status) || '--',
1125
+ user: buildEntity('User', 'User', (step.actionUserInfo ?? step.targetUser ?? null)),
1126
+ createdAt: buildEntity('Initiation Date', 'DateTime', step.createdAt ?? ''),
1127
+ actionDate: buildEntity('Action Date', 'DateTime', step.actionDate ?? ''),
1128
+ })), ...(ngDevMode ? [{ debugName: "approvalRows" }] : []));
1129
+ hasApprovals = computed(() => this.approvalRows().length > 0, ...(ngDevMode ? [{ debugName: "hasApprovals" }] : []));
1130
+ schemaNodes = computed(() => (this.preview()?.schema?.stepsSchema ?? []).map((step) => ({
1131
+ id: String(step.id),
1132
+ name: readDisplay(step.name) || String(step.id),
1133
+ color: step.isFinal ? '#059669' : step.isInitial ? '#2563eb' : '#0f172a',
1134
+ })), ...(ngDevMode ? [{ debugName: "schemaNodes" }] : []));
1135
+ schemaConnections = computed(() => (this.preview()?.schema?.connections ?? []).map((connection, index) => ({
1136
+ id: String(connection.id ?? `${connection.source}-${connection.target}-${index}`),
1137
+ from: String(connection.source),
1138
+ to: String(connection.target),
1139
+ })), ...(ngDevMode ? [{ debugName: "schemaConnections" }] : []));
1140
+ hasSchema = computed(() => this.schemaNodes().length > 0, ...(ngDevMode ? [{ debugName: "hasSchema" }] : []));
1141
+ constructor() {
1142
+ effect(() => {
1143
+ const requestId = this.requestId() ?? 0;
1144
+ if (requestId > 0) {
1145
+ untracked(() => this.loadPreview(requestId));
1146
+ return;
1147
+ }
1148
+ this.loadSub?.unsubscribe();
1149
+ this.loading.set(false);
1150
+ this.error.set(null);
1151
+ this.preview.set(null);
1152
+ });
1153
+ }
1154
+ ngOnDestroy() {
1155
+ this.loadSub?.unsubscribe();
1156
+ }
1157
+ loadPreview(requestId) {
1158
+ this.loadSub?.unsubscribe();
1159
+ this.loading.set(true);
1160
+ this.error.set(null);
1161
+ this.loadSub = this.http
1162
+ .get(`processes/${requestId}/preview`)
1163
+ .subscribe({
1164
+ next: (response) => {
1165
+ this.loading.set(false);
1166
+ this.preview.set(response.data ?? null);
1167
+ },
1168
+ error: (error) => {
1169
+ this.loading.set(false);
1170
+ this.preview.set(null);
1171
+ this.error.set(error?.error?.message ??
1172
+ error?.message ??
1173
+ 'Failed to load process preview');
1174
+ },
1175
+ });
1176
+ }
1177
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessPreviewJson, deps: [], target: i0.ɵɵFactoryTarget.Component });
1178
+ 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 }, view: { classPropertyName: "view", publicName: "view", 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 {\n @if (view() === 'schema') {\n @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 Process steps are not available for this item yet.\n </p>\n </div>\n }\n } @else if (hasApprovals()) {\n <mt-table\n [data]=\"approvalRows()\"\n [columns]=\"approvalColumns\"\n [showFilters]=\"false\"\n [generalSearch]=\"false\"\n [clickableRows]=\"false\"\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 approvals data is not available for this item yet.\n </p>\n </div>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "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"] }] });
1179
+ }
1180
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessPreviewJson, decorators: [{
1181
+ type: Component,
1182
+ args: [{ selector: 'mt-work-center-process-preview-json', standalone: true, imports: [CommonModule, Table, StructureBuilder], 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 {\n @if (view() === 'schema') {\n @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 Process steps are not available for this item yet.\n </p>\n </div>\n }\n } @else if (hasApprovals()) {\n <mt-table\n [data]=\"approvalRows()\"\n [columns]=\"approvalColumns\"\n [showFilters]=\"false\"\n [generalSearch]=\"false\"\n [clickableRows]=\"false\"\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 approvals data is not available for this item yet.\n </p>\n </div>\n }\n}\n" }]
1183
+ }], ctorParameters: () => [], propDecorators: { requestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestId", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }] } });
1184
+ function buildEntity(name, viewType, value) {
1185
+ return {
1186
+ name,
1187
+ viewType,
1188
+ value: value ?? '',
1189
+ configuration: {
1190
+ hideName: true,
1191
+ },
1192
+ };
1193
+ }
1194
+ function readDisplay(value) {
1195
+ if (typeof value === 'string') {
1196
+ return value;
1197
+ }
1198
+ if (typeof value === 'number' || typeof value === 'boolean') {
1199
+ return String(value);
1200
+ }
1201
+ if (value && typeof value === 'object') {
1202
+ return (readString(value, 'display') ??
1203
+ readString(value, 'en') ??
1204
+ readString(value, 'ar') ??
1205
+ '');
1206
+ }
1207
+ return '';
1208
+ }
1209
+ function readString(source, key) {
1210
+ const value = source[key];
1211
+ return typeof value === 'string' ? value : undefined;
1212
+ }
1213
+
1089
1214
  class WorkCenterProcessRequestType {
1090
1215
  details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
1216
+ activeTab = signal('requestDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
1217
+ currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
1218
+ tabOptions = [
1219
+ {
1220
+ label: 'Request Details',
1221
+ value: 'requestDetails',
1222
+ },
1223
+ {
1224
+ label: 'Approvals',
1225
+ value: 'approvals',
1226
+ },
1227
+ {
1228
+ label: 'Steps',
1229
+ value: 'schema',
1230
+ },
1231
+ {
1232
+ label: 'Discussion',
1233
+ value: 'discussion',
1234
+ },
1235
+ ];
1236
+ itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
1237
+ requestId = computed(() => readNumber(this.itemContext(), 'requestId') ??
1238
+ readNumber(this.itemContext(), 'draftProcessId'), ...(ngDevMode ? [{ debugName: "requestId" }] : []));
1239
+ discussionRecordId = computed(() => this.requestId() ?? 0, ...(ngDevMode ? [{ debugName: "discussionRecordId" }] : []));
1240
+ canRenderDiscussion = computed(() => this.discussionRecordId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDiscussion" }] : []));
1241
+ canRenderPreview = computed(() => (this.requestId() ?? 0) > 0, ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
1242
+ onDiscussionReadStateChanged(state) {
1243
+ const resolvedUserId = state?.userId?.trim();
1244
+ if (resolvedUserId) {
1245
+ this.currentUserId.set(resolvedUserId);
1246
+ }
1247
+ }
1091
1248
  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 }] });
1249
+ 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() !== 'approvals'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'approvals'\"\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 preview is not available for this process request yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'schema'\"\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 preview is not available for this process request 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]=\"'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</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", "view"] }] });
1093
1250
  }
1094
1251
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessRequestType, decorators: [{
1095
1252
  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" }]
1253
+ 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() !== 'approvals'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'approvals'\"\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 preview is not available for this process request yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'schema'\"\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 preview is not available for this process request 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]=\"'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</div>\n" }]
1097
1254
  }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
1098
1255
 
1256
+ class WorkCenterItemActionContextStore {
1257
+ clientForm = signal(null, ...(ngDevMode ? [{ debugName: "clientForm" }] : []));
1258
+ setClientForm(clientForm) {
1259
+ this.clientForm.set(clientForm);
1260
+ }
1261
+ resolveFormValues() {
1262
+ const values = this.clientForm()?.getSubmitValues();
1263
+ return Array.isArray(values)
1264
+ ? values.map((value) => ({
1265
+ requestPropertyId: value.requestPropertyId,
1266
+ propertyKey: value.propertyKey,
1267
+ value: value.value,
1268
+ }))
1269
+ : [];
1270
+ }
1271
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionContextStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1272
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionContextStore });
1273
+ }
1274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionContextStore, decorators: [{
1275
+ type: Injectable
1276
+ }] });
1277
+
1099
1278
  class WorkCenterProcessStepType {
1279
+ actionContext = inject(WorkCenterItemActionContextStore, {
1280
+ optional: true,
1281
+ });
1100
1282
  details = input.required(...(ngDevMode ? [{ debugName: "details" }] : []));
1101
- activeTab = signal('processForm', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
1283
+ clientForm = viewChild(ClientForm, ...(ngDevMode ? [{ debugName: "clientForm" }] : []));
1284
+ activeTab = signal('form', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
1285
+ currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
1102
1286
  tabOptions = [
1103
1287
  {
1104
- label: 'Process Form',
1105
- value: 'processForm',
1288
+ label: 'Form',
1289
+ value: 'form',
1106
1290
  },
1107
1291
  {
1108
- label: 'Module Preview',
1109
- value: 'modulePreview',
1292
+ label: 'Approvals',
1293
+ value: 'approvals',
1294
+ },
1295
+ {
1296
+ label: 'Steps',
1297
+ value: 'schema',
1298
+ },
1299
+ {
1300
+ label: 'Discussion',
1301
+ value: 'discussion',
1110
1302
  },
1111
1303
  ];
1112
1304
  itemContext = computed(() => readItemContext(this.details()), ...(ngDevMode ? [{ debugName: "itemContext" }] : []));
1113
- moduleKey = computed(() => readString$1(this.itemContext(), 'moduleKey') ?? '', ...(ngDevMode ? [{ debugName: "moduleKey" }] : []));
1114
- operationKey = computed(() => readString$1(this.itemContext(), 'operationKey') ?? '', ...(ngDevMode ? [{ debugName: "operationKey" }] : []));
1305
+ requestId = computed(() => readNumber(this.itemContext(), 'requestId') ??
1306
+ readNumber(this.itemContext(), 'draftProcessId'), ...(ngDevMode ? [{ debugName: "requestId" }] : []));
1307
+ moduleKey = computed(() => readString$2(this.itemContext(), 'moduleKey') ?? '', ...(ngDevMode ? [{ debugName: "moduleKey" }] : []));
1308
+ operationKey = computed(() => readString$2(this.itemContext(), 'operationKey') ?? '', ...(ngDevMode ? [{ debugName: "operationKey" }] : []));
1115
1309
  moduleId = computed(() => readNumber(this.itemContext(), 'moduleId'), ...(ngDevMode ? [{ debugName: "moduleId" }] : []));
1116
1310
  levelId = computed(() => readNumber(this.itemContext(), 'levelId'), ...(ngDevMode ? [{ debugName: "levelId" }] : []));
1117
1311
  levelDataId = computed(() => readNumber(this.itemContext(), 'levelDataId'), ...(ngDevMode ? [{ debugName: "levelDataId" }] : []));
@@ -1119,70 +1313,480 @@ class WorkCenterProcessStepType {
1119
1313
  requestSchemaId = computed(() => readNumber(this.itemContext(), 'requestSchemaId'), ...(ngDevMode ? [{ debugName: "requestSchemaId" }] : []));
1120
1314
  draftProcessId = computed(() => readNumber(this.itemContext(), 'draftProcessId') ??
1121
1315
  readNumber(this.itemContext(), 'requestId'), ...(ngDevMode ? [{ debugName: "draftProcessId" }] : []));
1316
+ discussionRecordId = computed(() => this.requestId() ?? 0, ...(ngDevMode ? [{ debugName: "discussionRecordId" }] : []));
1122
1317
  canRenderForm = computed(() => !!this.moduleKey() && !!this.operationKey(), ...(ngDevMode ? [{ debugName: "canRenderForm" }] : []));
1123
- canRenderPreview = computed(() => !!this.moduleKey() && !!this.operationKey(), ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
1318
+ canRenderDiscussion = computed(() => this.discussionRecordId() > 0, ...(ngDevMode ? [{ debugName: "canRenderDiscussion" }] : []));
1319
+ canRenderPreview = computed(() => (this.requestId() ?? 0) > 0, ...(ngDevMode ? [{ debugName: "canRenderPreview" }] : []));
1320
+ constructor() {
1321
+ effect(() => {
1322
+ this.actionContext?.setClientForm(this.clientForm() ?? null);
1323
+ });
1324
+ }
1325
+ onDiscussionReadStateChanged(state) {
1326
+ const resolvedUserId = state?.userId?.trim();
1327
+ if (resolvedUserId) {
1328
+ this.currentUserId.set(resolvedUserId);
1329
+ }
1330
+ }
1331
+ ngOnDestroy() {
1332
+ this.actionContext?.setClientForm(null);
1333
+ }
1124
1334
  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"] }] });
1335
+ 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() !== 'approvals'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'approvals'\"\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 preview is not available for this process item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'schema'\"\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 preview is not available for this process 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]=\"'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</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", "view"] }] });
1126
1336
  }
1127
1337
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterProcessStepType, decorators: [{
1128
1338
  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 }] }] } });
1339
+ args: [{ selector: 'mt-work-center-process-step-type', standalone: true, imports: [
1340
+ CommonModule,
1341
+ Tabs,
1342
+ ClientForm,
1343
+ DiscussionThread,
1344
+ WorkCenterProcessPreviewJson,
1345
+ ], 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() !== 'approvals'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'approvals'\"\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 preview is not available for this process item yet.\n </p>\n </div>\n }\n </div>\n\n <div class=\"flex-1\" [hidden]=\"activeTab() !== 'schema'\">\n @if (canRenderPreview()) {\n <mt-work-center-process-preview-json\n [requestId]=\"requestId()\"\n [view]=\"'schema'\"\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 preview is not available for this process 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]=\"'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</div>\n" }]
1346
+ }], ctorParameters: () => [], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }], clientForm: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ClientForm), { isSignal: true }] }] } });
1131
1347
 
1132
- class WorkCenterItemDrawer {
1348
+ class WorkCenterItemModal {
1133
1349
  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"] }] });
1350
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
1351
+ 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
1352
  }
1137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemDrawer, decorators: [{
1353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModal, decorators: [{
1138
1354
  type: Component,
1139
- args: [{ selector: 'mt-work-center-item-drawer', standalone: true, imports: [
1355
+ args: [{ selector: 'mt-work-center-item-modal', standalone: true, imports: [
1140
1356
  CommonModule,
1141
1357
  WorkCenterProcessStepType,
1142
1358
  WorkCenterProcessRequestType,
1143
1359
  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" }]
1360
+ ], 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
1361
  }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: true }] }] } });
1146
1362
 
1147
- class WorkCenterItemDrawerRoute {
1363
+ class WorkCenterItemActionConfirmDialog {
1364
+ ref = inject(ModalRef);
1365
+ modal = inject(ModalService);
1366
+ action = input.required(...(ngDevMode ? [{ debugName: "action" }] : []));
1367
+ formControl = new FormControl({});
1368
+ actionLabel = computed(() => this.action().actionName?.display || this.action().actionKey, ...(ngDevMode ? [{ debugName: "actionLabel" }] : []));
1369
+ formConfig = computed(() => ({
1370
+ sections: [
1371
+ {
1372
+ key: 'action-confirmation',
1373
+ type: 'none',
1374
+ fields: buildActionFields(this.action().payloadKeys, this.action().requiredPayloadKeys),
1375
+ },
1376
+ ],
1377
+ }), ...(ngDevMode ? [{ debugName: "formConfig" }] : []));
1378
+ hasFormFields = computed(() => this.formConfig().sections[0]?.fields.length > 0, ...(ngDevMode ? [{ debugName: "hasFormFields" }] : []));
1379
+ onCancel() {
1380
+ this.ref.close(null);
1381
+ }
1382
+ onConfirm() {
1383
+ if (this.formControl.invalid) {
1384
+ this.formControl.markAllAsTouched();
1385
+ return;
1386
+ }
1387
+ this.ref.close(this.formControl.getRawValue() ?? {});
1388
+ }
1389
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionConfirmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
1390
+ 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</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button\n label=\"Cancel\"\n severity=\"secondary\"\n variant=\"outlined\"\n (onClick)=\"onCancel()\"\n />\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"] }] });
1391
+ }
1392
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemActionConfirmDialog, decorators: [{
1393
+ type: Component,
1394
+ 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</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button\n label=\"Cancel\"\n severity=\"secondary\"\n variant=\"outlined\"\n (onClick)=\"onCancel()\"\n />\n <mt-button [label]=\"actionLabel()\" (onClick)=\"onConfirm()\" />\n</div>\n" }]
1395
+ }], propDecorators: { action: [{ type: i0.Input, args: [{ isSignal: true, alias: "action", required: true }] }] } });
1396
+ function buildActionFields(payloadKeys, requiredPayloadKeys) {
1397
+ const requestedKeys = new Set(payloadKeys ?? []);
1398
+ const requiredKeys = new Set(requiredPayloadKeys ?? []);
1399
+ const fields = [];
1400
+ if (requestedKeys.has('delegatedUser')) {
1401
+ fields.push({
1402
+ key: 'delegatedUser',
1403
+ type: 'user-search',
1404
+ label: 'Delegated User',
1405
+ placeholder: 'Search user',
1406
+ apiUrl: 'Identity/users',
1407
+ optionLabel: 'displayName',
1408
+ optionValue: 'id',
1409
+ validators: buildRequiredValidators(requiredKeys.has('delegatedUser')),
1410
+ colSpan: 12,
1411
+ });
1412
+ }
1413
+ if (requestedKeys.has('reason')) {
1414
+ fields.push({
1415
+ key: 'reason',
1416
+ type: 'textarea',
1417
+ label: 'Reason',
1418
+ placeholder: 'Enter reason',
1419
+ rows: 4,
1420
+ validators: buildRequiredValidators(requiredKeys.has('reason')),
1421
+ colSpan: 12,
1422
+ });
1423
+ }
1424
+ if (requestedKeys.has('note')) {
1425
+ fields.push({
1426
+ key: 'note',
1427
+ type: 'textarea',
1428
+ label: 'Note',
1429
+ placeholder: 'Enter note',
1430
+ rows: 4,
1431
+ validators: buildRequiredValidators(requiredKeys.has('note')),
1432
+ colSpan: 12,
1433
+ });
1434
+ }
1435
+ if (requestedKeys.has('attachments')) {
1436
+ fields.push({
1437
+ key: 'attachments',
1438
+ type: 'upload-file',
1439
+ label: 'Attachments',
1440
+ endPoint: 'uploader',
1441
+ multiple: true,
1442
+ title: 'Upload Attachment',
1443
+ description: 'Click or drop a file to upload',
1444
+ validators: buildRequiredValidators(requiredKeys.has('attachments')),
1445
+ colSpan: 12,
1446
+ });
1447
+ }
1448
+ return fields;
1449
+ }
1450
+ function buildRequiredValidators(required) {
1451
+ return required ? [ValidatorConfig.required()] : [];
1452
+ }
1453
+
1454
+ class WorkCenterItemModalFooterActions {
1455
+ http = inject(HttpClient);
1456
+ modal = inject(ModalService);
1457
+ toast = inject(ToastService);
1458
+ actionContext = inject(WorkCenterItemActionContextStore);
1459
+ loadSub;
1460
+ executeSub;
1461
+ lastContextKey = null;
1462
+ contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : []));
1463
+ actionExecuted = output();
1464
+ visibilityChange = output();
1465
+ reloadTick = signal(0, ...(ngDevMode ? [{ debugName: "reloadTick" }] : []));
1466
+ hasResolvedLoad = signal(false, ...(ngDevMode ? [{ debugName: "hasResolvedLoad" }] : []));
1467
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1468
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1469
+ actions = signal([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
1470
+ pendingActionKey = signal(null, ...(ngDevMode ? [{ debugName: "pendingActionKey" }] : []));
1471
+ displayActions = computed(() => this.actions()
1472
+ .filter((action) => action.isAvailable !== false &&
1473
+ !!action.url &&
1474
+ !!normalizeMethod(action.httpMethod))
1475
+ .map((action, index) => ({
1476
+ ...action,
1477
+ label: action.actionName?.display || action.actionKey,
1478
+ severity: resolveActionSeverity(action.actionKey, index),
1479
+ variant: resolveActionVariant(action.actionKey, index),
1480
+ })), ...(ngDevMode ? [{ debugName: "displayActions" }] : []));
1481
+ shouldRender = computed(() => !!this.contextKey() &&
1482
+ (!this.hasResolvedLoad() ||
1483
+ this.loading() ||
1484
+ !!this.error() ||
1485
+ this.displayActions().length > 0 ||
1486
+ !!this.pendingActionKey()), ...(ngDevMode ? [{ debugName: "shouldRender" }] : []));
1487
+ constructor() {
1488
+ effect(() => {
1489
+ const contextKey = this.contextKey();
1490
+ this.reloadTick();
1491
+ this.error.set(null);
1492
+ if (!contextKey) {
1493
+ this.lastContextKey = null;
1494
+ this.actions.set([]);
1495
+ this.loading.set(false);
1496
+ this.hasResolvedLoad.set(false);
1497
+ return;
1498
+ }
1499
+ if (contextKey !== this.lastContextKey) {
1500
+ this.actions.set([]);
1501
+ this.lastContextKey = contextKey;
1502
+ }
1503
+ untracked(() => this.loadActions(contextKey));
1504
+ });
1505
+ effect(() => {
1506
+ this.visibilityChange.emit(this.shouldRender());
1507
+ });
1508
+ }
1509
+ ngOnDestroy() {
1510
+ this.loadSub?.unsubscribe();
1511
+ this.executeSub?.unsubscribe();
1512
+ }
1513
+ executeAction(action) {
1514
+ const contextKey = this.contextKey();
1515
+ const method = normalizeMethod(action.httpMethod);
1516
+ const url = action.url?.trim();
1517
+ if (!contextKey ||
1518
+ !method ||
1519
+ !url ||
1520
+ action.isAvailable === false ||
1521
+ !!this.pendingActionKey()) {
1522
+ return;
1523
+ }
1524
+ if (action.needConfirmation) {
1525
+ this.openConfirmationDialog(action);
1526
+ return;
1527
+ }
1528
+ const payload = this.buildActionPayload(action);
1529
+ if (!this.ensurePayloadIsReady(action, payload)) {
1530
+ return;
1531
+ }
1532
+ this.runActionRequest(action, method, url, payload);
1533
+ }
1534
+ openConfirmationDialog(action) {
1535
+ const ref = this.modal.openModal(WorkCenterItemActionConfirmDialog, 'dialog', {
1536
+ header: action.label,
1537
+ width: '40rem',
1538
+ dismissableMask: true,
1539
+ inputValues: {
1540
+ action,
1541
+ },
1542
+ });
1543
+ ref.onClose
1544
+ .pipe(take(1))
1545
+ .subscribe((formValue) => {
1546
+ if (formValue == null) {
1547
+ return;
1548
+ }
1549
+ const method = normalizeMethod(action.httpMethod);
1550
+ const url = action.url?.trim();
1551
+ if (!method || !url) {
1552
+ return;
1553
+ }
1554
+ const payload = this.buildActionPayload(action, formValue);
1555
+ if (!this.ensurePayloadIsReady(action, payload)) {
1556
+ return;
1557
+ }
1558
+ this.runActionRequest(action, method, url, payload);
1559
+ });
1560
+ }
1561
+ runActionRequest(action, method, url, payload) {
1562
+ this.error.set(null);
1563
+ this.pendingActionKey.set(action.actionKey);
1564
+ this.executeSub?.unsubscribe();
1565
+ this.executeSub = this.http
1566
+ .request(method, url, buildRequestOptions(method, payload))
1567
+ .pipe(map((response) => resolveActionSuccessMessage(response, `${action.label} completed successfully.`)))
1568
+ .subscribe({
1569
+ next: (message) => {
1570
+ this.pendingActionKey.set(null);
1571
+ this.toast.success(message);
1572
+ this.reloadTick.update((value) => value + 1);
1573
+ this.actionExecuted.emit();
1574
+ },
1575
+ error: (error) => {
1576
+ const message = resolveHttpErrorMessage(error, `Failed to execute ${action.label}.`);
1577
+ this.pendingActionKey.set(null);
1578
+ this.error.set(message);
1579
+ this.toast.error(message);
1580
+ },
1581
+ });
1582
+ }
1583
+ buildActionPayload(action, formValue) {
1584
+ const payloadKeys = action.payloadKeys ?? [];
1585
+ if (!payloadKeys.length) {
1586
+ return undefined;
1587
+ }
1588
+ const payload = {};
1589
+ for (const key of payloadKeys) {
1590
+ const formFieldValue = formValue?.[key];
1591
+ if (formFieldValue !== undefined) {
1592
+ payload[key] = normalizePayloadValue(key, formFieldValue);
1593
+ continue;
1594
+ }
1595
+ const externalValue = this.resolveExternalPayloadValue(key, action);
1596
+ if (externalValue !== undefined) {
1597
+ payload[key] = externalValue;
1598
+ continue;
1599
+ }
1600
+ const defaultValue = resolveDefaultPayloadValue(key);
1601
+ if (defaultValue !== undefined) {
1602
+ payload[key] = defaultValue;
1603
+ }
1604
+ }
1605
+ return Object.keys(payload).length ? payload : undefined;
1606
+ }
1607
+ ensurePayloadIsReady(action, payload) {
1608
+ const missingRequiredKeys = (action.requiredPayloadKeys ?? []).filter((key) => isMissingPayloadValue(payload?.[key]));
1609
+ if (!missingRequiredKeys.length) {
1610
+ return true;
1611
+ }
1612
+ const message = `Cannot execute ${action.label}. Missing: ${missingRequiredKeys.join(', ')}.`;
1613
+ this.error.set(message);
1614
+ this.toast.error(message);
1615
+ return false;
1616
+ }
1617
+ resolveExternalPayloadValue(key, action) {
1618
+ switch (key) {
1619
+ case 'stepId':
1620
+ return action.stepIds?.[0];
1621
+ case 'values':
1622
+ return this.actionContext.resolveFormValues();
1623
+ default:
1624
+ return undefined;
1625
+ }
1626
+ }
1627
+ loadActions(contextKey) {
1628
+ this.loadSub?.unsubscribe();
1629
+ this.loading.set(true);
1630
+ this.hasResolvedLoad.set(false);
1631
+ this.loadSub = this.http
1632
+ .get('workcenter/runtime/item-actions', {
1633
+ params: { contextKey },
1634
+ })
1635
+ .pipe(map((response) => {
1636
+ if (response.code === 1) {
1637
+ return response.data.actions ?? [];
1638
+ }
1639
+ throw new Error(resolveEnvelopeErrorMessage(response, 'Failed to load item actions.'));
1640
+ }))
1641
+ .subscribe({
1642
+ next: (actions) => {
1643
+ this.actions.set(actions);
1644
+ this.loading.set(false);
1645
+ this.hasResolvedLoad.set(true);
1646
+ },
1647
+ error: (error) => {
1648
+ this.actions.set([]);
1649
+ this.loading.set(false);
1650
+ this.hasResolvedLoad.set(true);
1651
+ this.error.set(resolveHttpErrorMessage(error, 'Failed to load item actions.'));
1652
+ },
1653
+ });
1654
+ }
1655
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalFooterActions, deps: [], target: i0.ɵɵFactoryTarget.Component });
1656
+ 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"] }] });
1657
+ }
1658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalFooterActions, decorators: [{
1659
+ type: Component,
1660
+ args: [{ selector: 'mt-work-center-item-modal-footer-actions', standalone: true, imports: [CommonModule, Button], host: {
1661
+ class: 'flex w-full flex-1 flex-wrap items-center justify-end gap-2',
1662
+ }, 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" }]
1663
+ }], 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"] }] } });
1664
+ function buildRequestOptions(method, payload) {
1665
+ if (!payload || !methodSupportsBody(method)) {
1666
+ return { observe: 'body' };
1667
+ }
1668
+ return {
1669
+ body: payload,
1670
+ observe: 'body',
1671
+ };
1672
+ }
1673
+ function methodSupportsBody(method) {
1674
+ return ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method);
1675
+ }
1676
+ function normalizeMethod(value) {
1677
+ if (!value || typeof value !== 'string') {
1678
+ return null;
1679
+ }
1680
+ const method = value.trim().toUpperCase();
1681
+ return method.length ? method : null;
1682
+ }
1683
+ function normalizePayloadValue(key, value) {
1684
+ if (key === 'attachments') {
1685
+ if (value == null) {
1686
+ return [];
1687
+ }
1688
+ return Array.isArray(value) ? value : [value];
1689
+ }
1690
+ return value;
1691
+ }
1692
+ function resolveDefaultPayloadValue(key) {
1693
+ switch (key) {
1694
+ case 'attachments':
1695
+ return [];
1696
+ case 'delegatedUser':
1697
+ case 'note':
1698
+ case 'reason':
1699
+ return null;
1700
+ case 'values':
1701
+ return [];
1702
+ default:
1703
+ return undefined;
1704
+ }
1705
+ }
1706
+ function isMissingPayloadValue(value) {
1707
+ if (value == null) {
1708
+ return true;
1709
+ }
1710
+ if (typeof value === 'string') {
1711
+ return value.trim().length === 0;
1712
+ }
1713
+ if (Array.isArray(value)) {
1714
+ return value.length === 0;
1715
+ }
1716
+ return false;
1717
+ }
1718
+ function resolveActionSeverity(actionKey, index) {
1719
+ const normalized = actionKey.trim().toLowerCase();
1720
+ if (normalized === 'close' ||
1721
+ normalized === 'delete' ||
1722
+ normalized === 'reject' ||
1723
+ normalized === 'cancel') {
1724
+ return 'danger';
1725
+ }
1726
+ return index === 0 ? 'primary' : 'secondary';
1727
+ }
1728
+ function resolveActionVariant(actionKey, index) {
1729
+ const severity = resolveActionSeverity(actionKey, index);
1730
+ return severity === 'primary' ? undefined : 'outlined';
1731
+ }
1732
+ function resolveEnvelopeErrorMessage(response, fallback) {
1733
+ return (response?.errors?.message ??
1734
+ response?.message ??
1735
+ fallback);
1736
+ }
1737
+ function resolveActionSuccessMessage(response, fallback) {
1738
+ if (!response || typeof response !== 'object') {
1739
+ return fallback;
1740
+ }
1741
+ const apiResponse = response;
1742
+ if (typeof apiResponse.code === 'number' && apiResponse.code !== 1) {
1743
+ throw new Error(resolveEnvelopeErrorMessage(apiResponse, fallback));
1744
+ }
1745
+ return apiResponse.message?.trim() || fallback;
1746
+ }
1747
+ function resolveHttpErrorMessage(error, fallback) {
1748
+ if (!error || typeof error !== 'object') {
1749
+ return fallback;
1750
+ }
1751
+ const httpError = error;
1752
+ return httpError.error?.message ?? httpError.message ?? fallback;
1753
+ }
1754
+
1755
+ class WorkCenterItemModalRoute {
1148
1756
  http = inject(HttpClient);
1149
1757
  router = inject(Router);
1150
1758
  route = inject(ActivatedRoute);
1759
+ modal = inject(ModalService);
1151
1760
  contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : []));
1152
1761
  drawerVisible = signal(true, ...(ngDevMode ? [{ debugName: "drawerVisible" }] : []));
1153
1762
  loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1154
1763
  error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1155
1764
  details = signal(null, ...(ngDevMode ? [{ debugName: "details" }] : []));
1765
+ detailsReloadTick = signal(0, ...(ngDevMode ? [{ debugName: "detailsReloadTick" }] : []));
1766
+ footerActionsMounted = signal(false, ...(ngDevMode ? [{ debugName: "footerActionsMounted" }] : []));
1156
1767
  resolvedContextKey = computed(() => this.decodeContextKey(this.contextKey()), ...(ngDevMode ? [{ debugName: "resolvedContextKey" }] : []));
1157
1768
  drawerTitle = computed(() => this.readDisplayField(this.details()?.item, 'title') ?? 'Item Details', ...(ngDevMode ? [{ debugName: "drawerTitle" }] : []));
1158
1769
  drawerSubtitle = computed(() => this.readDisplayField(this.details()?.item, 'subtitle') ?? '', ...(ngDevMode ? [{ debugName: "drawerSubtitle" }] : []));
1159
1770
  constructor() {
1160
1771
  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
- });
1772
+ this.footerActionsMounted.set(!!this.resolvedContextKey());
1171
1773
  });
1172
1774
  effect((onCleanup) => {
1173
1775
  const contextKey = this.resolvedContextKey();
1174
- console.log('[work-center-debug] drawer route load effect', {
1776
+ const reloadTick = this.detailsReloadTick();
1777
+ console.log('[work-center-debug] modal route load effect', {
1175
1778
  contextKey,
1779
+ reloadTick,
1176
1780
  });
1177
1781
  this.error.set(null);
1178
1782
  this.details.set(null);
1179
1783
  if (!contextKey) {
1180
1784
  this.loading.set(false);
1181
- console.log('[work-center-debug] drawer route load skipped, no context key');
1785
+ console.log('[work-center-debug] modal route load skipped, no context key');
1182
1786
  return;
1183
1787
  }
1184
1788
  this.loading.set(true);
1185
- console.log('[work-center-debug] drawer route fetch start', {
1789
+ console.log('[work-center-debug] modal route fetch start', {
1186
1790
  endpoint: 'workcenter/runtime/item-basic-info',
1187
1791
  contextKey,
1188
1792
  });
@@ -1198,7 +1802,7 @@ class WorkCenterItemDrawerRoute {
1198
1802
  }))
1199
1803
  .subscribe({
1200
1804
  next: (details) => {
1201
- console.log('[work-center-debug] drawer route fetch success', {
1805
+ console.log('[work-center-debug] modal route fetch success', {
1202
1806
  contextKey,
1203
1807
  details,
1204
1808
  });
@@ -1206,7 +1810,7 @@ class WorkCenterItemDrawerRoute {
1206
1810
  this.loading.set(false);
1207
1811
  },
1208
1812
  error: (error) => {
1209
- console.error('[work-center-debug] drawer route fetch failed', {
1813
+ console.error('[work-center-debug] modal route fetch failed', {
1210
1814
  contextKey,
1211
1815
  error,
1212
1816
  });
@@ -1219,16 +1823,22 @@ class WorkCenterItemDrawerRoute {
1219
1823
  onCleanup(() => subscription.unsubscribe());
1220
1824
  });
1221
1825
  }
1826
+ onActionExecuted() {
1827
+ this.detailsReloadTick.update((value) => value + 1);
1828
+ }
1829
+ onFooterVisibilityChange(visible) {
1830
+ this.footerActionsMounted.set(visible);
1831
+ }
1222
1832
  async onVisibleChange(visible) {
1223
1833
  this.drawerVisible.set(visible);
1224
- console.log('[work-center-debug] drawer visible change', { visible });
1834
+ console.log('[work-center-debug] modal route visible change', { visible });
1225
1835
  if (visible) {
1226
1836
  return;
1227
1837
  }
1228
- await this.closeDrawer();
1838
+ await this.closeRouteOutlet();
1229
1839
  }
1230
- closeDrawer() {
1231
- console.log('[work-center-debug] drawer closing', {
1840
+ closeRouteOutlet() {
1841
+ console.log('[work-center-debug] modal route closing', {
1232
1842
  outlet: this.route.outlet || 'sidebar',
1233
1843
  parentUrl: this.route.parent?.snapshot.url.map((segment) => segment.path),
1234
1844
  });
@@ -1239,7 +1849,7 @@ class WorkCenterItemDrawerRoute {
1239
1849
  replaceUrl: true,
1240
1850
  })
1241
1851
  .then((success) => {
1242
- console.log('[work-center-debug] drawer close navigate result', {
1852
+ console.log('[work-center-debug] modal route close navigate result', {
1243
1853
  success,
1244
1854
  currentUrl: this.router.url,
1245
1855
  });
@@ -1276,12 +1886,18 @@ class WorkCenterItemDrawerRoute {
1276
1886
  ? display
1277
1887
  : null;
1278
1888
  }
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"] }] });
1889
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalRoute, deps: [], target: i0.ɵɵFactoryTarget.Component });
1890
+ 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
1891
  }
1282
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemDrawerRoute, decorators: [{
1892
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkCenterItemModalRoute, decorators: [{
1283
1893
  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" }]
1894
+ args: [{ selector: 'mt-work-center-item-modal-route', standalone: true, imports: [
1895
+ CommonModule,
1896
+ Drawer,
1897
+ SkeletonModule,
1898
+ WorkCenterItemModal,
1899
+ WorkCenterItemModalFooterActions,
1900
+ ], 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
1901
  }], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }] } });
1286
1902
 
1287
1903
  const APP_STATES = [WorkCenterState];
@@ -1290,5 +1906,5 @@ const APP_STATES = [WorkCenterState];
1290
1906
  * Generated bundle index. Do not edit.
1291
1907
  */
1292
1908
 
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 };
1909
+ 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
1910
  //# sourceMappingURL=masterteam-work-center.mjs.map