@masterteam/work-center 0.0.61 → 0.0.63

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.
@@ -168,6 +168,22 @@ class ApplyColumnFilters {
168
168
  this.filters = filters;
169
169
  }
170
170
  }
171
+ /**
172
+ * Sets the grouped column. Grouping is expressed to the backend as a single
173
+ * sort on the same field, so this also rewrites `context.sort` and resets
174
+ * `page` to 1 before reloading. `groupBy: null` clears both.
175
+ */
176
+ class SetGroupBy {
177
+ area;
178
+ groupBy;
179
+ dir;
180
+ static type = '[WorkCenter] Set Group By';
181
+ constructor(area, groupBy, dir = 'asc') {
182
+ this.area = area;
183
+ this.groupBy = groupBy;
184
+ this.dir = dir;
185
+ }
186
+ }
171
187
  /**
172
188
  * Clears both the header filter slice and the column filter slice in one
173
189
  * state update, triggering a single BE reload.
@@ -188,6 +204,29 @@ const WORK_CENTER_QUERY_VERSION = 1;
188
204
  const WORK_CENTER_MAX_PAGE_SIZE = 100;
189
205
  const WORK_CENTER_MAX_FILTERS = 20;
190
206
  const WORK_CENTER_MAX_SORT = 5;
207
+ /**
208
+ * Backend column key carrying the row's LevelData display label
209
+ * (`extra.levelDataName`). Grouping by it maps to a single backend sort on the
210
+ * same key — see `WORK_CENTER_LEVEL_GROUP_FIELD` for the grouping identity.
211
+ */
212
+ const WORK_CENTER_LEVEL_NAME_KEY = 'levelDataName';
213
+ /**
214
+ * Synthetic per-row field holding the *identity* behind the Level Name column.
215
+ * The visible label is ambiguous (two LevelData records may share a name), so
216
+ * rows are bucketed by `context.levelDataId` instead — except rows with no
217
+ * visible label, which get an empty identity so they all collapse into the one
218
+ * shared "—" group the backend contract requires.
219
+ */
220
+ const WORK_CENTER_LEVEL_GROUP_FIELD = '__mtLevelGroup';
221
+ /** Rendered in place of a missing / restricted LevelData label. */
222
+ const WORK_CENTER_EMPTY_LABEL = '—';
223
+ /**
224
+ * Bootstrap `group` value meaning "the user turned grouping off". Needed
225
+ * because an absent `group` means "not chosen yet" and falls back to the
226
+ * default grouping — without a distinct value, clearing the group would be
227
+ * undone by the next navigation.
228
+ */
229
+ const WORK_CENTER_GROUP_NONE = 'none';
191
230
 
192
231
  const AREA_COLORS = ['violet', 'blue', 'emerald', 'amber', 'teal'];
193
232
  /** Fallback accent rotation used only when the backend sends no stat color. */
@@ -273,6 +312,25 @@ function parseSortInput(value) {
273
312
  ? sanitizeSort(parsed)
274
313
  : [];
275
314
  }
315
+ /**
316
+ * Resolves the grouped column key from bootstrap inputs.
317
+ *
318
+ * A missing `group` means "not chosen yet" and keeps whatever state already
319
+ * has — which starts at the area default, so a first visit lands grouped.
320
+ * `WORK_CENTER_GROUP_NONE` is the only way to express "the user turned it
321
+ * off"; a bare `null` can't, because it is also what a host passes for an
322
+ * absent query param.
323
+ */
324
+ function resolveGroupByFromInputs(current, group) {
325
+ if (!hasParamValue(group) || typeof group !== 'string') {
326
+ return current;
327
+ }
328
+ const parsed = group.trim();
329
+ if (!parsed || parsed === WORK_CENTER_GROUP_NONE) {
330
+ return null;
331
+ }
332
+ return parsed;
333
+ }
276
334
  function parseFiltersInput(value) {
277
335
  const parsed = parseJson(value);
278
336
  return Array.isArray(parsed)
@@ -392,8 +450,27 @@ function buildColumnsFromProperties(properties) {
392
450
  toLabel$1(property.key),
393
451
  type: 'entity',
394
452
  viewType: toViewType(property.viewType, property.key),
453
+ ...withLevelNameGrouping(property.key),
395
454
  }));
396
455
  }
456
+ /**
457
+ * Level Name is a free-text column, so the table's cardinality heuristic would
458
+ * never offer it in the group picker. The backend orders the whole result set
459
+ * by that label before paging, which makes its groups contiguous and therefore
460
+ * groupable — so opt it in explicitly and point the table at the identity
461
+ * field instead of the ambiguous label.
462
+ */
463
+ function withLevelNameGrouping(key) {
464
+ return key === WORK_CENTER_LEVEL_NAME_KEY
465
+ ? {
466
+ groupable: true,
467
+ groupKey: WORK_CENTER_LEVEL_GROUP_FIELD,
468
+ // A level name names itself — "Level Name · Project Gamma" would just
469
+ // repeat the column header down every group.
470
+ showGroupColumnLabel: false,
471
+ }
472
+ : {};
473
+ }
397
474
  function buildColumns(columnsConfig) {
398
475
  const propertyColumns = buildColumnsFromProperties(columnsConfig?.properties ?? []);
399
476
  if (propertyColumns.length) {
@@ -405,9 +482,11 @@ function buildColumns(columnsConfig) {
405
482
  label: toLabel$1(key),
406
483
  type: 'entity',
407
484
  viewType: toViewType(undefined, key),
485
+ ...withLevelNameGrouping(key),
408
486
  })));
409
487
  }
410
488
  function toDisplayRows(rows, columns) {
489
+ const hasLevelName = columns.some((column) => column.key === WORK_CENTER_LEVEL_NAME_KEY);
411
490
  return rows.map((row) => {
412
491
  const sourceRow = flattenRuntimeRow(row);
413
492
  const displayRow = { ...sourceRow };
@@ -418,9 +497,38 @@ function toDisplayRows(rows, columns) {
418
497
  value: toDisplayValue(value, column),
419
498
  };
420
499
  }
500
+ if (hasLevelName) {
501
+ applyLevelNameGrouping(displayRow, sourceRow);
502
+ }
421
503
  return displayRow;
422
504
  });
423
505
  }
506
+ /**
507
+ * Adds the Level Name grouping identity to a display row and normalizes a
508
+ * missing / restricted label to `—`.
509
+ *
510
+ * The backend omits `extra.levelDataName` when the record is missing, deleted,
511
+ * or the user can't see it — those rows must share one group and must never
512
+ * expose the numeric id as a label. Rows that do have a label are keyed by
513
+ * `context.levelDataId` so two records with the same name stay separate.
514
+ */
515
+ function applyLevelNameGrouping(displayRow, sourceRow) {
516
+ const cell = displayRow[WORK_CENTER_LEVEL_NAME_KEY];
517
+ const label = typeof cell?.value === 'string' ? cell.value.trim() : '';
518
+ if (!label) {
519
+ displayRow[WORK_CENTER_LEVEL_NAME_KEY] = {
520
+ ...cell,
521
+ value: WORK_CENTER_EMPTY_LABEL,
522
+ };
523
+ displayRow[WORK_CENTER_LEVEL_GROUP_FIELD] = '';
524
+ return;
525
+ }
526
+ const levelDataId = getValue(sourceRow, 'context.levelDataId');
527
+ const hasId = levelDataId !== null && levelDataId !== undefined && levelDataId !== '';
528
+ displayRow[WORK_CENTER_LEVEL_GROUP_FIELD] = hasId
529
+ ? `id:${String(levelDataId)}`
530
+ : `name:${label}`;
531
+ }
424
532
  function buildMenuItems(cards) {
425
533
  const mapped = cards.map((card, index) => ({
426
534
  key: card.key,
@@ -456,6 +564,19 @@ function buildKpis(stats, fallbackIcon) {
456
564
  color: stat.color?.trim() || KPI_COLORS[index % KPI_COLORS.length],
457
565
  }));
458
566
  }
567
+ /**
568
+ * Level Name grouping is the default view of the personal work areas — those
569
+ * rows come from all over the hierarchy, so "which project is this?" is the
570
+ * first question a user has. Workspace is already scoped to one record, so
571
+ * grouping it by that record would produce a single group.
572
+ */
573
+ function defaultGroupBy(area) {
574
+ return area === 'Workspace' ? null : WORK_CENTER_LEVEL_NAME_KEY;
575
+ }
576
+ /** The backend sort that renders a grouped column as contiguous rows. */
577
+ function sortForGroup(groupBy) {
578
+ return groupBy ? [{ field: groupBy, dir: 'asc' }] : [];
579
+ }
459
580
  function createDefaultContext(area) {
460
581
  return {
461
582
  area,
@@ -464,7 +585,7 @@ function createDefaultContext(area) {
464
585
  selectedCardKey: null,
465
586
  page: 1,
466
587
  pageSize: WORK_CENTER_LOCAL_FETCH_SIZE,
467
- sort: [],
588
+ sort: sortForGroup(defaultGroupBy(area)),
468
589
  runtimeFilters: [],
469
590
  includeStats: true,
470
591
  };
@@ -474,6 +595,7 @@ function createDefaultAreaState(area) {
474
595
  context: createDefaultContext(area),
475
596
  headerFilters: [],
476
597
  columnFilters: [],
598
+ groupBy: defaultGroupBy(area),
477
599
  menuItems: [],
478
600
  rows: [],
479
601
  columns: [],
@@ -523,7 +645,14 @@ function normalizeContext(context) {
523
645
  runtimeFilters: sanitizeFilters(context.runtimeFilters),
524
646
  };
525
647
  }
526
- function buildContextFromInputs(currentContext, area, inputs = {}) {
648
+ function buildContextFromInputs(currentContext, area, inputs = {},
649
+ /**
650
+ * Already-resolved grouped column. Grouping is executed as a backend sort,
651
+ * so when the host supplies no explicit `sort` the grouped column defines
652
+ * it — that is what makes the default grouping reach the very first request
653
+ * instead of costing a second round trip.
654
+ */
655
+ groupBy = null) {
527
656
  const parsedCardKey = toSelectedCardKey(inputs.card);
528
657
  const parsedTemplateId = toOptionalInt(inputs.templateId);
529
658
  const parsedLevelDataId = toOptionalInt(inputs.levelDataId);
@@ -540,9 +669,11 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
540
669
  levelDataId: parsedLevelDataId ?? currentContext.levelDataId,
541
670
  sort: hasParamValue(inputs.sort)
542
671
  ? parseSortInput(inputs.sort)
543
- : inputs.sort === null
544
- ? []
545
- : currentContext.sort,
672
+ : groupBy
673
+ ? sortForGroup(groupBy)
674
+ : inputs.sort === null
675
+ ? []
676
+ : currentContext.sort,
546
677
  runtimeFilters: hasParamValue(inputs.filters)
547
678
  ? parseFiltersInput(inputs.filters)
548
679
  : inputs.filters === null
@@ -576,8 +707,20 @@ function mapRuntimeResponse(current, response) {
576
707
  const columns = buildColumns(selectedCard?.columnsConfig ?? selectedCardFromList?.columnsConfig);
577
708
  const rows = toDisplayRows(selectedCard?.items ?? [], columns);
578
709
  const kpis = buildKpis(selectedCard?.stats ?? [], selectedMenuItem?.icon ?? null);
710
+ // A card that doesn't advertise the grouped column can't be grouped by it —
711
+ // drop it here rather than letting the table discover the stale column and
712
+ // bounce a second request. The sort goes with it when it was the one the
713
+ // grouping asked for.
714
+ const groupBy = current.groupBy && columns.some((column) => column.key === current.groupBy)
715
+ ? current.groupBy
716
+ : null;
717
+ const droppedGroup = !groupBy && current.groupBy;
718
+ const sort = droppedGroup && isSortForGroup(current.context.sort, current.groupBy)
719
+ ? []
720
+ : current.context.sort;
579
721
  return {
580
722
  ...current,
723
+ groupBy,
581
724
  menuItems,
582
725
  rows,
583
726
  columns,
@@ -591,11 +734,16 @@ function mapRuntimeResponse(current, response) {
591
734
  context: {
592
735
  ...current.context,
593
736
  selectedCardKey,
737
+ sort,
594
738
  page: selectedCard?.pagination.page ?? current.context.page,
595
739
  pageSize: selectedCard?.pagination.pageSize ?? current.context.pageSize,
596
740
  },
597
741
  };
598
742
  }
743
+ /** True when `sort` is exactly the single rule a grouping would produce. */
744
+ function isSortForGroup(sort, groupBy) {
745
+ return !!groupBy && sort.length === 1 && sort[0].field === groupBy;
746
+ }
599
747
 
600
748
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
601
749
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -638,6 +786,9 @@ let WorkCenterState = class WorkCenterState {
638
786
  static columnFilters(snapshot) {
639
787
  return snapshot.columnFilters;
640
788
  }
789
+ static groupBy(snapshot) {
790
+ return snapshot.groupBy;
791
+ }
641
792
  static totalCount(snapshot) {
642
793
  return snapshot.totalCount;
643
794
  }
@@ -693,12 +844,16 @@ let WorkCenterState = class WorkCenterState {
693
844
  setParams(ctx, action) {
694
845
  const state = ctx.getState();
695
846
  const current = state.byArea[action.area];
696
- const nextContext = buildContextFromInputs(current.context, action.area, action.inputs);
847
+ // Resolve grouping first: with no explicit `sort` input it is what defines
848
+ // the backend sort, so the default grouping reaches the first request.
849
+ const nextGroupBy = resolveGroupByFromInputs(current.groupBy, action.inputs?.group);
850
+ const nextContext = buildContextFromInputs(current.context, action.area, action.inputs, nextGroupBy);
697
851
  const areaChanged = state.activeArea !== action.area;
698
852
  const contextChanged = !isSameContext(current.context, nextContext);
853
+ const groupChanged = nextGroupBy !== current.groupBy;
699
854
  const runtimeLoading = state.loadingActive.includes(WorkCenterActionKey.LoadRuntime);
700
855
  const shouldLoad = areaChanged || contextChanged || !runtimeLoading;
701
- if (areaChanged || contextChanged) {
856
+ if (areaChanged || contextChanged || groupChanged) {
702
857
  // URL-derived filters land on the header slice. Anything previously
703
858
  // applied via the in-table column filters is dropped so the BE payload
704
859
  // matches what the user sees on the page header.
@@ -715,6 +870,7 @@ let WorkCenterState = class WorkCenterState {
715
870
  ...current,
716
871
  headerFilters: nextHeaderFilters,
717
872
  columnFilters: nextColumnFilters,
873
+ groupBy: nextGroupBy,
718
874
  context: nextContext,
719
875
  },
720
876
  },
@@ -742,6 +898,41 @@ let WorkCenterState = class WorkCenterState {
742
898
  columnFilters: action.filters,
743
899
  });
744
900
  }
901
+ /**
902
+ * Grouping is a backend concern: the table only renders contiguous rows, so
903
+ * the grouped column is pushed down as the single `context.sort` entry and
904
+ * pagination restarts at page 1. Clearing the group sends `sort: []`.
905
+ */
906
+ setGroupBy(ctx, action) {
907
+ const state = ctx.getState();
908
+ const current = state.byArea[action.area];
909
+ const nextGroupBy = action.groupBy?.trim() ? action.groupBy : null;
910
+ const nextSort = nextGroupBy
911
+ ? [{ field: nextGroupBy, dir: action.dir }]
912
+ : [];
913
+ const sameGroup = current.groupBy === nextGroupBy;
914
+ const sameSort = JSON.stringify(current.context.sort) === JSON.stringify(nextSort);
915
+ if (sameGroup && sameSort)
916
+ return;
917
+ ctx.patchState({
918
+ activeArea: action.area,
919
+ byArea: {
920
+ ...state.byArea,
921
+ [action.area]: {
922
+ ...current,
923
+ groupBy: nextGroupBy,
924
+ context: sameSort
925
+ ? current.context
926
+ : { ...current.context, sort: nextSort, page: 1 },
927
+ },
928
+ },
929
+ });
930
+ // A group change that doesn't move the backend order (already sorted by
931
+ // that field) is a pure render concern — no refetch.
932
+ if (sameSort)
933
+ return;
934
+ return ctx.dispatch(new LoadRuntime(action.area, 'group-change'));
935
+ }
745
936
  clearAllFilters(ctx, action) {
746
937
  return this.applyFilterSlice(ctx, action.area, {
747
938
  headerFilters: [],
@@ -845,6 +1036,9 @@ __decorate([
845
1036
  __decorate([
846
1037
  Action(ApplyColumnFilters)
847
1038
  ], WorkCenterState.prototype, "applyColumnFilters", null);
1039
+ __decorate([
1040
+ Action(SetGroupBy)
1041
+ ], WorkCenterState.prototype, "setGroupBy", null);
848
1042
  __decorate([
849
1043
  Action(ClearAllFilters)
850
1044
  ], WorkCenterState.prototype, "clearAllFilters", null);
@@ -884,6 +1078,9 @@ __decorate([
884
1078
  __decorate([
885
1079
  Selector([WorkCenterState.activeSnapshot])
886
1080
  ], WorkCenterState, "columnFilters", null);
1081
+ __decorate([
1082
+ Selector([WorkCenterState.activeSnapshot])
1083
+ ], WorkCenterState, "groupBy", null);
887
1084
  __decorate([
888
1085
  Selector([WorkCenterState.activeSnapshot])
889
1086
  ], WorkCenterState, "totalCount", null);
@@ -907,7 +1104,7 @@ WorkCenterState = __decorate([
907
1104
  ], WorkCenterState);
908
1105
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterState, decorators: [{
909
1106
  type: Injectable
910
- }], propDecorators: { enterArea: [], hydrateFromContext: [], setParams: [], setLookups: [], applyHeaderFilters: [], applyColumnFilters: [], clearAllFilters: [], loadRuntime: [] } });
1107
+ }], propDecorators: { enterArea: [], hydrateFromContext: [], setParams: [], setLookups: [], applyHeaderFilters: [], applyColumnFilters: [], setGroupBy: [], clearAllFilters: [], loadRuntime: [] } });
911
1108
 
912
1109
  class WorkCenterFacade {
913
1110
  store = inject(Store);
@@ -921,12 +1118,24 @@ class WorkCenterFacade {
921
1118
  runtimeFilterSchema = select(WorkCenterState.runtimeFilterSchema);
922
1119
  headerFilters = select(WorkCenterState.headerFilters);
923
1120
  columnFilters = select(WorkCenterState.columnFilters);
1121
+ groupBy = select(WorkCenterState.groupBy);
924
1122
  totalCount = select(WorkCenterState.totalCount);
925
1123
  warnings = select(WorkCenterState.warnings);
926
1124
  loadingActive = select(WorkCenterState.getLoadingActive);
927
1125
  errors = select(WorkCenterState.getErrors);
928
1126
  loading = computed(() => this.loadingActive().includes(WorkCenterActionKey.LoadRuntime), ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
929
1127
  error = computed(() => this.errors()[WorkCenterActionKey.LoadRuntime] ?? null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
1128
+ /**
1129
+ * Snapshot reads for callers that must observe state *immediately* after a
1130
+ * dispatch — e.g. an output handler mirroring the runtime query into the URL.
1131
+ * The `select()` signals above are the right choice everywhere else.
1132
+ */
1133
+ snapshotContext() {
1134
+ return this.store.selectSnapshot(WorkCenterState.context);
1135
+ }
1136
+ snapshotGroupBy() {
1137
+ return this.store.selectSnapshot(WorkCenterState.groupBy);
1138
+ }
930
1139
  enterArea(area) {
931
1140
  return this.store.dispatch(new EnterArea(area));
932
1141
  }
@@ -995,6 +1204,15 @@ class WorkCenterFacade {
995
1204
  applyColumnFiltersAndLoad(area, runtimeFilters) {
996
1205
  return this.store.dispatch(new ApplyColumnFilters(area, runtimeFilters));
997
1206
  }
1207
+ /**
1208
+ * Groups the table by `groupBy` (or clears grouping with `null`). Pushes the
1209
+ * grouped column down as the single backend sort, resets to page 1 and
1210
+ * reloads. Safe to call from the table's `groupByChange` — the lazy event
1211
+ * that follows carries the same sort and is absorbed as a no-op.
1212
+ */
1213
+ setGroupByAndLoad(area, groupBy, dir = 'asc') {
1214
+ return this.store.dispatch(new SetGroupBy(area, groupBy, dir));
1215
+ }
998
1216
  /**
999
1217
  * Clears both header and column filter slices in one state update,
1000
1218
  * triggering a single BE reload.
@@ -1012,15 +1230,24 @@ class WorkCenterFacade {
1012
1230
  }
1013
1231
  return Math.max(1, Math.floor(parsed));
1014
1232
  }
1233
+ /**
1234
+ * `mt-table` always reports its sort on a lazy event, so a `null` field is an
1235
+ * explicit "no sort" and must clear `context.sort` (the BE contract asks for
1236
+ * `sort: []`). Only an event with no `sortField` key at all — nothing the
1237
+ * current table emits — leaves the existing sort alone.
1238
+ */
1015
1239
  toSortFromLazyEvent(event) {
1016
- const sortField = event?.sortField;
1017
- if (typeof sortField !== 'string' || !sortField.length) {
1240
+ if (!event || !('sortField' in event)) {
1018
1241
  return null;
1019
1242
  }
1243
+ const sortField = event.sortField;
1244
+ if (typeof sortField !== 'string' || !sortField.length) {
1245
+ return [];
1246
+ }
1020
1247
  return [
1021
1248
  {
1022
1249
  field: sortField,
1023
- dir: event?.sortOrder === -1 ? 'desc' : 'asc',
1250
+ dir: event.sortOrder === -1 ? 'desc' : 'asc',
1024
1251
  },
1025
1252
  ];
1026
1253
  }
@@ -1685,7 +1912,7 @@ class WorkCenterProcessPreview {
1685
1912
  });
1686
1913
  }
1687
1914
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterProcessPreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
1688
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterProcessPreview, isStandalone: true, selector: "mt-work-center-process-preview", 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()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process preview is not available for this item yet.\r\n </p>\r\n </div>\r\n} @else if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"text-sm text-surface-500\">Loading process preview...</p>\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">{{ error() }}</p>\r\n </div>\r\n} @else {\r\n @if (view() === \"schema\") {\r\n @if (hasSchema()) {\r\n <div class=\"wc-process-preview-schema h-[70vh] overflow-hidden\">\r\n <mt-structure-builder\r\n class=\"h-full\"\r\n [layoutDirection]=\"'LR'\"\r\n [readonly]=\"true\"\r\n [structureMode]=\"'workflow'\"\r\n [nodeFields]=\"previewNodeFields\"\r\n [nodes]=\"schemaNodes()\"\r\n [connections]=\"schemaConnections()\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process steps are not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n } @else if (hasApprovals()) {\r\n <div class=\"max-h-[70vh] overflow-y-auto\">\r\n <mt-table\r\n noCard\r\n [data]=\"approvalRows()\"\r\n [columns]=\"approvalColumns()\"\r\n storageKey=\"work-center-process-preview-table\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [clickableRows]=\"false\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process approvals data is not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n}\r\n", styles: [":host ::ng-deep .wc-process-preview-schema .wf-detail-row{align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "availableNodesLabel", "nodeForm", "nodeDialogFooterConfig", "connectionForm", "connectionFormulaSchemaId", "connectionFormulaConfig", "connectionGuard", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "structureMode", "nodeStyle", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
1915
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterProcessPreview, isStandalone: true, selector: "mt-work-center-process-preview", 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()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process preview is not available for this item yet.\r\n </p>\r\n </div>\r\n} @else if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"text-sm text-surface-500\">Loading process preview...</p>\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">{{ error() }}</p>\r\n </div>\r\n} @else {\r\n @if (view() === \"schema\") {\r\n @if (hasSchema()) {\r\n <div class=\"wc-process-preview-schema h-[70vh] overflow-hidden\">\r\n <mt-structure-builder\r\n class=\"h-full\"\r\n [layoutDirection]=\"'LR'\"\r\n [readonly]=\"true\"\r\n [structureMode]=\"'workflow'\"\r\n [nodeFields]=\"previewNodeFields\"\r\n [nodes]=\"schemaNodes()\"\r\n [connections]=\"schemaConnections()\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process steps are not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n } @else if (hasApprovals()) {\r\n <div class=\"max-h-[70vh] overflow-y-auto\">\r\n <mt-table\r\n noCard\r\n [data]=\"approvalRows()\"\r\n [columns]=\"approvalColumns()\"\r\n storageKey=\"work-center-process-preview-table\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [clickableRows]=\"false\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process approvals data is not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n}\r\n", styles: [":host ::ng-deep .wc-process-preview-schema .wf-detail-row{align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy", "sortField", "sortDirection"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange", "sortFieldChange", "sortDirectionChange"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "availableNodesLabel", "nodeForm", "nodeDialogFooterConfig", "connectionForm", "connectionFormulaSchemaId", "connectionFormulaConfig", "connectionGuard", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "structureMode", "nodeStyle", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
1689
1916
  }
1690
1917
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterProcessPreview, decorators: [{
1691
1918
  type: Component,
@@ -2506,6 +2733,13 @@ const GENERAL_TASK_CARD_KEYS = new Set([
2506
2733
  'generaltask',
2507
2734
  'generaltasks',
2508
2735
  ]);
2736
+ /**
2737
+ * Grouped columns the backend has no aggregate for. Their group headers must
2738
+ * count only the rows on the current page, so the KPI totals map is withheld —
2739
+ * otherwise a group whose label happens to match a stat ("Total", "Overdue")
2740
+ * would show an unrelated number.
2741
+ */
2742
+ const PAGE_LOCAL_GROUP_KEYS = new Set([WORK_CENTER_LEVEL_NAME_KEY]);
2509
2743
  function toLabel(value) {
2510
2744
  const normalized = value.split('.').pop() ?? value;
2511
2745
  return normalized
@@ -2706,6 +2940,15 @@ class WorkCenterPage {
2706
2940
  runtimeFiltersChanged = output();
2707
2941
  itemClicked = output();
2708
2942
  cardSelected = output();
2943
+ /**
2944
+ * Emitted whenever the backend sort changes (including grouping, which is
2945
+ * sent as a sort). Hosts should persist it — the runtime query is rebuilt
2946
+ * from `bootstrapInputs`, so a sort that isn't round-tripped is dropped on
2947
+ * the next navigation.
2948
+ */
2949
+ sortChanged = output();
2950
+ /** Emitted when the grouped column changes; `null` when grouping is cleared. */
2951
+ groupChanged = output();
2709
2952
  context = this.facade.context;
2710
2953
  headerFilters = this.facade.headerFilters;
2711
2954
  tableFilters = signal({}, ...(ngDevMode ? [{ debugName: "tableFilters" }] : /* istanbul ignore next */ []));
@@ -2725,16 +2968,40 @@ class WorkCenterPage {
2725
2968
  totalCount = this.facade.totalCount;
2726
2969
  columnFilters = this.facade.columnFilters;
2727
2970
  loading = this.facade.loading;
2971
+ groupBy = this.facade.groupBy;
2972
+ /**
2973
+ * Sort and grouping live in the runtime query (and the host's URL), not in
2974
+ * table storage — persisting them locally would let a restored table claim a
2975
+ * grouping the backend query no longer has. Stable reference: a fresh array
2976
+ * per change detection would re-run the table's persistence effect.
2977
+ */
2978
+ persistStateExclude = [
2979
+ 'pagePosition',
2980
+ 'sort',
2981
+ 'groupBy',
2982
+ ];
2728
2983
  tableColumns = computed(() => this.columns().map((column) => ({
2729
2984
  ...column,
2730
2985
  sortable: true,
2731
2986
  })), ...(ngDevMode ? [{ debugName: "tableColumns" }] : /* istanbul ignore next */ []));
2987
+ /**
2988
+ * Grouping is executed by the backend as a single sort, so the table's own
2989
+ * sort state is driven from the query we actually sent instead of the
2990
+ * table's internal memory of it.
2991
+ */
2992
+ sortField = computed(() => this.context().sort[0]?.field ?? null, ...(ngDevMode ? [{ debugName: "sortField" }] : /* istanbul ignore next */ []));
2993
+ sortDirection = computed(() => this.context().sort[0]?.dir ?? null, ...(ngDevMode ? [{ debugName: "sortDirection" }] : /* istanbul ignore next */ []));
2732
2994
  /**
2733
2995
  * Maps each status/group display label to its total count from the KPI
2734
2996
  * summary cards so the group header shows the real backend total rather than
2735
- * the current-page row count.
2997
+ * the current-page row count. Withheld for groups the backend doesn't
2998
+ * aggregate — see `PAGE_LOCAL_GROUP_KEYS`.
2736
2999
  */
2737
- statusGroupCountMap = computed(() => {
3000
+ groupCountMap = computed(() => {
3001
+ const activeGroup = this.groupBy();
3002
+ if (!activeGroup || PAGE_LOCAL_GROUP_KEYS.has(activeGroup)) {
3003
+ return null;
3004
+ }
2738
3005
  const map = new Map();
2739
3006
  for (const kpi of this.kpis()) {
2740
3007
  const label = kpi.subTitle;
@@ -2744,7 +3011,7 @@ class WorkCenterPage {
2744
3011
  }
2745
3012
  }
2746
3013
  return map;
2747
- }, ...(ngDevMode ? [{ debugName: "statusGroupCountMap" }] : /* istanbul ignore next */ []));
3014
+ }, ...(ngDevMode ? [{ debugName: "groupCountMap" }] : /* istanbul ignore next */ []));
2748
3015
  propertyFilterSchema = computed(() => {
2749
3016
  this.activeLang();
2750
3017
  const schema = this.runtimeFilterSchema();
@@ -2833,6 +3100,25 @@ class WorkCenterPage {
2833
3100
  * (handled by `applyColumnFiltersAndLoad`); when only paging/sort changed
2834
3101
  * we fall through to `applyTableLazyLoadAndLoad`.
2835
3102
  */
3103
+ /**
3104
+ * The table asks to group; the backend does the ordering. `setGroupByAndLoad`
3105
+ * rewrites `context.sort` and resets paging, so the lazy event the table
3106
+ * fires straight after carries the same sort and lands as a no-op.
3107
+ */
3108
+ onTableGroupByChange(key) {
3109
+ const nextGroup = key?.trim() ? key : null;
3110
+ if (nextGroup === this.groupBy()) {
3111
+ return;
3112
+ }
3113
+ const previousSort = this.facade.snapshotContext().sort;
3114
+ // Re-grouping the column we're already sorted by keeps its direction.
3115
+ const dir = nextGroup && this.sortField() === nextGroup
3116
+ ? (this.sortDirection() ?? 'asc')
3117
+ : 'asc';
3118
+ this.facade.setGroupByAndLoad(this.area(), nextGroup, dir);
3119
+ this.groupChanged.emit(nextGroup);
3120
+ this.emitSortIfChanged(previousSort);
3121
+ }
2836
3122
  onTableLazyLoad(event) {
2837
3123
  const schema = this.runtimeFilterSchema();
2838
3124
  const propertyKeys = (schema?.properties ?? [])
@@ -2845,7 +3131,21 @@ class WorkCenterPage {
2845
3131
  this.facade.applyColumnFiltersAndLoad(this.area(), nextColumnFilters);
2846
3132
  return;
2847
3133
  }
3134
+ const previousSort = this.facade.snapshotContext().sort;
2848
3135
  this.facade.applyTableLazyLoadAndLoad(this.area(), event);
3136
+ this.emitSortIfChanged(previousSort);
3137
+ }
3138
+ /**
3139
+ * Announces the backend sort to the host only when it actually moved, so a
3140
+ * host that mirrors it into the URL doesn't churn history on every page hit.
3141
+ * Reads the snapshot, not the signal — this runs in the same tick as the
3142
+ * dispatch that changed it.
3143
+ */
3144
+ emitSortIfChanged(previousSort) {
3145
+ const nextSort = this.facade.snapshotContext().sort;
3146
+ if (JSON.stringify(previousSort) !== JSON.stringify(nextSort)) {
3147
+ this.sortChanged.emit(nextSort);
3148
+ }
2849
3149
  }
2850
3150
  onGeneralTaskCreateClick() {
2851
3151
  const modalOptions = this.generalTaskModal();
@@ -2929,7 +3229,7 @@ class WorkCenterPage {
2929
3229
  return normalized.length ? normalized : null;
2930
3230
  }
2931
3231
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
2932
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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 }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, showSidebar: { classPropertyName: "showSidebar", publicName: "showSidebar", isSignal: true, isRequired: false, transformFunction: null }, bootstrapInputs: { classPropertyName: "bootstrapInputs", publicName: "bootstrapInputs", isSignal: true, isRequired: false, transformFunction: null }, openItemDrawer: { classPropertyName: "openItemDrawer", publicName: "openItemDrawer", isSignal: true, isRequired: false, transformFunction: null }, itemReadOnly: { classPropertyName: "itemReadOnly", publicName: "itemReadOnly", 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 }, generalTaskModal: { classPropertyName: "generalTaskModal", publicName: "generalTaskModal", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeFiltersChanged: "runtimeFiltersChanged", itemClicked: "itemClicked", cardSelected: "cardSelected" }, ngImport: i0, template: "<ng-template #headerActions>\r\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"headerFilters()\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n\r\n @if (showGeneralTaskCreateButton()) {\r\n <mt-button\r\n [label]=\"generalTaskButtonLabel()\"\r\n [icon]=\"generalTaskButtonIcon()\"\r\n size=\"small\"\r\n (onClick)=\"onGeneralTaskCreateClick()\"\r\n />\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #pageContent>\r\n <div class=\"flex flex-col gap-8\">\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\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div class=\"gap-3 flex flex-wrap\">\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n noCard\r\n [data]=\"rows()\"\r\n [columns]=\"tableColumns()\"\r\n tableLayout=\"auto\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [cellClickFilter]=\"true\"\r\n [generalSearch]=\"true\"\r\n [exportable]=\"true\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [freezeActions]=\"true\"\r\n [lazy]=\"true\"\r\n [lazyLocalSearch]=\"true\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"context().page - 1\"\r\n [first]=\"(context().page - 1) * context().pageSize\"\r\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\r\n [groupCountMap]=\"statusGroupCountMap()\"\r\n storageKey=\"work-center-page-table\"\r\n [filters]=\"tableFilters()\"\r\n (filtersChange)=\"tableFilters.set($event)\"\r\n (lazyLoad)=\"onTableLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</ng-template>\r\n\r\n@if (showSidebar()) {\r\n <mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"resolvedPageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n storageKey=\"work-center-client-page\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n >\r\n <ng-template #headerClientPageEnd>\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </mt-client-page>\r\n} @else {\r\n <div class=\"flex h-full min-h-0 flex-col bg-surface-0\">\r\n <div\r\n class=\"flex shrink-0 items-center justify-end border-b border-surface px-7 py-4\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </div>\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-7 py-5\">\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </div>\r\n </div>\r\n}\r\n\r\n@if (selectedItemContextKey(); as contextKey) {\r\n <mt-work-center-item-modal-route\r\n [contextKey]=\"contextKey\"\r\n [manageRouteOutlet]=\"false\"\r\n [showPreviewLevelAction]=\"false\"\r\n [readOnly]=\"itemReadOnly()\"\r\n appendTo=\"body\"\r\n drawerStyleClass=\"mt-work-center-item-drawer !w-[90vw]\"\r\n (closed)=\"selectedItemContextKey.set(null)\"\r\n />\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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"] }, { kind: "component", type: ClientPage, selector: "mt-client-page", inputs: ["menuIcon", "menuTitle", "menuItems", "menuItemsLoading", "activeItem", "collapsed", "resizable", "storageKey", "storageMode", "minSidebarWidth", "maxSidebarWidth", "defaultSidebarWidth"], outputs: ["collapsedChange", "menuItemClick", "loadChildren"] }, { 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", "cardClass"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "component", type: WorkCenterItemModalRoute, selector: "mt-work-center-item-modal-route", inputs: ["contextKey", "manageRouteOutlet", "showPreviewLevelAction", "readOnly", "appendTo", "drawerStyleClass"], outputs: ["previewLevel", "closed"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
3232
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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 }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, showSidebar: { classPropertyName: "showSidebar", publicName: "showSidebar", isSignal: true, isRequired: false, transformFunction: null }, bootstrapInputs: { classPropertyName: "bootstrapInputs", publicName: "bootstrapInputs", isSignal: true, isRequired: false, transformFunction: null }, openItemDrawer: { classPropertyName: "openItemDrawer", publicName: "openItemDrawer", isSignal: true, isRequired: false, transformFunction: null }, itemReadOnly: { classPropertyName: "itemReadOnly", publicName: "itemReadOnly", 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 }, generalTaskModal: { classPropertyName: "generalTaskModal", publicName: "generalTaskModal", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeFiltersChanged: "runtimeFiltersChanged", itemClicked: "itemClicked", cardSelected: "cardSelected", sortChanged: "sortChanged", groupChanged: "groupChanged" }, ngImport: i0, template: "<ng-template #headerActions>\r\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"headerFilters()\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n\r\n @if (showGeneralTaskCreateButton()) {\r\n <mt-button\r\n [label]=\"generalTaskButtonLabel()\"\r\n [icon]=\"generalTaskButtonIcon()\"\r\n size=\"small\"\r\n (onClick)=\"onGeneralTaskCreateClick()\"\r\n />\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #pageContent>\r\n <div class=\"flex flex-col gap-8\">\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\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div class=\"gap-3 flex flex-wrap\">\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n noCard\r\n [data]=\"rows()\"\r\n [columns]=\"tableColumns()\"\r\n tableLayout=\"auto\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [cellClickFilter]=\"true\"\r\n [generalSearch]=\"true\"\r\n [exportable]=\"true\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [freezeActions]=\"true\"\r\n [lazy]=\"true\"\r\n [lazyLocalSearch]=\"true\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"context().page - 1\"\r\n [first]=\"(context().page - 1) * context().pageSize\"\r\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\r\n [groupCountMap]=\"groupCountMap()\"\r\n [groupBy]=\"groupBy()\"\r\n [sortField]=\"sortField()\"\r\n [sortDirection]=\"sortDirection()\"\r\n storageKey=\"work-center-page-table\"\r\n [persistStateExclude]=\"persistStateExclude\"\r\n [filters]=\"tableFilters()\"\r\n (filtersChange)=\"tableFilters.set($event)\"\r\n (groupByChange)=\"onTableGroupByChange($event)\"\r\n (lazyLoad)=\"onTableLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</ng-template>\r\n\r\n@if (showSidebar()) {\r\n <mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"resolvedPageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n storageKey=\"work-center-client-page\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n >\r\n <ng-template #headerClientPageEnd>\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </mt-client-page>\r\n} @else {\r\n <div class=\"flex h-full min-h-0 flex-col bg-surface-0\">\r\n <div\r\n class=\"flex shrink-0 items-center justify-end border-b border-surface px-7 py-4\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </div>\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-7 py-5\">\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </div>\r\n </div>\r\n}\r\n\r\n@if (selectedItemContextKey(); as contextKey) {\r\n <mt-work-center-item-modal-route\r\n [contextKey]=\"contextKey\"\r\n [manageRouteOutlet]=\"false\"\r\n [showPreviewLevelAction]=\"false\"\r\n [readOnly]=\"itemReadOnly()\"\r\n appendTo=\"body\"\r\n drawerStyleClass=\"mt-work-center-item-drawer !w-[90vw]\"\r\n (closed)=\"selectedItemContextKey.set(null)\"\r\n />\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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"] }, { kind: "component", type: ClientPage, selector: "mt-client-page", inputs: ["menuIcon", "menuTitle", "menuItems", "menuItemsLoading", "activeItem", "collapsed", "resizable", "storageKey", "storageMode", "minSidebarWidth", "maxSidebarWidth", "defaultSidebarWidth"], outputs: ["collapsedChange", "menuItemClick", "loadChildren"] }, { 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", "cardClass"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy", "sortField", "sortDirection"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange", "sortFieldChange", "sortDirectionChange"] }, { kind: "component", type: WorkCenterItemModalRoute, selector: "mt-work-center-item-modal-route", inputs: ["contextKey", "manageRouteOutlet", "showPreviewLevelAction", "readOnly", "appendTo", "drawerStyleClass"], outputs: ["previewLevel", "closed"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
2933
3233
  }
2934
3234
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterPage, decorators: [{
2935
3235
  type: Component,
@@ -2942,8 +3242,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
2942
3242
  Table,
2943
3243
  WorkCenterItemModalRoute,
2944
3244
  SkeletonModule,
2945
- ], template: "<ng-template #headerActions>\r\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"headerFilters()\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n\r\n @if (showGeneralTaskCreateButton()) {\r\n <mt-button\r\n [label]=\"generalTaskButtonLabel()\"\r\n [icon]=\"generalTaskButtonIcon()\"\r\n size=\"small\"\r\n (onClick)=\"onGeneralTaskCreateClick()\"\r\n />\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #pageContent>\r\n <div class=\"flex flex-col gap-8\">\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\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div class=\"gap-3 flex flex-wrap\">\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n noCard\r\n [data]=\"rows()\"\r\n [columns]=\"tableColumns()\"\r\n tableLayout=\"auto\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [cellClickFilter]=\"true\"\r\n [generalSearch]=\"true\"\r\n [exportable]=\"true\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [freezeActions]=\"true\"\r\n [lazy]=\"true\"\r\n [lazyLocalSearch]=\"true\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"context().page - 1\"\r\n [first]=\"(context().page - 1) * context().pageSize\"\r\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\r\n [groupCountMap]=\"statusGroupCountMap()\"\r\n storageKey=\"work-center-page-table\"\r\n [filters]=\"tableFilters()\"\r\n (filtersChange)=\"tableFilters.set($event)\"\r\n (lazyLoad)=\"onTableLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</ng-template>\r\n\r\n@if (showSidebar()) {\r\n <mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"resolvedPageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n storageKey=\"work-center-client-page\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n >\r\n <ng-template #headerClientPageEnd>\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </mt-client-page>\r\n} @else {\r\n <div class=\"flex h-full min-h-0 flex-col bg-surface-0\">\r\n <div\r\n class=\"flex shrink-0 items-center justify-end border-b border-surface px-7 py-4\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </div>\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-7 py-5\">\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </div>\r\n </div>\r\n}\r\n\r\n@if (selectedItemContextKey(); as contextKey) {\r\n <mt-work-center-item-modal-route\r\n [contextKey]=\"contextKey\"\r\n [manageRouteOutlet]=\"false\"\r\n [showPreviewLevelAction]=\"false\"\r\n [readOnly]=\"itemReadOnly()\"\r\n appendTo=\"body\"\r\n drawerStyleClass=\"mt-work-center-item-drawer !w-[90vw]\"\r\n (closed)=\"selectedItemContextKey.set(null)\"\r\n />\r\n}\r\n" }]
2946
- }], ctorParameters: () => [], 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 }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], showSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSidebar", required: false }] }], bootstrapInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "bootstrapInputs", required: false }] }], openItemDrawer: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemDrawer", required: false }] }], itemReadOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemReadOnly", required: false }] }], openItemsInModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemsInModal", required: false }] }], itemModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemModal", required: false }] }], generalTaskModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalTaskModal", required: false }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }], cardSelected: [{ type: i0.Output, args: ["cardSelected"] }] } });
3245
+ ], template: "<ng-template #headerActions>\r\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"headerFilters()\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n\r\n @if (showGeneralTaskCreateButton()) {\r\n <mt-button\r\n [label]=\"generalTaskButtonLabel()\"\r\n [icon]=\"generalTaskButtonIcon()\"\r\n size=\"small\"\r\n (onClick)=\"onGeneralTaskCreateClick()\"\r\n />\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #pageContent>\r\n <div class=\"flex flex-col gap-8\">\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\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div class=\"gap-3 flex flex-wrap\">\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n noCard\r\n [data]=\"rows()\"\r\n [columns]=\"tableColumns()\"\r\n tableLayout=\"auto\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [cellClickFilter]=\"true\"\r\n [generalSearch]=\"true\"\r\n [exportable]=\"true\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [freezeActions]=\"true\"\r\n [lazy]=\"true\"\r\n [lazyLocalSearch]=\"true\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"context().page - 1\"\r\n [first]=\"(context().page - 1) * context().pageSize\"\r\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\r\n [groupCountMap]=\"groupCountMap()\"\r\n [groupBy]=\"groupBy()\"\r\n [sortField]=\"sortField()\"\r\n [sortDirection]=\"sortDirection()\"\r\n storageKey=\"work-center-page-table\"\r\n [persistStateExclude]=\"persistStateExclude\"\r\n [filters]=\"tableFilters()\"\r\n (filtersChange)=\"tableFilters.set($event)\"\r\n (groupByChange)=\"onTableGroupByChange($event)\"\r\n (lazyLoad)=\"onTableLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</ng-template>\r\n\r\n@if (showSidebar()) {\r\n <mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"resolvedPageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n storageKey=\"work-center-client-page\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n >\r\n <ng-template #headerClientPageEnd>\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </mt-client-page>\r\n} @else {\r\n <div class=\"flex h-full min-h-0 flex-col bg-surface-0\">\r\n <div\r\n class=\"flex shrink-0 items-center justify-end border-b border-surface px-7 py-4\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\r\n </div>\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-7 py-5\">\r\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\r\n </div>\r\n </div>\r\n}\r\n\r\n@if (selectedItemContextKey(); as contextKey) {\r\n <mt-work-center-item-modal-route\r\n [contextKey]=\"contextKey\"\r\n [manageRouteOutlet]=\"false\"\r\n [showPreviewLevelAction]=\"false\"\r\n [readOnly]=\"itemReadOnly()\"\r\n appendTo=\"body\"\r\n drawerStyleClass=\"mt-work-center-item-drawer !w-[90vw]\"\r\n (closed)=\"selectedItemContextKey.set(null)\"\r\n />\r\n}\r\n" }]
3246
+ }], ctorParameters: () => [], 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 }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], showSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSidebar", required: false }] }], bootstrapInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "bootstrapInputs", required: false }] }], openItemDrawer: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemDrawer", required: false }] }], itemReadOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemReadOnly", required: false }] }], openItemsInModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemsInModal", required: false }] }], itemModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemModal", required: false }] }], generalTaskModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalTaskModal", required: false }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }], cardSelected: [{ type: i0.Output, args: ["cardSelected"] }], sortChanged: [{ type: i0.Output, args: ["sortChanged"] }], groupChanged: [{ type: i0.Output, args: ["groupChanged"] }] } });
2947
3247
 
2948
3248
  const APP_STATES = [WorkCenterState];
2949
3249
 
@@ -2951,5 +3251,5 @@ const APP_STATES = [WorkCenterState];
2951
3251
  * Generated bundle index. Do not edit.
2952
3252
  */
2953
3253
 
2954
- export { APP_STATES, ApplyColumnFilters, ApplyHeaderFilters, ClearAllFilters, EnterArea, HydrateFromContext, LoadRuntime, SetLookups, SetParams, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterClientFormModal, WorkCenterFacade, WorkCenterItemModal, WorkCenterItemModalRoute, WorkCenterPage, WorkCenterState, decodeWorkCenterRouteContextKey, encodeWorkCenterRouteContextKey };
3254
+ export { APP_STATES, ApplyColumnFilters, ApplyHeaderFilters, ClearAllFilters, EnterArea, HydrateFromContext, LoadRuntime, SetGroupBy, SetLookups, SetParams, WORK_CENTER_EMPTY_LABEL, WORK_CENTER_GROUP_NONE, WORK_CENTER_LEVEL_GROUP_FIELD, WORK_CENTER_LEVEL_NAME_KEY, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterClientFormModal, WorkCenterFacade, WorkCenterItemModal, WorkCenterItemModalRoute, WorkCenterPage, WorkCenterState, decodeWorkCenterRouteContextKey, encodeWorkCenterRouteContextKey };
2955
3255
  //# sourceMappingURL=masterteam-work-center.mjs.map