@acorex-platform/module-workflow-management-client 0.0.21

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.
Files changed (41) hide show
  1. package/fesm2022/acorex-platform-module-workflow-management-client-acorex-platform-module-workflow-management-client-B_Sl7G2v.mjs +4990 -0
  2. package/fesm2022/acorex-platform-module-workflow-management-client-acorex-platform-module-workflow-management-client-B_Sl7G2v.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-module-workflow-management-client-activity-command-configurator-widget-column.component-BPa0Sh6Z.mjs +57 -0
  4. package/fesm2022/acorex-platform-module-workflow-management-client-activity-command-configurator-widget-column.component-BPa0Sh6Z.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-module-workflow-management-client-activity-command-configurator-widget-edit.component-DuYGXzAL.mjs +482 -0
  6. package/fesm2022/acorex-platform-module-workflow-management-client-activity-command-configurator-widget-edit.component-DuYGXzAL.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-module-workflow-management-client-contracts.mjs +163 -0
  8. package/fesm2022/acorex-platform-module-workflow-management-client-contracts.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-module-workflow-management-client-execute-workflow-with-input.command-BFdyJ4rC.mjs +127 -0
  10. package/fesm2022/acorex-platform-module-workflow-management-client-execute-workflow-with-input.command-BFdyJ4rC.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-workflow-management-client-execute-workflow.command-Cfdm1QAy.mjs +142 -0
  12. package/fesm2022/acorex-platform-module-workflow-management-client-execute-workflow.command-Cfdm1QAy.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-module-workflow-management-client-index-C8nsbDAw.mjs +142 -0
  14. package/fesm2022/acorex-platform-module-workflow-management-client-index-C8nsbDAw.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-module-workflow-management-client-index-CttfExOC.mjs +417 -0
  16. package/fesm2022/acorex-platform-module-workflow-management-client-index-CttfExOC.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-module-workflow-management-client-index-DKZTLui4.mjs +1329 -0
  18. package/fesm2022/acorex-platform-module-workflow-management-client-index-DKZTLui4.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-module-workflow-management-client-save-workflow-definition-activities.command-spFF77AO.mjs +60 -0
  20. package/fesm2022/acorex-platform-module-workflow-management-client-save-workflow-definition-activities.command-spFF77AO.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-activity-instance-rows.utils-CMVZYS4y.mjs +172 -0
  22. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-activity-instance-rows.utils-CMVZYS4y.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-configurator-widget-column.component-D0E2zjIA.mjs +81 -0
  24. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-configurator-widget-column.component-D0E2zjIA.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-configurator-widget-edit.component-CVTeOv-q.mjs +538 -0
  26. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-configurator-widget-edit.component-CVTeOv-q.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-live-dashboard.queries--9NtYkau.mjs +218 -0
  28. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-live-dashboard.queries--9NtYkau.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-run-history-popup.component-BWOyivC5.mjs +588 -0
  30. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-run-history-popup.component-BWOyivC5.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-run-history-timeline-tab.component-AnJ-Pywf.mjs +33 -0
  32. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-run-history-timeline-tab.component-AnJ-Pywf.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-run-history-visual-tab.component-Bw68Jwcb.mjs +227 -0
  34. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-run-history-visual-tab.component-Bw68Jwcb.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-task-popover.component-Cg4gODGo.mjs +300 -0
  36. package/fesm2022/acorex-platform-module-workflow-management-client-workflow-task-popover.component-Cg4gODGo.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-module-workflow-management-client.mjs +2 -0
  38. package/fesm2022/acorex-platform-module-workflow-management-client.mjs.map +1 -0
  39. package/package.json +28 -0
  40. package/types/acorex-platform-module-workflow-management-client-contracts.d.ts +341 -0
  41. package/types/acorex-platform-module-workflow-management-client.d.ts +1026 -0
@@ -0,0 +1,1329 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, input, inject, NgZone, DestroyRef, viewChild, signal, computed, effect, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import * as contracts from '@acorex-platform/module-workflow-management-client/contracts';
4
+ import { WORKFLOW_DEFINITION_ACTIVITIES_PAGE_COMPONENT_KEY, RootConfig } from '@acorex-platform/module-workflow-management-client/contracts';
5
+ export * from '@acorex-platform/module-workflow-management-client/contracts';
6
+ import { AXPDataGenerator } from '@acorex-platform/framework-client/core';
7
+ import * as i1 from '@acorex/cdk/accordion';
8
+ import { AXAccordionCdkModule } from '@acorex/cdk/accordion';
9
+ import * as i2 from '@acorex/components/button';
10
+ import { AXButtonModule } from '@acorex/components/button';
11
+ import * as i4 from '@acorex/components/decorators';
12
+ import { AXDecoratorModule } from '@acorex/components/decorators';
13
+ import { AXDropdownModule } from '@acorex/components/dropdown';
14
+ import { AXFormModule } from '@acorex/components/form';
15
+ import * as i3 from '@acorex/components/menu';
16
+ import { AXContextMenuComponent, AXMenuModule } from '@acorex/components/menu';
17
+ import * as i5 from '@acorex/components/search-box';
18
+ import { AXSearchBoxModule } from '@acorex/components/search-box';
19
+ import { AXSelectBoxModule } from '@acorex/components/select-box';
20
+ import * as i7 from '@acorex/core/translation';
21
+ import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
22
+ import { AXPWorkflowDesignerComponent, arrangeWorkflowDiagram, AXPWorkflowPaletteItemDragDirective } from '@acorex-platform/module-platform-management-client';
23
+ import { AXPPropertyViewerComponent, buildPropertyViewerTabsFromProperties, AXPLayoutFloatingZoomBarComponent, AXPLayoutSideDetailPanelComponent } from '@acorex-platform/framework-client/layout/components';
24
+ import { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';
25
+ import { AXPPageLayoutBaseComponent, AXPPageLayoutBase } from '@acorex-platform/framework-client/layout/views';
26
+ import { mapAXPPropertyToWidgetProperty } from '@acorex-platform/framework-client/layout/widget-core';
27
+ import { AXPCommandService } from '@acorex-platform/framework-client/runtime';
28
+ import { AXPActivityDefinitionService } from '@acorex-platform/framework-client/workflow';
29
+ import * as i1$1 from '@angular/common';
30
+ import { CommonModule } from '@angular/common';
31
+ import { FormsModule } from '@angular/forms';
32
+ import { cloneDeep, isEqual } from 'lodash';
33
+ import { WORKFLOW_DEFINITION_ACTIVITIES_SAVE_COMMAND } from './acorex-platform-module-workflow-management-client-save-workflow-definition-activities.command-spFF77AO.mjs';
34
+
35
+ //#region ---- Workflow Definition Activities Page Provider ----
36
+ class AXMWorkflowDefinitionActivitiesPageComponentProvider {
37
+ async components() {
38
+ return [
39
+ {
40
+ key: WORKFLOW_DEFINITION_ACTIVITIES_PAGE_COMPONENT_KEY,
41
+ loader: () => Promise.resolve().then(function () { return workflowDefinitionActivitiesPage_component; }).then((m) => m.AXMWorkflowDefinitionActivitiesPageComponent),
42
+ },
43
+ ];
44
+ }
45
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkflowDefinitionActivitiesPageComponentProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
46
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkflowDefinitionActivitiesPageComponentProvider }); }
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkflowDefinitionActivitiesPageComponentProvider, decorators: [{
49
+ type: Injectable
50
+ }] });
51
+
52
+ //#region ---- Types ----
53
+ //#endregion
54
+ //#region ---- Designer layout helpers ----
55
+ function isDesignerLayoutArranged(graph) {
56
+ return graph?.designer?.layoutArranged === true;
57
+ }
58
+ /** True when every activity has persisted designer node coordinates. */
59
+ function graphHasPersistedDesignerLayout(graph) {
60
+ const activities = graph?.activities ?? [];
61
+ if (activities.length === 0) {
62
+ return false;
63
+ }
64
+ const nodes = graph?.designer?.nodes;
65
+ if (nodes == null || Object.keys(nodes).length === 0) {
66
+ return false;
67
+ }
68
+ return activities.every((a) => {
69
+ const n = nodes[a.id];
70
+ return n != null && typeof n.x === 'number' && typeof n.y === 'number';
71
+ });
72
+ }
73
+ //#endregion
74
+
75
+ //#region ---- Imports ----
76
+ //#endregion
77
+ //#region ---- Constants ----
78
+ const DEFAULT_NODE_W = 240;
79
+ const DEFAULT_NODE_H = 96;
80
+ const DESIGNER_GRID_SIZE = 20;
81
+ /** Debounce window before persisting designer edits (drag emits many modelChange events). */
82
+ const AUTO_SAVE_DEBOUNCE_MS = 500;
83
+ const DISCARD_COMMAND = 'WorkflowManagement.WorkflowDefinition:Activities:Discard';
84
+ const ADD_STEP_COMMAND = 'WorkflowManagement.WorkflowDefinition:Activities:AddStep';
85
+ const ARRANGE_LAYOUT_COMMAND = 'WorkflowManagement.WorkflowDefinition:Activities:ArrangeLayout';
86
+ const TOGGLE_DETAIL_PANEL_ACTION_ID = 'workflow-management.activities.toggle-detail-panel';
87
+ const ADD_ACTIVITY_ACTION_ID = 'workflow-management.activities.add-activity';
88
+ const TOGGLE_DETAIL_PANEL_ACTION_TITLE_KEY = '@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.node-actions.toggle-detail-panel';
89
+ const ADD_ACTIVITY_ACTION_TITLE_KEY = '@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.node-actions.add-activity';
90
+ const ARRANGE_LAYOUT_ACTION_TITLE_KEY = '@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.node-actions.arrange-layout';
91
+ //#endregion
92
+ //#region ---- Helpers ----
93
+ function normalizeActivityDefinitionInputs(raw) {
94
+ if (Array.isArray(raw)) {
95
+ return raw;
96
+ }
97
+ if (typeof raw === 'string' && raw.trim().length > 0) {
98
+ try {
99
+ const parsed = JSON.parse(raw);
100
+ return Array.isArray(parsed) ? parsed : [];
101
+ }
102
+ catch {
103
+ return [];
104
+ }
105
+ }
106
+ return [];
107
+ }
108
+ function portKey(port) {
109
+ return port == null || port === '' ? 'Done' : port;
110
+ }
111
+ function rowFromInstance(a) {
112
+ const inputs = a.inputs != null && typeof a.inputs === 'object' && !Array.isArray(a.inputs)
113
+ ? { ...a.inputs }
114
+ : {};
115
+ const extRaw = a.extensions;
116
+ const extensions = extRaw != null && typeof extRaw === 'object' && !Array.isArray(extRaw)
117
+ ? { ...extRaw }
118
+ : undefined;
119
+ return {
120
+ id: a.id,
121
+ name: typeof a.name === 'string' ? a.name : '',
122
+ inputs,
123
+ ...(extensions != null && Object.keys(extensions).length > 0 ? { extensions } : {}),
124
+ };
125
+ }
126
+ function instanceFromRow(r) {
127
+ const out = { id: r.id, name: r.name, inputs: { ...r.inputs } };
128
+ if (r.extensions != null && Object.keys(r.extensions).length > 0) {
129
+ out.extensions = { ...r.extensions };
130
+ }
131
+ return out;
132
+ }
133
+ function emptyGraph() {
134
+ return { startActivityId: '', activities: [], connections: [] };
135
+ }
136
+ function graphFingerprint(g) {
137
+ if (g == null) {
138
+ return null;
139
+ }
140
+ return {
141
+ startActivityId: g.startActivityId,
142
+ activities: g.activities,
143
+ connections: g.connections,
144
+ designer: g.designer,
145
+ };
146
+ }
147
+ //#endregion
148
+ //#region ---- Component ----
149
+ class AXMWorkflowDefinitionActivitiesPageComponent extends AXPPageLayoutBaseComponent {
150
+ //#endregion
151
+ //#region ---- Lifecycle ----
152
+ constructor() {
153
+ super();
154
+ //#region ---- Inputs ----
155
+ this.rootContext = input(/* @ts-ignore */
156
+ ...(ngDevMode ? [undefined, { debugName: "rootContext" }] : /* istanbul ignore next */ []));
157
+ this.pageConfig = input(/* @ts-ignore */
158
+ ...(ngDevMode ? [undefined, { debugName: "pageConfig" }] : /* istanbul ignore next */ []));
159
+ //#endregion
160
+ //#region ---- Services ----
161
+ this.commandService = inject(AXPCommandService);
162
+ this.entityService = inject(AXPEntityService);
163
+ this.activityDefService = inject(AXPActivityDefinitionService);
164
+ this.mlResolver = inject(AXTranslationService);
165
+ this.hostPageLayout = inject(AXPPageLayoutBase, { optional: true, skipSelf: true });
166
+ this.ngZone = inject(NgZone);
167
+ this.destroyRef = inject(DestroyRef);
168
+ //#endregion
169
+ //#region ---- Auto-save ----
170
+ this.autoSaveTimer = null;
171
+ this.autoSaveInFlight = false;
172
+ this.autoSavePending = false;
173
+ this.suppressAutoSave = false;
174
+ //#region ---- View refs ----
175
+ this.propertyViewerRef = viewChild(AXPPropertyViewerComponent, /* @ts-ignore */
176
+ ...(ngDevMode ? [{ debugName: "propertyViewerRef" }] : /* istanbul ignore next */ []));
177
+ this.workflowDesignerRef = viewChild(AXPWorkflowDesignerComponent, /* @ts-ignore */
178
+ ...(ngDevMode ? [{ debugName: "workflowDesignerRef" }] : /* istanbul ignore next */ []));
179
+ this.contextMenu = viewChild(AXContextMenuComponent, /* @ts-ignore */
180
+ ...(ngDevMode ? [{ debugName: "contextMenu" }] : /* istanbul ignore next */ []));
181
+ //#endregion
182
+ //#region ---- State ----
183
+ this.baselineGraph = signal(null, /* @ts-ignore */
184
+ ...(ngDevMode ? [{ debugName: "baselineGraph" }] : /* istanbul ignore next */ []));
185
+ /** Persisted on `graph.designer.layoutArranged` after the first auto-arrange (or layout migration). */
186
+ this.layoutArrangedFlag = signal(false, /* @ts-ignore */
187
+ ...(ngDevMode ? [{ debugName: "layoutArrangedFlag" }] : /* istanbul ignore next */ []));
188
+ this.initialLayoutArrangeInFlight = false;
189
+ this.activityCatalogLoaded = signal(false, /* @ts-ignore */
190
+ ...(ngDevMode ? [{ debugName: "activityCatalogLoaded" }] : /* istanbul ignore next */ []));
191
+ this.activityDefCache = signal({}, /* @ts-ignore */
192
+ ...(ngDevMode ? [{ debugName: "activityDefCache" }] : /* istanbul ignore next */ []));
193
+ this.activitySelectItems = signal([], /* @ts-ignore */
194
+ ...(ngDevMode ? [{ debugName: "activitySelectItems" }] : /* istanbul ignore next */ []));
195
+ this.activities = signal([], /* @ts-ignore */
196
+ ...(ngDevMode ? [{ debugName: "activities" }] : /* istanbul ignore next */ []));
197
+ this.connections = signal([], /* @ts-ignore */
198
+ ...(ngDevMode ? [{ debugName: "connections" }] : /* istanbul ignore next */ []));
199
+ this.startActivityId = signal('', /* @ts-ignore */
200
+ ...(ngDevMode ? [{ debugName: "startActivityId" }] : /* istanbul ignore next */ []));
201
+ this.selectedRowId = signal(null, /* @ts-ignore */
202
+ ...(ngDevMode ? [{ debugName: "selectedRowId" }] : /* istanbul ignore next */ []));
203
+ this.viewerTabs = signal([], /* @ts-ignore */
204
+ ...(ngDevMode ? [{ debugName: "viewerTabs" }] : /* istanbul ignore next */ []));
205
+ this.selectedActivityOutcomeRows = signal([], /* @ts-ignore */
206
+ ...(ngDevMode ? [{ debugName: "selectedActivityOutcomeRows" }] : /* istanbul ignore next */ []));
207
+ this.isDirty = signal(false, /* @ts-ignore */
208
+ ...(ngDevMode ? [{ debugName: "isDirty" }] : /* istanbul ignore next */ []));
209
+ this.backgroundPattern = signal('dots', /* @ts-ignore */
210
+ ...(ngDevMode ? [{ debugName: "backgroundPattern" }] : /* istanbul ignore next */ []));
211
+ this.zoomLevel = signal(100, /* @ts-ignore */
212
+ ...(ngDevMode ? [{ debugName: "zoomLevel" }] : /* istanbul ignore next */ []));
213
+ this.isFullscreen = signal(false, /* @ts-ignore */
214
+ ...(ngDevMode ? [{ debugName: "isFullscreen" }] : /* istanbul ignore next */ []));
215
+ this.isInfoPanelOpen = signal(false, /* @ts-ignore */
216
+ ...(ngDevMode ? [{ debugName: "isInfoPanelOpen" }] : /* istanbul ignore next */ []));
217
+ this.isPaletteOpen = signal(false, /* @ts-ignore */
218
+ ...(ngDevMode ? [{ debugName: "isPaletteOpen" }] : /* istanbul ignore next */ []));
219
+ this.paletteSearchTerm = signal('', /* @ts-ignore */
220
+ ...(ngDevMode ? [{ debugName: "paletteSearchTerm" }] : /* istanbul ignore next */ []));
221
+ /** Canvas layout keyed by activity instance id; kept in sync with designer `modelChange` and saved on `graph.designer`. */
222
+ this.designerLayout = signal({}, /* @ts-ignore */
223
+ ...(ngDevMode ? [{ debugName: "designerLayout" }] : /* istanbul ignore next */ []));
224
+ //#endregion
225
+ //#region ---- Computed ----
226
+ this.context = computed(() => this.rootContext() ?? {}, /* @ts-ignore */
227
+ ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
228
+ this.selectedRow = computed(() => this.activities().find((x) => x.id === this.selectedRowId()) ?? null, /* @ts-ignore */
229
+ ...(ngDevMode ? [{ debugName: "selectedRow" }] : /* istanbul ignore next */ []));
230
+ this.startActivityItems = computed(() => this.activities().map((r) => ({ value: r.id, text: this.formatActivityStepLabel(r) })), /* @ts-ignore */
231
+ ...(ngDevMode ? [{ debugName: "startActivityItems" }] : /* istanbul ignore next */ []));
232
+ this.activitySelectOptions = computed(() => {
233
+ const graphTitleByName = new Map();
234
+ for (const r of this.activities()) {
235
+ const n = r.name?.trim();
236
+ if (!n) {
237
+ continue;
238
+ }
239
+ const ext = r.extensions;
240
+ const dt = ext && typeof ext['displayTitle'] === 'string' ? ext['displayTitle'].trim() : '';
241
+ if (dt) {
242
+ graphTitleByName.set(n, dt);
243
+ }
244
+ }
245
+ const byValue = new Map();
246
+ for (const x of this.activitySelectItems()) {
247
+ byValue.set(x.value, {
248
+ value: x.value,
249
+ description: x.description,
250
+ icon: x.icon,
251
+ text: graphTitleByName.get(x.value) ?? x.text,
252
+ categoryId: x.categoryId,
253
+ categoryTitle: x.categoryTitle,
254
+ });
255
+ }
256
+ for (const r of this.activities()) {
257
+ const n = r.name?.trim();
258
+ if (!n || byValue.has(n)) {
259
+ continue;
260
+ }
261
+ byValue.set(n, {
262
+ value: n,
263
+ description: '',
264
+ icon: '',
265
+ text: graphTitleByName.get(n) ?? n,
266
+ categoryId: 'uncategorized',
267
+ categoryTitle: 'Uncategorized',
268
+ });
269
+ }
270
+ return [...byValue.values()].sort((a, b) => a.text.localeCompare(b.text));
271
+ }, /* @ts-ignore */
272
+ ...(ngDevMode ? [{ debugName: "activitySelectOptions" }] : /* istanbul ignore next */ []));
273
+ this.paletteItems = computed(() => this.activitySelectOptions().map((x) => ({
274
+ type: x.value,
275
+ title: x.text,
276
+ shape: 'rounded-rectangle',
277
+ size: { width: 230, height: 90 },
278
+ inboundPorts: [{ side: 'left', ratio: 0.5, key: 'in', label: 'in' }],
279
+ outboundPorts: [{ side: 'right', ratio: 0.5, key: 'Done', label: 'Done' }],
280
+ data: { category: 'activity-definition' },
281
+ })), /* @ts-ignore */
282
+ ...(ngDevMode ? [{ debugName: "paletteItems" }] : /* istanbul ignore next */ []));
283
+ this.paletteGroups = computed(() => {
284
+ const groupsById = new Map();
285
+ for (const item of this.activitySelectOptions()) {
286
+ const groupId = item.categoryId.trim() || 'uncategorized';
287
+ const groupTitle = item.categoryTitle.trim() || 'Uncategorized';
288
+ const existing = groupsById.get(groupId);
289
+ const paletteItem = {
290
+ type: item.value,
291
+ title: item.text,
292
+ description: item.description,
293
+ icon: item.icon,
294
+ shape: 'rounded-rectangle',
295
+ size: { width: 230, height: 90 },
296
+ inboundPorts: [{ side: 'left', ratio: 0.5, key: 'in', label: 'in' }],
297
+ outboundPorts: [{ side: 'right', ratio: 0.5, key: 'Done', label: 'Done' }],
298
+ data: { category: 'activity-definition' },
299
+ };
300
+ if (existing) {
301
+ existing.items.push(paletteItem);
302
+ continue;
303
+ }
304
+ groupsById.set(groupId, { id: groupId, title: groupTitle, items: [paletteItem] });
305
+ }
306
+ return [...groupsById.values()]
307
+ .map((group) => ({
308
+ ...group,
309
+ items: [...group.items].sort((a, b) => a.title.localeCompare(b.title)),
310
+ }))
311
+ .sort((a, b) => a.title.localeCompare(b.title));
312
+ }, /* @ts-ignore */
313
+ ...(ngDevMode ? [{ debugName: "paletteGroups" }] : /* istanbul ignore next */ []));
314
+ this.filteredPaletteGroups = computed(() => {
315
+ const searchTerm = this.paletteSearchTerm().trim().toLowerCase();
316
+ const groups = this.paletteGroups();
317
+ if (!searchTerm) {
318
+ return groups;
319
+ }
320
+ return groups
321
+ .map((group) => {
322
+ const items = group.items.filter((item) => {
323
+ const title = item.title?.toLowerCase() ?? '';
324
+ const description = item.description?.toLowerCase() ?? '';
325
+ return title.includes(searchTerm) || description.includes(searchTerm);
326
+ });
327
+ return { ...group, items };
328
+ })
329
+ .filter((group) => group.items.length > 0);
330
+ }, /* @ts-ignore */
331
+ ...(ngDevMode ? [{ debugName: "filteredPaletteGroups" }] : /* istanbul ignore next */ []));
332
+ this.designerModel = computed(() => {
333
+ const rows = this.activities();
334
+ const conns = this.connections();
335
+ const cache = this.activityDefCache();
336
+ const layout = this.designerLayout();
337
+ const nodes = rows.map((r, i) => {
338
+ const def = r.name ? cache[r.name] : undefined;
339
+ const outcomes = this.buildOutcomeRows(r.id, r, def);
340
+ const L = layout[r.id];
341
+ const pos = L ? { x: L.x, y: L.y } : this.gridFallbackPosition(i);
342
+ const size = L ? { width: L.width, height: L.height } : { width: DEFAULT_NODE_W, height: DEFAULT_NODE_H };
343
+ return {
344
+ id: r.id,
345
+ type: r.name,
346
+ title: this.resolveNodeTitle(r),
347
+ shape: 'rounded-rectangle',
348
+ size,
349
+ position: pos,
350
+ color: this.startActivityId() === r.id ? 'success' : 'secondary',
351
+ inboundPorts: [
352
+ { id: `${r.id}:in`, kind: 'inbound', side: 'left', ratio: 0.5, key: 'in', label: 'in' },
353
+ ],
354
+ outboundPorts: outcomes.map((o, oi, arr) => ({
355
+ id: `${r.id}:out:${o.port}`,
356
+ kind: 'outbound',
357
+ side: 'right',
358
+ ratio: arr.length === 1 ? 0.5 : (oi + 1) / (arr.length + 1),
359
+ key: o.port,
360
+ label: o.label,
361
+ })),
362
+ };
363
+ });
364
+ const outPortByKey = new Map();
365
+ for (const n of nodes) {
366
+ for (const p of n.outboundPorts) {
367
+ outPortByKey.set(`${n.id}:${portKey(p.key)}`, p.id);
368
+ }
369
+ }
370
+ const connectors = conns
371
+ .map((c, i) => {
372
+ const sourcePortKey = portKey(c.source.port);
373
+ const sourcePortId = outPortByKey.get(`${c.source.activtyName}:${sourcePortKey}`);
374
+ if (!sourcePortId) {
375
+ return null;
376
+ }
377
+ return {
378
+ id: `c-${i}-${c.source.activtyName}-${c.target.activtyName}-${sourcePortKey}`,
379
+ sourceNodeId: c.source.activtyName,
380
+ sourcePortId,
381
+ targetNodeId: c.target.activtyName,
382
+ targetPortId: `${c.target.activtyName}:in`,
383
+ };
384
+ })
385
+ .filter((x) => x != null);
386
+ return { nodes, connectors };
387
+ }, /* @ts-ignore */
388
+ ...(ngDevMode ? [{ debugName: "designerModel" }] : /* istanbul ignore next */ []));
389
+ this.selectedNodeInfoRows = computed(() => {
390
+ const selected = this.selectedRow();
391
+ if (!selected) {
392
+ return [];
393
+ }
394
+ const selectOption = this.activitySelectOptions().find((x) => x.value === selected.name);
395
+ return [
396
+ { title: 'Title', content: this.resolveNodeTitle(selected) || '---' },
397
+ { title: 'Type', content: selected.name || '---' },
398
+ { title: 'Id', content: selected.id || '---' },
399
+ { title: 'Category', content: selectOption?.categoryTitle || '---' },
400
+ { title: 'Inputs', content: `${Object.keys(selected.inputs ?? {}).length}` },
401
+ { title: 'Outcomes', content: `${this.selectedActivityOutcomeRows().length}` },
402
+ ];
403
+ }, /* @ts-ignore */
404
+ ...(ngDevMode ? [{ debugName: "selectedNodeInfoRows" }] : /* istanbul ignore next */ []));
405
+ this.workflowDetailPanelCopy = signal({
406
+ panelTitle: 'Activity details',
407
+ emptyMessage: 'Select a node to see details.',
408
+ }, /* @ts-ignore */
409
+ ...(ngDevMode ? [{ debugName: "workflowDetailPanelCopy" }] : /* istanbul ignore next */ []));
410
+ this.workflowDetailPanelHeader = computed(() => {
411
+ const selected = this.selectedRow();
412
+ if (selected == null) {
413
+ return null;
414
+ }
415
+ const selectOption = this.activitySelectOptions().find((x) => x.value === selected.name);
416
+ const iconGlyph = selectOption?.icon?.trim();
417
+ return {
418
+ primaryTitle: this.resolveNodeTitle(selected) || '---',
419
+ icon: iconGlyph ? { iconClass: `fa-light fa-lg fa-fw ${iconGlyph}` } : undefined,
420
+ };
421
+ }, /* @ts-ignore */
422
+ ...(ngDevMode ? [{ debugName: "workflowDetailPanelHeader" }] : /* istanbul ignore next */ []));
423
+ this.workflowDetailPanelRows = computed(() => {
424
+ if (this.selectedRow() == null) {
425
+ return [];
426
+ }
427
+ return this.selectedNodeInfoRows().map((row) => ({
428
+ label: row.title,
429
+ value: row.content,
430
+ }));
431
+ }, /* @ts-ignore */
432
+ ...(ngDevMode ? [{ debugName: "workflowDetailPanelRows" }] : /* istanbul ignore next */ []));
433
+ this.workflowDetailPanelEmptyState = computed(() => {
434
+ if (this.selectedRow() != null) {
435
+ return null;
436
+ }
437
+ const copy = this.workflowDetailPanelCopy();
438
+ return {
439
+ primaryTitle: copy.panelTitle,
440
+ message: copy.emptyMessage,
441
+ icon: { iconClass: 'fa-solid fa-lg fa-fw fa-diagram-project' },
442
+ };
443
+ }, /* @ts-ignore */
444
+ ...(ngDevMode ? [{ debugName: "workflowDetailPanelEmptyState" }] : /* istanbul ignore next */ []));
445
+ let previousRootId = undefined;
446
+ effect(() => {
447
+ const ctx = this.rootContext();
448
+ const currentId = ctx != null && typeof ctx === 'object' ? ctx['id'] : undefined;
449
+ if (currentId !== previousRootId) {
450
+ previousRootId = currentId;
451
+ untracked(() => this.hydrateFromServerContext(ctx));
452
+ }
453
+ });
454
+ effect(() => {
455
+ const ctx = this.context();
456
+ const id = typeof ctx['id'] === 'string' ? ctx['id'] : undefined;
457
+ const arranged = this.layoutArrangedFlag();
458
+ const activityCount = this.activities().length;
459
+ if (!id || arranged || activityCount === 0) {
460
+ return;
461
+ }
462
+ untracked(() => void this.maybeApplyInitialArrangedLayout());
463
+ });
464
+ this.destroyRef.onDestroy(() => this.clearAutoSaveTimer());
465
+ }
466
+ //#endregion
467
+ //#region ---- Page chrome / commands ----
468
+ hasUnsavedChanges() {
469
+ return this.isDirty();
470
+ }
471
+ // override async getPrimaryMenuItems(): Promise<AXPActionMenuItem[]> {
472
+ // const addTitle =
473
+ // (await this.translateService.translateAsync(
474
+ // '@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.add-step',
475
+ // )) || 'Add step';
476
+ // const discardTitle = (await this.translateService.translateAsync('@general:actions.discard.title')) || 'Discard';
477
+ // const saveTitle = (await this.translateService.translateAsync('@general:actions.save.title')) || 'Save';
478
+ // const addAction: AXPLayoutDetailsViewAction = {
479
+ // title: addTitle,
480
+ // icon: 'fa-light fa-plus',
481
+ // zone: 'header',
482
+ // priority: 'primary',
483
+ // color: 'primary',
484
+ // command: { name: ADD_STEP_COMMAND, options: {} },
485
+ // };
486
+ // const discardAction: AXPLayoutDetailsViewAction = {
487
+ // title: discardTitle,
488
+ // icon: 'fa-light fa-rotate-left',
489
+ // zone: 'footer',
490
+ // priority: 'secondary',
491
+ // color: 'default',
492
+ // visible: this.isDirty(),
493
+ // command: { name: DISCARD_COMMAND, options: {} },
494
+ // };
495
+ // const saveAction: AXPLayoutDetailsViewAction = {
496
+ // title: saveTitle,
497
+ // icon: 'fa-light fa-floppy-disk',
498
+ // zone: 'footer',
499
+ // priority: 'primary',
500
+ // color: 'primary',
501
+ // visible: this.isDirty(),
502
+ // command: { name: WORKFLOW_DEFINITION_ACTIVITIES_SAVE_COMMAND, options: {} },
503
+ // };
504
+ // return [addAction, discardAction, saveAction];
505
+ // }
506
+ async getSecondaryMenuItems() {
507
+ const title = await this.mlResolver.translateAsync(ARRANGE_LAYOUT_ACTION_TITLE_KEY);
508
+ return [
509
+ {
510
+ title,
511
+ icon: 'fa-light fa-sitemap',
512
+ command: { name: ARRANGE_LAYOUT_COMMAND, options: {} },
513
+ disabled: this.activities().length === 0,
514
+ },
515
+ ];
516
+ }
517
+ execute(command) {
518
+ if (command.name === DISCARD_COMMAND) {
519
+ this.applyBaselineGraph();
520
+ return;
521
+ }
522
+ if (command.name === ADD_STEP_COMMAND) {
523
+ this.addStep();
524
+ return;
525
+ }
526
+ if (command.name === ARRANGE_LAYOUT_COMMAND) {
527
+ this.applyArrangedLayout();
528
+ return;
529
+ }
530
+ if (command.name === WORKFLOW_DEFINITION_ACTIVITIES_SAVE_COMMAND) {
531
+ return this.handleSaveExecute();
532
+ }
533
+ }
534
+ //#endregion
535
+ //#region ---- Designer handlers ----
536
+ onDesignerModelChange(model) {
537
+ const previousNodeCount = this.activities().length;
538
+ const oldById = new Map(this.activities().map((x) => [x.id, x]));
539
+ const nextRows = model.nodes.map((n) => {
540
+ const prev = oldById.get(n.id);
541
+ const title = n.title?.trim();
542
+ const extensions = { ...(prev?.extensions ?? {}) };
543
+ if (title) {
544
+ extensions['displayTitle'] = title;
545
+ }
546
+ else {
547
+ delete extensions['displayTitle'];
548
+ }
549
+ return {
550
+ id: n.id,
551
+ name: n.type?.trim() ? n.type : (prev?.name ?? ''),
552
+ inputs: { ...(prev?.inputs ?? {}) },
553
+ ...(Object.keys(extensions).length > 0 ? { extensions } : {}),
554
+ };
555
+ });
556
+ const outgoingByPortId = new Map();
557
+ for (const n of model.nodes) {
558
+ for (const p of n.outboundPorts) {
559
+ outgoingByPortId.set(p.id, portKey(p.key));
560
+ }
561
+ }
562
+ const nextConnections = [];
563
+ for (const c of model.connectors) {
564
+ const pk = outgoingByPortId.get(c.sourcePortId);
565
+ if (!pk) {
566
+ continue;
567
+ }
568
+ nextConnections.push({
569
+ source: { activtyName: c.sourceNodeId, port: pk === 'Done' ? null : pk },
570
+ target: { activtyName: c.targetNodeId, port: null },
571
+ });
572
+ }
573
+ this.activities.set(nextRows);
574
+ this.connections.set(nextConnections);
575
+ if (!nextRows.some((x) => x.id === this.startActivityId())) {
576
+ this.startActivityId.set(nextRows[0]?.id ?? '');
577
+ }
578
+ if (!nextRows.some((x) => x.id === this.selectedRowId())) {
579
+ this.selectedRowId.set(nextRows[0]?.id ?? null);
580
+ }
581
+ for (const r of nextRows) {
582
+ void this.ensureDefinition(r.name);
583
+ }
584
+ this.syncDesignerLayoutFromModel(model);
585
+ void this.refreshPropertyViewer();
586
+ this.recomputeDirty();
587
+ if (nextRows.length > previousNodeCount) {
588
+ this.closePalette();
589
+ }
590
+ }
591
+ onDesignerActivationChange(a) {
592
+ if (a?.kind !== 'node') {
593
+ return;
594
+ }
595
+ this.selectedRowId.set(a.id);
596
+ void this.refreshPropertyViewer();
597
+ }
598
+ //#region ---- Context Menu ----
599
+ onDesignerNodeContextMenu(payload) {
600
+ const anchor = payload.event.currentTarget instanceof HTMLElement
601
+ ? payload.event.currentTarget
602
+ : payload.event.target instanceof HTMLElement
603
+ ? payload.event.target.closest('.axp-workflow-designer__node')
604
+ : null;
605
+ if (!(anchor instanceof HTMLElement)) {
606
+ return;
607
+ }
608
+ void this.openWorkflowContextMenuAt(payload.event.clientX, payload.event.clientY, anchor, [
609
+ ADD_ACTIVITY_ACTION_ID,
610
+ TOGGLE_DETAIL_PANEL_ACTION_ID,
611
+ ]);
612
+ }
613
+ onDesignerSurfaceContextMenu(event) {
614
+ if (event.target instanceof HTMLElement && event.target.closest('.axp-workflow-designer__node')) {
615
+ return;
616
+ }
617
+ event.preventDefault();
618
+ event.stopPropagation();
619
+ const anchor = event.target instanceof HTMLElement
620
+ ? (event.target.closest('.axp-workflow-designer__surface') ?? event.target)
621
+ : null;
622
+ if (!(anchor instanceof HTMLElement)) {
623
+ return;
624
+ }
625
+ void this.openWorkflowContextMenuAt(event.clientX, event.clientY, anchor, [ADD_ACTIVITY_ACTION_ID]);
626
+ }
627
+ handleWorkflowContextMenuItemClick(e) {
628
+ if (e.item.name === TOGGLE_DETAIL_PANEL_ACTION_ID) {
629
+ this.toggleInfoPanel();
630
+ return;
631
+ }
632
+ if (e.item.name === ADD_ACTIVITY_ACTION_ID) {
633
+ this.openPalette();
634
+ }
635
+ }
636
+ openPalette() {
637
+ this.isPaletteOpen.set(true);
638
+ this.paletteSearchTerm.set('');
639
+ }
640
+ closePalette() {
641
+ this.isPaletteOpen.set(false);
642
+ }
643
+ async openWorkflowContextMenuAt(clientX, clientY, targetElement, actionIds) {
644
+ const items = [];
645
+ for (const actionId of actionIds) {
646
+ const item = await this.buildWorkflowContextMenuItem(actionId);
647
+ if (item != null) {
648
+ items.push(item);
649
+ }
650
+ }
651
+ if (items.length === 0) {
652
+ return;
653
+ }
654
+ const menu = this.contextMenu();
655
+ if (menu == null) {
656
+ return;
657
+ }
658
+ this.ngZone.run(() => {
659
+ const openingEvent = {
660
+ sender: menu,
661
+ canceled: false,
662
+ targetElement,
663
+ items,
664
+ };
665
+ menu.showAt({ x: clientX, y: clientY }, targetElement, openingEvent);
666
+ });
667
+ }
668
+ async buildWorkflowContextMenuItem(actionId) {
669
+ if (actionId === ADD_ACTIVITY_ACTION_ID) {
670
+ return {
671
+ name: ADD_ACTIVITY_ACTION_ID,
672
+ text: (await this.translateService.translateAsync(ADD_ACTIVITY_ACTION_TITLE_KEY)) ?? 'Add Activity',
673
+ icon: 'fa-light fa-plus',
674
+ };
675
+ }
676
+ if (actionId === TOGGLE_DETAIL_PANEL_ACTION_ID) {
677
+ return {
678
+ name: TOGGLE_DETAIL_PANEL_ACTION_ID,
679
+ text: (await this.translateService.translateAsync(TOGGLE_DETAIL_PANEL_ACTION_TITLE_KEY)) ?? 'Toggle Details Panel',
680
+ icon: 'fa-light fa-sidebar',
681
+ };
682
+ }
683
+ return null;
684
+ }
685
+ //#endregion
686
+ onBackgroundPatternChange(event) {
687
+ const value = event.target.value;
688
+ if (value === 'line' || value === 'dots') {
689
+ this.backgroundPattern.set(value);
690
+ }
691
+ }
692
+ onDesignerZoomChange(value) {
693
+ this.zoomLevel.set(this.clampZoomLevel(value));
694
+ }
695
+ onPaletteSearchChange(event) {
696
+ this.paletteSearchTerm.set(event?.value ?? '');
697
+ }
698
+ zoomIn() {
699
+ this.workflowDesignerRef()?.zoomIn();
700
+ this.zoomLevel.set(this.clampZoomLevel(this.workflowDesignerRef()?.getZoomLevel() ?? this.zoomLevel()));
701
+ }
702
+ zoomOut() {
703
+ this.workflowDesignerRef()?.zoomOut();
704
+ this.zoomLevel.set(this.clampZoomLevel(this.workflowDesignerRef()?.getZoomLevel() ?? this.zoomLevel()));
705
+ }
706
+ zoomReset() {
707
+ this.workflowDesignerRef()?.zoomReset();
708
+ this.zoomLevel.set(this.clampZoomLevel(this.workflowDesignerRef()?.getZoomLevel() ?? 100));
709
+ }
710
+ toggleFullscreen() {
711
+ const next = !this.isFullscreen();
712
+ this.isFullscreen.set(next);
713
+ const doc = globalThis.document;
714
+ if (!doc) {
715
+ return;
716
+ }
717
+ if (next) {
718
+ void doc.documentElement.requestFullscreen?.();
719
+ return;
720
+ }
721
+ void doc.exitFullscreen?.();
722
+ }
723
+ toggleInfoPanel() {
724
+ this.isInfoPanelOpen.update((open) => !open);
725
+ }
726
+ onStartActivityChange(event) {
727
+ this.startActivityId.set(event.value != null ? String(event.value) : '');
728
+ this.recomputeDirty();
729
+ }
730
+ onSelectedActivityTypeChange(event) {
731
+ const row = this.selectedRow();
732
+ if (!row) {
733
+ return;
734
+ }
735
+ const name = event.value != null ? String(event.value) : '';
736
+ const rowId = row.id;
737
+ this.activities.update((rows) => rows.map((r) => (r.id !== rowId ? r : { ...r, name, inputs: {}, extensions: undefined })));
738
+ void this.ensureDefinition(name);
739
+ void this.activityDefService.getActivityByName(name).then((def) => {
740
+ const rowNow = this.activities().find((r) => r.id === rowId) ?? null;
741
+ const allowed = new Set(this.buildOutcomeRows(rowId, rowNow, def).map((o) => o.port));
742
+ this.pruneOutgoingConnections(rowId, allowed);
743
+ void this.refreshPropertyViewer();
744
+ this.recomputeDirty();
745
+ });
746
+ void this.refreshPropertyViewer();
747
+ this.recomputeDirty();
748
+ }
749
+ onViewerChanged(ev) {
750
+ if (ev.mode === 'init') {
751
+ return;
752
+ }
753
+ const id = this.selectedRowId();
754
+ if (id == null || ev.values == null) {
755
+ return;
756
+ }
757
+ const inputs = ev.values.inputs ?? {};
758
+ this.activities.update((rows) => rows.map((r) => (r.id === id ? { ...r, inputs: { ...inputs } } : r)));
759
+ const sel = this.activities().find((r) => r.id === id);
760
+ if (sel?.name?.trim()) {
761
+ void this.activityDefService.getActivityByName(sel.name).then((def) => {
762
+ this.selectedActivityOutcomeRows.set(this.buildOutcomeRows(sel.id, sel, def));
763
+ });
764
+ }
765
+ this.recomputeDirty();
766
+ }
767
+ //#endregion
768
+ //#region ---- Graph persistence ----
769
+ gridFallbackPosition(index) {
770
+ return { x: 80 + (index % 4) * 320, y: 80 + Math.floor(index / 4) * 190 };
771
+ }
772
+ clampZoomLevel(value) {
773
+ if (Number.isNaN(value)) {
774
+ return 100;
775
+ }
776
+ return Math.max(20, Math.min(300, Math.round(value)));
777
+ }
778
+ initDesignerLayoutFromGraph(graph) {
779
+ const activities = graph?.activities ?? [];
780
+ const raw = graph?.designer?.nodes;
781
+ const next = {};
782
+ if (raw != null) {
783
+ for (const [id, v] of Object.entries(raw)) {
784
+ if (v != null && typeof v.x === 'number' && typeof v.y === 'number') {
785
+ next[id] = {
786
+ x: v.x,
787
+ y: v.y,
788
+ width: typeof v.width === 'number' && v.width > 0 ? v.width : DEFAULT_NODE_W,
789
+ height: typeof v.height === 'number' && v.height > 0 ? v.height : DEFAULT_NODE_H,
790
+ };
791
+ }
792
+ }
793
+ }
794
+ activities.forEach((a, i) => {
795
+ if (!next[a.id]) {
796
+ const p = this.gridFallbackPosition(i);
797
+ next[a.id] = { x: p.x, y: p.y, width: DEFAULT_NODE_W, height: DEFAULT_NODE_H };
798
+ }
799
+ });
800
+ this.designerLayout.set(next);
801
+ }
802
+ syncDesignerLayoutFromModel(model) {
803
+ const next = {};
804
+ for (const n of model.nodes) {
805
+ next[n.id] = {
806
+ x: n.position.x,
807
+ y: n.position.y,
808
+ width: n.size.width > 0 ? n.size.width : DEFAULT_NODE_W,
809
+ height: n.size.height > 0 ? n.size.height : DEFAULT_NODE_H,
810
+ };
811
+ }
812
+ this.designerLayout.set(next);
813
+ }
814
+ /** Updates persisted node coordinates only (no activity/connection graph rewrite). */
815
+ applyArrangedLayout() {
816
+ if (this.activities().length === 0) {
817
+ return;
818
+ }
819
+ const startId = this.startActivityId().trim();
820
+ const arranged = arrangeWorkflowDiagram(this.designerModel(), {
821
+ startNodeId: startId.length > 0 ? startId : undefined,
822
+ gridSize: DESIGNER_GRID_SIZE,
823
+ });
824
+ this.syncDesignerLayoutFromModel(arranged);
825
+ this.layoutArrangedFlag.set(true);
826
+ this.recomputeDirty();
827
+ }
828
+ buildDesignerNodesForSave() {
829
+ const layout = this.designerLayout();
830
+ const out = {};
831
+ for (const [id, L] of Object.entries(layout)) {
832
+ out[id] = {
833
+ x: L.x,
834
+ y: L.y,
835
+ nodeId: id,
836
+ width: L.width,
837
+ height: L.height,
838
+ };
839
+ }
840
+ return out;
841
+ }
842
+ buildCurrentGraph() {
843
+ const base = this.baselineGraph();
844
+ const layoutArranged = this.layoutArrangedFlag() || isDesignerLayoutArranged(base ?? undefined);
845
+ return {
846
+ startActivityId: this.startActivityId(),
847
+ activities: this.activities().map((r) => instanceFromRow(r)),
848
+ connections: cloneDeep(this.connections()),
849
+ designer: {
850
+ ...base?.designer,
851
+ layoutArranged: layoutArranged ? true : undefined,
852
+ nodes: this.buildDesignerNodesForSave(),
853
+ },
854
+ };
855
+ }
856
+ recomputeDirty() {
857
+ this.isDirty.set(!isEqual(graphFingerprint(this.buildCurrentGraph()), graphFingerprint(this.baselineGraph())));
858
+ this.recompute();
859
+ this.scheduleAutoSave();
860
+ }
861
+ clearAutoSaveTimer() {
862
+ if (this.autoSaveTimer != null) {
863
+ clearTimeout(this.autoSaveTimer);
864
+ this.autoSaveTimer = null;
865
+ }
866
+ }
867
+ /** Debounced persist for designer moves, connections, arrange, and property edits. */
868
+ scheduleAutoSave() {
869
+ if (this.suppressAutoSave || !this.isDirty()) {
870
+ return;
871
+ }
872
+ const ctx = this.context();
873
+ const id = typeof ctx['id'] === 'string' ? ctx['id'] : undefined;
874
+ if (!id) {
875
+ return;
876
+ }
877
+ this.clearAutoSaveTimer();
878
+ this.autoSaveTimer = setTimeout(() => {
879
+ this.autoSaveTimer = null;
880
+ void this.runAutoSave();
881
+ }, AUTO_SAVE_DEBOUNCE_MS);
882
+ }
883
+ async runAutoSave() {
884
+ if (this.suppressAutoSave || !this.isDirty()) {
885
+ return;
886
+ }
887
+ if (this.autoSaveInFlight) {
888
+ this.autoSavePending = true;
889
+ return;
890
+ }
891
+ this.autoSaveInFlight = true;
892
+ try {
893
+ await this.handleSaveExecute({ silent: true });
894
+ }
895
+ finally {
896
+ this.autoSaveInFlight = false;
897
+ if (this.autoSavePending) {
898
+ this.autoSavePending = false;
899
+ if (this.isDirty()) {
900
+ this.scheduleAutoSave();
901
+ }
902
+ }
903
+ }
904
+ }
905
+ async handleSaveExecute(options) {
906
+ this.clearAutoSaveTimer();
907
+ const ctx = this.context();
908
+ const id = typeof ctx['id'] === 'string' ? ctx['id'] : undefined;
909
+ if (!id) {
910
+ return {
911
+ success: false,
912
+ message: { text: await this.translateService.translateAsync('@general:messages.entity.invalid-data') },
913
+ };
914
+ }
915
+ const graph = this.buildCurrentGraph();
916
+ const result = await this.commandService.execute(WORKFLOW_DEFINITION_ACTIVITIES_SAVE_COMMAND, { id, graph, silent: options?.silent });
917
+ const execResult = (result ?? { success: false });
918
+ if (execResult.success) {
919
+ this.baselineGraph.set(cloneDeep(graph));
920
+ this.isDirty.set(false);
921
+ if (!options?.silent) {
922
+ this.recompute();
923
+ }
924
+ }
925
+ return execResult;
926
+ }
927
+ hydrateFromServerContext(ctx) {
928
+ this.clearAutoSaveTimer();
929
+ this.suppressAutoSave = true;
930
+ try {
931
+ const graph = ctx?.['graph'] ?? emptyGraph();
932
+ this.baselineGraph.set(cloneDeep(graph));
933
+ this.layoutArrangedFlag.set(isDesignerLayoutArranged(graph));
934
+ this.initDesignerLayoutFromGraph(graph);
935
+ this.activities.set((graph.activities ?? []).map((a) => rowFromInstance(a)));
936
+ this.connections.set(cloneDeep(graph.connections ?? []));
937
+ let start = graph.startActivityId ?? '';
938
+ const rows = this.activities();
939
+ if (!start && rows.length > 0) {
940
+ start = rows[0].id;
941
+ }
942
+ this.startActivityId.set(start);
943
+ this.selectedRowId.set(rows[0]?.id ?? null);
944
+ this.isDirty.set(false);
945
+ void this.ensureActivityCatalogLoaded();
946
+ for (const r of rows) {
947
+ void this.ensureDefinition(r.name);
948
+ }
949
+ void this.refreshPropertyViewer();
950
+ }
951
+ finally {
952
+ this.suppressAutoSave = false;
953
+ }
954
+ }
955
+ /**
956
+ * Runs auto-arrange once per workflow definition, then persists `graph.designer.layoutArranged`.
957
+ * Definitions that already have saved node positions are marked arranged without moving nodes.
958
+ */
959
+ async maybeApplyInitialArrangedLayout() {
960
+ if (this.layoutArrangedFlag() || this.initialLayoutArrangeInFlight) {
961
+ return;
962
+ }
963
+ const ctx = this.context();
964
+ const id = typeof ctx['id'] === 'string' ? ctx['id'] : undefined;
965
+ if (!id) {
966
+ return;
967
+ }
968
+ if (this.activities().length === 0) {
969
+ return;
970
+ }
971
+ this.initialLayoutArrangeInFlight = true;
972
+ this.suppressAutoSave = true;
973
+ try {
974
+ const base = this.baselineGraph();
975
+ if (graphHasPersistedDesignerLayout(base ?? undefined)) {
976
+ this.layoutArrangedFlag.set(true);
977
+ this.recomputeDirty();
978
+ if (this.isDirty()) {
979
+ await this.handleSaveExecute({ silent: true });
980
+ }
981
+ return;
982
+ }
983
+ this.applyArrangedLayout();
984
+ if (this.isDirty()) {
985
+ await this.handleSaveExecute({ silent: true });
986
+ }
987
+ }
988
+ finally {
989
+ this.suppressAutoSave = false;
990
+ this.initialLayoutArrangeInFlight = false;
991
+ }
992
+ }
993
+ applyBaselineGraph() {
994
+ this.clearAutoSaveTimer();
995
+ this.suppressAutoSave = true;
996
+ try {
997
+ const base = this.baselineGraph();
998
+ this.layoutArrangedFlag.set(isDesignerLayoutArranged(base ?? undefined));
999
+ this.initDesignerLayoutFromGraph(base ?? undefined);
1000
+ const rows = (base?.activities ?? []).map((a) => rowFromInstance(a));
1001
+ this.activities.set(rows);
1002
+ this.connections.set(cloneDeep(base?.connections ?? []));
1003
+ let start = base?.startActivityId ?? '';
1004
+ if (!start && rows.length > 0) {
1005
+ start = rows[0].id;
1006
+ }
1007
+ this.startActivityId.set(start);
1008
+ this.selectedRowId.set(rows[0]?.id ?? null);
1009
+ this.isDirty.set(false);
1010
+ for (const r of rows) {
1011
+ void this.ensureDefinition(r.name);
1012
+ }
1013
+ void this.refreshPropertyViewer();
1014
+ this.recompute();
1015
+ }
1016
+ finally {
1017
+ this.suppressAutoSave = false;
1018
+ }
1019
+ }
1020
+ addStep() {
1021
+ const catalog = this.activitySelectOptions();
1022
+ const defaultName = catalog[0]?.value ?? '';
1023
+ const row = { id: AXPDataGenerator.uuid(), name: defaultName, inputs: {} };
1024
+ this.activities.update((list) => [...list, row]);
1025
+ const idx = this.activities().length - 1;
1026
+ const p = this.gridFallbackPosition(idx);
1027
+ this.designerLayout.update((L) => ({
1028
+ ...L,
1029
+ [row.id]: { x: p.x, y: p.y, width: DEFAULT_NODE_W, height: DEFAULT_NODE_H },
1030
+ }));
1031
+ this.selectedRowId.set(row.id);
1032
+ if (!this.startActivityId() && row.id) {
1033
+ this.startActivityId.set(row.id);
1034
+ }
1035
+ void this.ensureDefinition(row.name);
1036
+ void this.refreshPropertyViewer();
1037
+ this.recomputeDirty();
1038
+ }
1039
+ //#endregion
1040
+ //#region ---- Outcomes & labels ----
1041
+ formatActivityStepLabel(r) {
1042
+ const shortId = r.id.length >= 8 ? r.id.slice(0, 8) : r.id;
1043
+ const typePart = r.name?.trim() ? r.name : '…';
1044
+ return `${typePart} (${shortId})`;
1045
+ }
1046
+ resolveNodeTitle(r) {
1047
+ const ext = r.extensions;
1048
+ const display = ext && typeof ext['displayTitle'] === 'string' ? ext['displayTitle'].trim() : '';
1049
+ if (display) {
1050
+ return display;
1051
+ }
1052
+ return this.activitySelectOptions().find((x) => x.value === r.name)?.text ?? r.name;
1053
+ }
1054
+ outcomeRowsFromRawDefinition(raw) {
1055
+ if (raw == null) {
1056
+ return [];
1057
+ }
1058
+ let items = [];
1059
+ if (Array.isArray(raw)) {
1060
+ items = raw;
1061
+ }
1062
+ else if (typeof raw === 'string' && raw.trim().length > 0) {
1063
+ try {
1064
+ const parsed = JSON.parse(raw);
1065
+ items = Array.isArray(parsed) ? parsed : [];
1066
+ }
1067
+ catch {
1068
+ return [];
1069
+ }
1070
+ }
1071
+ else {
1072
+ return [];
1073
+ }
1074
+ const rows = [];
1075
+ for (const item of items) {
1076
+ if (typeof item === 'string' && item.trim()) {
1077
+ rows.push({ port: item, label: item });
1078
+ continue;
1079
+ }
1080
+ if (item != null && typeof item === 'object' && !Array.isArray(item)) {
1081
+ const o = item;
1082
+ const portVal = o['name'] ?? o['value'] ?? o['outcome'] ?? o['port'];
1083
+ if (typeof portVal !== 'string' || !portVal.trim()) {
1084
+ continue;
1085
+ }
1086
+ const titleRaw = o['title'];
1087
+ let label = portVal;
1088
+ if (typeof titleRaw === 'string' && titleRaw.trim()) {
1089
+ label = titleRaw;
1090
+ }
1091
+ else if (titleRaw != null && typeof titleRaw === 'object') {
1092
+ label = this.mlResolver.resolve(titleRaw) ?? portVal;
1093
+ }
1094
+ rows.push({ port: portVal, label });
1095
+ }
1096
+ }
1097
+ return rows;
1098
+ }
1099
+ outcomePortsFromConnections(activityId) {
1100
+ const ports = new Set();
1101
+ for (const c of this.connections()) {
1102
+ if (c.source.activtyName === activityId) {
1103
+ ports.add(portKey(c.source.port));
1104
+ }
1105
+ }
1106
+ return [...ports];
1107
+ }
1108
+ outcomePortsFromTaskActions(inputs) {
1109
+ const actions = inputs['actions'];
1110
+ if (actions == null) {
1111
+ return [];
1112
+ }
1113
+ let root = actions;
1114
+ if (typeof actions === 'string' && actions.trim().length > 0) {
1115
+ try {
1116
+ root = JSON.parse(actions);
1117
+ }
1118
+ catch {
1119
+ return [];
1120
+ }
1121
+ }
1122
+ if (typeof root !== 'object' || root === null) {
1123
+ return [];
1124
+ }
1125
+ const names = [];
1126
+ const obj = root;
1127
+ for (const key of ['suffix', 'prefix']) {
1128
+ const list = obj[key];
1129
+ if (!Array.isArray(list)) {
1130
+ continue;
1131
+ }
1132
+ for (const entry of list) {
1133
+ if (!entry || typeof entry !== 'object') {
1134
+ continue;
1135
+ }
1136
+ const cmd = entry['command'];
1137
+ if (cmd && typeof cmd === 'object') {
1138
+ const n = cmd['name'];
1139
+ if (typeof n === 'string' && n.trim()) {
1140
+ names.push(n);
1141
+ }
1142
+ }
1143
+ }
1144
+ }
1145
+ return names;
1146
+ }
1147
+ buildOutcomeRows(activityId, row, def) {
1148
+ const map = new Map();
1149
+ for (const o of this.outcomeRowsFromRawDefinition(def?.outcomes)) {
1150
+ map.set(o.port, o);
1151
+ }
1152
+ for (const p of this.outcomePortsFromConnections(activityId)) {
1153
+ if (!map.has(p)) {
1154
+ map.set(p, { port: p, label: p });
1155
+ }
1156
+ }
1157
+ if (row) {
1158
+ for (const p of this.outcomePortsFromTaskActions(row.inputs)) {
1159
+ if (!map.has(p)) {
1160
+ map.set(p, { port: p, label: p });
1161
+ }
1162
+ }
1163
+ }
1164
+ if (map.size === 0) {
1165
+ map.set('Done', { port: 'Done', label: 'Done' });
1166
+ }
1167
+ return [...map.values()].sort((a, b) => a.port.localeCompare(b.port));
1168
+ }
1169
+ pruneOutgoingConnections(sourceActivityId, allowedPorts) {
1170
+ this.connections.update((list) => list.filter((c) => {
1171
+ if (c.source.activtyName !== sourceActivityId) {
1172
+ return true;
1173
+ }
1174
+ return allowedPorts.has(portKey(c.source.port));
1175
+ }));
1176
+ }
1177
+ //#endregion
1178
+ //#region ---- Catalog & property viewer ----
1179
+ async ensureActivityCatalogLoaded() {
1180
+ if (this.activityCatalogLoaded()) {
1181
+ return;
1182
+ }
1183
+ try {
1184
+ const data = this.entityService
1185
+ .withEntity(RootConfig.module.name, RootConfig.entities.activityDefinition.name)
1186
+ .data();
1187
+ const res = (await data.query({ skip: 0, take: 1000 }));
1188
+ const items = (res.items ?? [])
1189
+ .map((row) => {
1190
+ const n = row.name;
1191
+ const typeFallback = row.type;
1192
+ const valueKey = typeof n === 'string' && n.trim()
1193
+ ? n.trim()
1194
+ : typeof n === 'number'
1195
+ ? String(n)
1196
+ : typeof typeFallback === 'string' && typeFallback.trim()
1197
+ ? typeFallback.trim()
1198
+ : typeof typeFallback === 'number'
1199
+ ? String(typeFallback)
1200
+ : '';
1201
+ if (!valueKey) {
1202
+ return null;
1203
+ }
1204
+ const titleRaw = row.title;
1205
+ let text = valueKey;
1206
+ if (typeof titleRaw === 'string' && titleRaw.trim()) {
1207
+ text = titleRaw.trim();
1208
+ }
1209
+ else if (titleRaw != null && typeof titleRaw === 'object') {
1210
+ text = this.mlResolver.resolve(titleRaw) ?? valueKey;
1211
+ }
1212
+ const descriptionRaw = row.description;
1213
+ let description = descriptionRaw;
1214
+ if (typeof descriptionRaw === 'string' && descriptionRaw.trim()) {
1215
+ description = descriptionRaw.trim();
1216
+ }
1217
+ else if (descriptionRaw != null && typeof descriptionRaw === 'object') {
1218
+ description = this.mlResolver.resolve(descriptionRaw) ?? descriptionRaw;
1219
+ }
1220
+ const categoryRaw = row.category;
1221
+ const categoryTitleResolved = categoryRaw?.title != null
1222
+ ? (this.mlResolver.resolve(categoryRaw.title) ?? categoryRaw.name)
1223
+ : 'Uncategorized';
1224
+ const icon = row.icon;
1225
+ return {
1226
+ value: valueKey,
1227
+ text: String(text).trim() || valueKey,
1228
+ description: description,
1229
+ categoryId: categoryRaw?.id ?? 'uncategorized',
1230
+ categoryTitle: categoryTitleResolved,
1231
+ icon: icon,
1232
+ };
1233
+ })
1234
+ .filter((x) => x != null);
1235
+ items.sort((a, b) => a.text.localeCompare(b.text));
1236
+ this.activitySelectItems.set(items);
1237
+ }
1238
+ catch {
1239
+ this.activitySelectItems.set([]);
1240
+ }
1241
+ finally {
1242
+ this.activityCatalogLoaded.set(true);
1243
+ }
1244
+ }
1245
+ async ensureDefinition(name) {
1246
+ if (!name?.trim()) {
1247
+ return;
1248
+ }
1249
+ if (this.activityDefCache()[name]) {
1250
+ return;
1251
+ }
1252
+ const def = await this.activityDefService.getActivityByName(name);
1253
+ if (def) {
1254
+ this.activityDefCache.update((c) => ({ ...c, [name]: def }));
1255
+ }
1256
+ }
1257
+ async refreshPropertyViewer() {
1258
+ const row = this.selectedRow();
1259
+ if (row == null || row.name.trim() === '') {
1260
+ this.viewerTabs.set([]);
1261
+ this.selectedActivityOutcomeRows.set([]);
1262
+ setTimeout(() => this.propertyViewerRef()?.initializeContext({ inputs: {} }), 0);
1263
+ return;
1264
+ }
1265
+ const def = await this.activityDefService.getActivityByName(row.name);
1266
+ if (def) {
1267
+ this.activityDefCache.update((c) => ({ ...c, [row.name]: def }));
1268
+ }
1269
+ const rowLatest = this.activities().find((r) => r.id === row.id) ?? row;
1270
+ this.selectedActivityOutcomeRows.set(this.buildOutcomeRows(row.id, rowLatest, def));
1271
+ const inputProps = normalizeActivityDefinitionInputs(def?.inputs);
1272
+ const group = { name: 'activity-inputs', title: 'Inputs', order: 0 };
1273
+ const widgetProps = inputProps.map((p, index) => mapAXPPropertyToWidgetProperty(p, {
1274
+ group,
1275
+ order: index,
1276
+ valuePathPrefix: 'inputs',
1277
+ resolveTitle: (prop) => typeof prop.title === 'string' ? prop.title : (this.mlResolver.resolve(prop.title) ?? prop.name),
1278
+ resolveDescription: (prop) => prop.description === undefined
1279
+ ? undefined
1280
+ : typeof prop.description === 'string'
1281
+ ? prop.description
1282
+ : this.mlResolver.resolve(prop.description),
1283
+ }));
1284
+ this.viewerTabs.set(buildPropertyViewerTabsFromProperties(widgetProps));
1285
+ setTimeout(() => {
1286
+ const current = this.activities().find((r) => r.id === row.id);
1287
+ this.propertyViewerRef()?.initializeContext({ inputs: cloneDeep(current?.inputs ?? {}) });
1288
+ }, 0);
1289
+ }
1290
+ //#endregion
1291
+ //#region ---- Utilities ----
1292
+ recompute() {
1293
+ super.recompute();
1294
+ const maybeLayout = this.hostPageLayout;
1295
+ maybeLayout?.recompute?.();
1296
+ }
1297
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkflowDefinitionActivitiesPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1298
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMWorkflowDefinitionActivitiesPageComponent, isStandalone: true, selector: "axm-workflow-definition-activities-page", inputs: { rootContext: { classPropertyName: "rootContext", publicName: "rootContext", isSignal: true, isRequired: false, transformFunction: null }, pageConfig: { classPropertyName: "pageConfig", publicName: "pageConfig", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: block; width: 100%; height: 100%;" }, providers: [{ provide: AXPPageLayoutBase, useExisting: AXMWorkflowDefinitionActivitiesPageComponent }], viewQueries: [{ propertyName: "propertyViewerRef", first: true, predicate: AXPPropertyViewerComponent, descendants: true, isSignal: true }, { propertyName: "workflowDesignerRef", first: true, predicate: AXPWorkflowDesignerComponent, descendants: true, isSignal: true }, { propertyName: "contextMenu", first: true, predicate: AXContextMenuComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- <axp-page-toolbar>\n <axp-layout-suffix>\n <div class=\"axm-workflow-definition-activities__toolbar-group\">\n <ax-button>\n <ax-icon icon=\"fa-light fa-sliders\"></ax-icon>\n <ax-dropdown-panel>\n <div class=\"axm-workflow-definition-activities__appearance-panel\">\n <label class=\"axm-workflow-definition-activities__pattern-label\" for=\"background-pattern-select\"\n >Background Pattern</label\n >\n <select\n id=\"background-pattern-select\"\n class=\"axm-workflow-definition-activities__pattern-select\"\n [value]=\"backgroundPattern()\"\n (change)=\"onBackgroundPatternChange($event)\"\n >\n <option value=\"dots\">Dots</option>\n <option value=\"line\">Lines</option>\n </select>\n </div>\n </ax-dropdown-panel>\n </ax-button>\n <ax-button (onClick)=\"toggleFullscreen()\">\n <ax-icon>\n <i class=\"fa-solid\" [class]=\"isFullscreen() ? 'fa-compress' : 'fa-expand'\"></i>\n </ax-icon>\n </ax-button>\n <ax-button (onClick)=\"toggleInfoPanel()\">\n <ax-icon [icon]=\"isInfoPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info'\"></ax-icon>\n </ax-button>\n </div>\n </axp-layout-suffix>\n </axp-page-toolbar> -->\n\n<div\n class=\"axm-workflow-definition-activities\"\n [class.axm-workflow-definition-activities--with-palette]=\"isPaletteOpen()\"\n [class.axm-workflow-definition-activities--with-info]=\"isInfoPanelOpen()\"\n>\n @if (isPaletteOpen()) {\n <aside class=\"axm-workflow-definition-activities__palette\">\n <div class=\"axm-workflow-definition-activities__palette-head\">\n <div class=\"axm-workflow-definition-activities__palette-head-row\">\n <h3 class=\"axm-workflow-definition-activities__title\">\n {{\n ('@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.add-step'\n | translate\n | async) ?? 'Activities'\n }}\n </h3>\n <ax-button [look]=\"'blank'\" class=\"ax-sm rounded-full\" (onClick)=\"closePalette()\">\n <ax-icon icon=\"fa-solid fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n <p class=\"axm-workflow-definition-activities__palette-sub\">\n {{\n ('@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.connections.hint'\n | translate\n | async) ?? ''\n }}\n </p>\n <ax-search-box\n class=\"axm-workflow-definition-activities__palette-search ax-sm\"\n [value]=\"paletteSearchTerm()\"\n (onValueChanged)=\"onPaletteSearchChange($event)\"\n [placeholder]=\"'@general:search.title' | translate | async\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n <div class=\"axm-workflow-definition-activities__palette-list\">\n <div class=\"axm-workflow-definition-activities__accordion-group\" axAccordionGroup [accordion]=\"false\">\n @for (group of filteredPaletteGroups(); track group.id) {\n @if (group.items.length > 0) {\n <section\n class=\"axm-workflow-definition-activities__accordion-item\"\n axAccordionItem\n [isCollapsed]=\"false\"\n #acc=\"axAccordionItem\"\n >\n <header\n class=\"axm-workflow-definition-activities__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n >\n <div class=\"axm-workflow-definition-activities__accordion-header-main\">\n <span class=\"axm-workflow-definition-activities__accordion-title\">{{ group.title }}</span>\n </div>\n <span class=\"axm-workflow-definition-activities__accordion-chevron\">\n <i [class]=\"acc.isCollapsed() ? 'fa-light fa-chevron-down' : 'fa-light fa-chevron-up'\"></i>\n </span>\n </header>\n <div class=\"axm-workflow-definition-activities__accordion-content\" axAccordionItemContent>\n @for (item of group.items; track item.type) {\n <button\n type=\"button\"\n class=\"axm-workflow-definition-activities__palette-item\"\n [axpWorkflowPaletteItem]=\"item\"\n >\n <span class=\"axm-workflow-definition-activities__palette-item-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-light ' + item.icon\"></i>\n </span>\n <span class=\"axm-workflow-definition-activities__palette-item-body\">\n <span class=\"axm-workflow-definition-activities__palette-item-title\">{{ item.title }}</span>\n <span class=\"axm-workflow-definition-activities__palette-item-meta\">{{\n item.description\n }}</span>\n </span>\n </button>\n }\n </div>\n </section>\n }\n }\n </div>\n </div>\n </aside>\n }\n\n <div class=\"axm-workflow-definition-activities__main\">\n <section class=\"axm-workflow-definition-activities__canvas\" (contextmenu)=\"onDesignerSurfaceContextMenu($event)\">\n <axp-workflow-designer\n [model]=\"designerModel()\"\n [backgroundPattern]=\"backgroundPattern()\"\n (zoomChange)=\"onDesignerZoomChange($event)\"\n (modelChange)=\"onDesignerModelChange($event)\"\n (activationChange)=\"onDesignerActivationChange($event)\"\n (nodeContextMenu)=\"onDesignerNodeContextMenu($event)\"\n ></axp-workflow-designer>\n <ax-context-menu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleWorkflowContextMenuItemClick($event)\"\n />\n <axp-layout-floating-zoom-bar\n [zoomLevel]=\"zoomLevel()\"\n (zoomIn)=\"zoomIn()\"\n (zoomOut)=\"zoomOut()\"\n (zoomReset)=\"zoomReset()\"\n />\n </section>\n </div>\n @if (isInfoPanelOpen()) {\n <axp-layout-side-detail-panel\n class=\"axm-workflow-definition-activities__info sticky top-0 z-10 max-h-full flex-none\"\n [header]=\"workflowDetailPanelHeader()\"\n [rows]=\"workflowDetailPanelRows()\"\n [emptyState]=\"workflowDetailPanelEmptyState()\"\n (panelClose)=\"toggleInfoPanel()\"\n />\n }\n</div>\n", styles: ["@layer properties;.axm-workflow-definition-activities{display:grid;height:100%;align-items:stretch;grid-template-columns:minmax(0,1fr);gap:.75rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette{display:flex;min-height:0px;flex-direction:column;gap:.75rem;padding:.5rem;border-radius:16px}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-head{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-head-row{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-sub{margin:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));line-height:1.35;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-search{width:100%}.axm-workflow-definition-activities .axm-workflow-definition-activities__main{display:flex;min-height:0px;min-width:0px;flex-direction:column;gap:.75rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__toolbar{display:flex;justify-content:flex-end}.axm-workflow-definition-activities .axm-workflow-definition-activities__toolbar-group{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.axm-workflow-definition-activities .axm-workflow-definition-activities__appearance-panel{display:flex;flex-direction:column;gap:.75rem;min-width:220px;padding:.35rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__zoom-actions{display:flex;align-items:center;gap:.4rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__pattern-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__pattern-select{min-height:34px;border-radius:8px;border:1px solid rgb(var(--ax-sys-color-border-surface));background:rgb(var(--ax-sys-color-surface));color:var(--ax-sys-color-on-surface);padding:0 .5rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__canvas{position:relative;min-height:0px;flex:auto;overflow:hidden;min-height:min(70vh,720px);border-radius:16px;background:var(--ax-sys-color-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__canvas axp-axm-workflow-designer{display:block;height:100%;width:100%;min-height:inherit}.axm-workflow-definition-activities .axm-workflow-definition-activities__title{margin:0;--tw-font-weight: var(--font-weight-bold, 700);font-weight:var(--font-weight-bold, 700);font-size:.9375rem;letter-spacing:-.01em;color:var(--ax-sys-color-on-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-list{display:flex;flex-direction:column;overflow:auto;gap:.45rem;padding-inline-end:2px;margin-inline-end:-2px}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-group{display:flex;flex-direction:column;gap:.45rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-item{overflow:hidden;border-radius:var(--radius-xl, .75rem);transition:border-color .15s ease}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-header{display:flex;cursor:pointer;align-items:center;justify-content:space-between;-webkit-user-select:none;user-select:none;gap:.5rem;padding:.62rem .7rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-header-main{display:inline-flex;min-width:0px;align-items:center;gap:.45rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-bold, 700);font-weight:var(--font-weight-bold, 700);line-height:1.25;color:var(--ax-sys-color-on-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-content{display:flex;flex-direction:column;gap:.4rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-chevron{font-size:.8rem;--tw-leading: 1;line-height:1;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item{position:relative;display:flex;width:100%;cursor:grab;align-items:center;text-align:left;gap:.65rem;padding:.4rem .55rem;border-radius:12px;color:var(--ax-sys-color-on-surface);font:inherit;transition:border-color .15s ease}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item:hover{background-color:rgb(var(--ax-sys-color-primary-50))}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item:active{cursor:grabbing;background-color:rgb(var(--ax-sys-color-primary-100))}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-icon{display:flex;flex-shrink:0;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));width:2.25rem;height:2.25rem;border-radius:10px;color:rgb(var(--ax-sys-color-primary-600))}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:.1rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);line-height:1.25}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-size:.6875rem;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-grip{flex-shrink:0;font-size:.85rem;opacity:35%;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__info{min-height:0px}@media(max-width:1100px){.axm-workflow-definition-activities{grid-template-columns:1fr;min-height:auto}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette{max-height:280px}.axm-workflow-definition-activities .axm-workflow-definition-activities__canvas{min-height:480px}.axm-workflow-definition-activities .axm-workflow-definition-activities__info{max-height:280px}}.axm-workflow-definition-activities--with-palette{grid-template-columns:minmax(260px,300px) minmax(0,1fr)}.axm-workflow-definition-activities--with-info:not(.axm-workflow-definition-activities--with-palette){grid-template-columns:minmax(0,1fr) minmax(260px,320px)}.axm-workflow-definition-activities--with-palette.axm-axm-workflow-definition-activities--with-info{grid-template-columns:minmax(260px,300px) minmax(0,1fr) minmax(260px,320px)}.axm-workflow-definition-activities--fullscreen{position:fixed;z-index:400;box-sizing:border-box;inset:0;height:100vh;background:rgb(var(--ax-sys-color-lightest-surface));padding:.75rem}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: AXAccordionCdkModule }, { kind: "directive", type: i1.AXAccordionGroupDirective, selector: "[axAccordionGroup]", inputs: ["accordion", "activeIndex", "collapsedOnItemClick"], exportAs: ["axAccordionGroup"] }, { kind: "directive", type: i1.AXAccordionItemContentDirective, selector: "[axAccordionItemContent]", inputs: ["transition"], exportAs: ["axAccordionItemContent"] }, { kind: "directive", type: i1.AXAccordionItemHeaderDirective, selector: "[axAccordionItemHeader]", exportAs: ["axAccordionItemHeader"] }, { kind: "directive", type: i1.AXAccordionItemDirective, selector: "[axAccordionItem]", inputs: ["isCollapsed"], outputs: ["isCollapsedChange", "onClick"], exportAs: ["axAccordionItem"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXMenuModule }, { kind: "component", type: i3.AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i4.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i5.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLayoutFloatingZoomBarComponent, selector: "axp-layout-floating-zoom-bar", inputs: ["zoomLevel"], outputs: ["zoomIn", "zoomOut", "zoomReset"] }, { kind: "component", type: AXPLayoutSideDetailPanelComponent, selector: "axp-layout-side-detail-panel", inputs: ["multiSelectLabel", "header", "sections", "rows", "rowsSectionTitle", "noRowsMessage", "emptyState"], outputs: ["panelClose"] }, { kind: "component", type: AXPWorkflowDesignerComponent, selector: "axp-workflow-designer", inputs: ["model", "readonly", "highlightedNodeIds", "gridSize", "snapToGrid", "connectionPreviewStyle", "backgroundPattern", "canConnect", "paletteItems", "showPortLabels", "nodeBodyTemplate"], outputs: ["modelChange", "zoomChange", "designerPointerDown", "designerClick", "designerDoubleClick", "nodePointerDown", "nodeClick", "nodeDoubleClick", "nodeContextMenu", "nodeDragStart", "nodeDragEnd", "portPointerDown", "linkDragStart", "linkDragMove", "linkDragEnd", "connectorClick", "connectorDoubleClick", "connectionCreated", "connectionRejected", "activationChange"] }, { kind: "directive", type: AXPWorkflowPaletteItemDragDirective, selector: "[axpWorkflowPaletteItem]", inputs: ["axpWorkflowPaletteItem", "axpWorkflowPaletteDragDisabled"], outputs: ["axpWorkflowPaletteDragStart", "axpWorkflowPaletteDragEnd"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i7.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1299
+ }
1300
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMWorkflowDefinitionActivitiesPageComponent, decorators: [{
1301
+ type: Component,
1302
+ args: [{ selector: 'axm-workflow-definition-activities-page', imports: [
1303
+ CommonModule,
1304
+ FormsModule,
1305
+ AXAccordionCdkModule,
1306
+ AXButtonModule,
1307
+ AXMenuModule,
1308
+ AXDecoratorModule,
1309
+ AXDropdownModule,
1310
+ AXFormModule,
1311
+ AXSearchBoxModule,
1312
+ AXSelectBoxModule,
1313
+ AXTranslationModule,
1314
+ AXPLayoutFloatingZoomBarComponent,
1315
+ AXPLayoutSideDetailPanelComponent,
1316
+ AXPWorkflowDesignerComponent,
1317
+ AXPWorkflowPaletteItemDragDirective,
1318
+ ], host: {
1319
+ style: 'display: block; width: 100%; height: 100%;',
1320
+ }, changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: AXPPageLayoutBase, useExisting: AXMWorkflowDefinitionActivitiesPageComponent }], template: "<!-- <axp-page-toolbar>\n <axp-layout-suffix>\n <div class=\"axm-workflow-definition-activities__toolbar-group\">\n <ax-button>\n <ax-icon icon=\"fa-light fa-sliders\"></ax-icon>\n <ax-dropdown-panel>\n <div class=\"axm-workflow-definition-activities__appearance-panel\">\n <label class=\"axm-workflow-definition-activities__pattern-label\" for=\"background-pattern-select\"\n >Background Pattern</label\n >\n <select\n id=\"background-pattern-select\"\n class=\"axm-workflow-definition-activities__pattern-select\"\n [value]=\"backgroundPattern()\"\n (change)=\"onBackgroundPatternChange($event)\"\n >\n <option value=\"dots\">Dots</option>\n <option value=\"line\">Lines</option>\n </select>\n </div>\n </ax-dropdown-panel>\n </ax-button>\n <ax-button (onClick)=\"toggleFullscreen()\">\n <ax-icon>\n <i class=\"fa-solid\" [class]=\"isFullscreen() ? 'fa-compress' : 'fa-expand'\"></i>\n </ax-icon>\n </ax-button>\n <ax-button (onClick)=\"toggleInfoPanel()\">\n <ax-icon [icon]=\"isInfoPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info'\"></ax-icon>\n </ax-button>\n </div>\n </axp-layout-suffix>\n </axp-page-toolbar> -->\n\n<div\n class=\"axm-workflow-definition-activities\"\n [class.axm-workflow-definition-activities--with-palette]=\"isPaletteOpen()\"\n [class.axm-workflow-definition-activities--with-info]=\"isInfoPanelOpen()\"\n>\n @if (isPaletteOpen()) {\n <aside class=\"axm-workflow-definition-activities__palette\">\n <div class=\"axm-workflow-definition-activities__palette-head\">\n <div class=\"axm-workflow-definition-activities__palette-head-row\">\n <h3 class=\"axm-workflow-definition-activities__title\">\n {{\n ('@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.add-step'\n | translate\n | async) ?? 'Activities'\n }}\n </h3>\n <ax-button [look]=\"'blank'\" class=\"ax-sm rounded-full\" (onClick)=\"closePalette()\">\n <ax-icon icon=\"fa-solid fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n <p class=\"axm-workflow-definition-activities__palette-sub\">\n {{\n ('@workflow-management:workflow-definitions.entities.workflow-definition.pages.activities.connections.hint'\n | translate\n | async) ?? ''\n }}\n </p>\n <ax-search-box\n class=\"axm-workflow-definition-activities__palette-search ax-sm\"\n [value]=\"paletteSearchTerm()\"\n (onValueChanged)=\"onPaletteSearchChange($event)\"\n [placeholder]=\"'@general:search.title' | translate | async\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n <div class=\"axm-workflow-definition-activities__palette-list\">\n <div class=\"axm-workflow-definition-activities__accordion-group\" axAccordionGroup [accordion]=\"false\">\n @for (group of filteredPaletteGroups(); track group.id) {\n @if (group.items.length > 0) {\n <section\n class=\"axm-workflow-definition-activities__accordion-item\"\n axAccordionItem\n [isCollapsed]=\"false\"\n #acc=\"axAccordionItem\"\n >\n <header\n class=\"axm-workflow-definition-activities__accordion-header\"\n axAccordionItemHeader\n role=\"button\"\n >\n <div class=\"axm-workflow-definition-activities__accordion-header-main\">\n <span class=\"axm-workflow-definition-activities__accordion-title\">{{ group.title }}</span>\n </div>\n <span class=\"axm-workflow-definition-activities__accordion-chevron\">\n <i [class]=\"acc.isCollapsed() ? 'fa-light fa-chevron-down' : 'fa-light fa-chevron-up'\"></i>\n </span>\n </header>\n <div class=\"axm-workflow-definition-activities__accordion-content\" axAccordionItemContent>\n @for (item of group.items; track item.type) {\n <button\n type=\"button\"\n class=\"axm-workflow-definition-activities__palette-item\"\n [axpWorkflowPaletteItem]=\"item\"\n >\n <span class=\"axm-workflow-definition-activities__palette-item-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-light ' + item.icon\"></i>\n </span>\n <span class=\"axm-workflow-definition-activities__palette-item-body\">\n <span class=\"axm-workflow-definition-activities__palette-item-title\">{{ item.title }}</span>\n <span class=\"axm-workflow-definition-activities__palette-item-meta\">{{\n item.description\n }}</span>\n </span>\n </button>\n }\n </div>\n </section>\n }\n }\n </div>\n </div>\n </aside>\n }\n\n <div class=\"axm-workflow-definition-activities__main\">\n <section class=\"axm-workflow-definition-activities__canvas\" (contextmenu)=\"onDesignerSurfaceContextMenu($event)\">\n <axp-workflow-designer\n [model]=\"designerModel()\"\n [backgroundPattern]=\"backgroundPattern()\"\n (zoomChange)=\"onDesignerZoomChange($event)\"\n (modelChange)=\"onDesignerModelChange($event)\"\n (activationChange)=\"onDesignerActivationChange($event)\"\n (nodeContextMenu)=\"onDesignerNodeContextMenu($event)\"\n ></axp-workflow-designer>\n <ax-context-menu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleWorkflowContextMenuItemClick($event)\"\n />\n <axp-layout-floating-zoom-bar\n [zoomLevel]=\"zoomLevel()\"\n (zoomIn)=\"zoomIn()\"\n (zoomOut)=\"zoomOut()\"\n (zoomReset)=\"zoomReset()\"\n />\n </section>\n </div>\n @if (isInfoPanelOpen()) {\n <axp-layout-side-detail-panel\n class=\"axm-workflow-definition-activities__info sticky top-0 z-10 max-h-full flex-none\"\n [header]=\"workflowDetailPanelHeader()\"\n [rows]=\"workflowDetailPanelRows()\"\n [emptyState]=\"workflowDetailPanelEmptyState()\"\n (panelClose)=\"toggleInfoPanel()\"\n />\n }\n</div>\n", styles: ["@layer properties;.axm-workflow-definition-activities{display:grid;height:100%;align-items:stretch;grid-template-columns:minmax(0,1fr);gap:.75rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette{display:flex;min-height:0px;flex-direction:column;gap:.75rem;padding:.5rem;border-radius:16px}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-head{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-head-row{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-sub{margin:0;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));line-height:1.35;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-search{width:100%}.axm-workflow-definition-activities .axm-workflow-definition-activities__main{display:flex;min-height:0px;min-width:0px;flex-direction:column;gap:.75rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__toolbar{display:flex;justify-content:flex-end}.axm-workflow-definition-activities .axm-workflow-definition-activities__toolbar-group{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2)}.axm-workflow-definition-activities .axm-workflow-definition-activities__appearance-panel{display:flex;flex-direction:column;gap:.75rem;min-width:220px;padding:.35rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__zoom-actions{display:flex;align-items:center;gap:.4rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__pattern-label{font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__pattern-select{min-height:34px;border-radius:8px;border:1px solid rgb(var(--ax-sys-color-border-surface));background:rgb(var(--ax-sys-color-surface));color:var(--ax-sys-color-on-surface);padding:0 .5rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__canvas{position:relative;min-height:0px;flex:auto;overflow:hidden;min-height:min(70vh,720px);border-radius:16px;background:var(--ax-sys-color-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__canvas axp-axm-workflow-designer{display:block;height:100%;width:100%;min-height:inherit}.axm-workflow-definition-activities .axm-workflow-definition-activities__title{margin:0;--tw-font-weight: var(--font-weight-bold, 700);font-weight:var(--font-weight-bold, 700);font-size:.9375rem;letter-spacing:-.01em;color:var(--ax-sys-color-on-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-list{display:flex;flex-direction:column;overflow:auto;gap:.45rem;padding-inline-end:2px;margin-inline-end:-2px}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-group{display:flex;flex-direction:column;gap:.45rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-item{overflow:hidden;border-radius:var(--radius-xl, .75rem);transition:border-color .15s ease}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-header{display:flex;cursor:pointer;align-items:center;justify-content:space-between;-webkit-user-select:none;user-select:none;gap:.5rem;padding:.62rem .7rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-header-main{display:inline-flex;min-width:0px;align-items:center;gap:.45rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-title{font-size:.8125rem;--tw-font-weight: var(--font-weight-bold, 700);font-weight:var(--font-weight-bold, 700);line-height:1.25;color:var(--ax-sys-color-on-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-content{display:flex;flex-direction:column;gap:.4rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__accordion-chevron{font-size:.8rem;--tw-leading: 1;line-height:1;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item{position:relative;display:flex;width:100%;cursor:grab;align-items:center;text-align:left;gap:.65rem;padding:.4rem .55rem;border-radius:12px;color:var(--ax-sys-color-on-surface);font:inherit;transition:border-color .15s ease}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item:hover{background-color:rgb(var(--ax-sys-color-primary-50))}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item:active{cursor:grabbing;background-color:rgb(var(--ax-sys-color-primary-100))}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-icon{display:flex;flex-shrink:0;align-items:center;justify-content:center;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));width:2.25rem;height:2.25rem;border-radius:10px;color:rgb(var(--ax-sys-color-primary-600))}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-body{display:flex;min-width:0px;flex:1;flex-direction:column;gap:.1rem}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.8125rem;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);line-height:1.25}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-size:.6875rem;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette-item-grip{flex-shrink:0;font-size:.85rem;opacity:35%;color:var(--ax-sys-color-on-light-surface)}.axm-workflow-definition-activities .axm-workflow-definition-activities__info{min-height:0px}@media(max-width:1100px){.axm-workflow-definition-activities{grid-template-columns:1fr;min-height:auto}.axm-workflow-definition-activities .axm-workflow-definition-activities__palette{max-height:280px}.axm-workflow-definition-activities .axm-workflow-definition-activities__canvas{min-height:480px}.axm-workflow-definition-activities .axm-workflow-definition-activities__info{max-height:280px}}.axm-workflow-definition-activities--with-palette{grid-template-columns:minmax(260px,300px) minmax(0,1fr)}.axm-workflow-definition-activities--with-info:not(.axm-workflow-definition-activities--with-palette){grid-template-columns:minmax(0,1fr) minmax(260px,320px)}.axm-workflow-definition-activities--with-palette.axm-axm-workflow-definition-activities--with-info{grid-template-columns:minmax(260px,300px) minmax(0,1fr) minmax(260px,320px)}.axm-workflow-definition-activities--fullscreen{position:fixed;z-index:400;box-sizing:border-box;inset:0;height:100vh;background:rgb(var(--ax-sys-color-lightest-surface));padding:.75rem}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
1321
+ }], ctorParameters: () => [], propDecorators: { rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], propertyViewerRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPPropertyViewerComponent), { isSignal: true }] }], workflowDesignerRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPWorkflowDesignerComponent), { isSignal: true }] }], contextMenu: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXContextMenuComponent), { isSignal: true }] }] } });
1322
+
1323
+ var workflowDefinitionActivitiesPage_component = /*#__PURE__*/Object.freeze({
1324
+ __proto__: null,
1325
+ AXMWorkflowDefinitionActivitiesPageComponent: AXMWorkflowDefinitionActivitiesPageComponent
1326
+ });
1327
+
1328
+ export { AXMWorkflowDefinitionActivitiesPageComponent, AXMWorkflowDefinitionActivitiesPageComponentProvider, graphHasPersistedDesignerLayout, isDesignerLayoutArranged };
1329
+ //# sourceMappingURL=acorex-platform-module-workflow-management-client-index-DKZTLui4.mjs.map