@parallelworks/ui 0.34.0 → 0.35.0
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.
- package/README.md +201 -0
- package/dist/ai/components/ChatEmptyState.js +71 -86
- package/dist/ai/components/ChatInput.d.ts +11 -3
- package/dist/ai/components/ChatInput.js +19 -11
- package/dist/ai/components/ChatSidebar.js +12 -130
- package/dist/ai/components/ChatStage.d.ts +11 -0
- package/dist/ai/components/ChatStage.js +26 -0
- package/dist/ai/components/ComposerChrome.d.ts +3 -0
- package/dist/ai/components/ComposerChrome.js +21 -2
- package/dist/ai/components/conversationActions.d.ts +23 -0
- package/dist/ai/components/conversationActions.js +108 -0
- package/dist/ai/index.d.ts +4 -3
- package/dist/ai/index.js +6 -5
- package/dist/ai/strings.d.ts +1 -0
- package/dist/ai/strings.js +2 -1
- package/dist/ai/ui/ConversationSidebar.d.ts +3 -2
- package/dist/ai/ui/ConversationSidebar.js +2 -1
- package/dist/ai/ui/sidebar.d.ts +6 -0
- package/dist/ai/ui/sidebar.js +10 -1
- package/dist/components/Dropdown.js +3 -1
- package/dist/components/FilterPill.js +1 -0
- package/dist/components/Provider.d.ts +14 -0
- package/dist/components/Provider.js +14 -3
- package/dist/components/SegmentedControl.d.ts +24 -0
- package/dist/components/SegmentedControl.js +69 -0
- package/dist/editing.d.ts +32 -0
- package/dist/editor/FormCodePanel.js +1 -1
- package/dist/engine.d.ts +3 -0
- package/dist/form/FieldWrapper.js +1 -1
- package/dist/form/Fields/CheckboxGroupField.d.ts +3 -3
- package/dist/form/Fields/CheckboxGroupField.js +10 -4
- package/dist/form/Fields/RadioField.d.ts +5 -3
- package/dist/form/Fields/RadioField.js +25 -17
- package/dist/form/Fields/fieldOption.d.ts +12 -0
- package/dist/form/Fields/fieldOption.js +17 -0
- package/dist/form/Form.d.ts +4 -2
- package/dist/form/Form.js +170 -68
- package/dist/form/FormLayout.d.ts +7 -0
- package/dist/form/FormLayout.js +144 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +1 -1
- package/dist/form/SpecialTypes/FormikCustomInput.js +7 -0
- package/dist/form/Wizard/WizardContainer.d.ts +1 -1
- package/dist/form/Wizard/WizardContainer.js +244 -49
- package/dist/form/Wizard/WizardNavigation.js +4 -4
- package/dist/form/Wizard/WizardStepContent.d.ts +1 -1
- package/dist/form/Wizard/WizardStepContent.js +19 -10
- package/dist/form/Wizard/WizardStepIndicator.js +35 -7
- package/dist/form/Wizard/types.d.ts +19 -6
- package/dist/form/Wizard/useWizardState.d.ts +1 -0
- package/dist/form/Wizard/useWizardState.js +5 -1
- package/dist/form/Wizard/utils.d.ts +7 -0
- package/dist/form/Wizard/utils.js +18 -1
- package/dist/form/index.d.ts +2 -0
- package/dist/form/index.js +4 -2
- package/dist/form/layout.d.ts +50 -0
- package/dist/form/layout.js +125 -0
- package/dist/form/layoutCSS.d.ts +10 -0
- package/dist/form/layoutCSS.js +234 -0
- package/dist/form/lib.d.ts +2 -0
- package/dist/form/lib.js +17 -2
- package/dist/form/types/fieldTypes.d.ts +8 -23
- package/dist/graph/DependencyGraph.d.ts +20 -1
- package/dist/graph/DependencyGraph.js +437 -142
- package/dist/graph/MatrixGroup.d.ts +3 -1
- package/dist/graph/MatrixGroup.js +31 -28
- package/dist/graph/TreeView.js +6 -6
- package/dist/graph/gridSpacing.d.ts +7 -0
- package/dist/graph/gridSpacing.js +10 -0
- package/dist/graph/util.d.ts +2 -0
- package/dist/graph/util.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/list/ListViewControls.d.ts +15 -0
- package/dist/list/ListViewControls.js +9 -3
- package/dist/list/index.d.ts +1 -1
- package/dist/list/index.js +2 -2
- package/dist/styles/base.css +3 -1
- package/dist/styles/theme.css +5 -0
- package/dist/styles.css +1 -1
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.js +3 -2
- package/package.json +4 -2
- package/dist/ai/components/ComposerFrame.d.ts +0 -16
- package/dist/ai/components/ComposerFrame.js +0 -33
|
@@ -2,14 +2,21 @@ import { useRunFile, useSlots, useStrings, useWorkflowEngine } from "../componen
|
|
|
2
2
|
import { FaArrowLeft } from "../icons/fa/FaArrowLeft.js";
|
|
3
3
|
import { FaArrowRight } from "../icons/fa/FaArrowRight.js";
|
|
4
4
|
import { IoDocumentTextOutline } from "../icons/io5/IoDocumentTextOutline.js";
|
|
5
|
+
import { LuChevronLeft } from "../icons/lu/LuChevronLeft.js";
|
|
6
|
+
import { LuChevronRight } from "../icons/lu/LuChevronRight.js";
|
|
7
|
+
import { LuZoomIn } from "../icons/lu/LuZoomIn.js";
|
|
8
|
+
import { LuZoomOut } from "../icons/lu/LuZoomOut.js";
|
|
5
9
|
import { TooltipInfo } from "../components/Tooltip.js";
|
|
6
10
|
import { BareModal, modalPanelClasses } from "../components/BareModal.js";
|
|
11
|
+
import { IconButton } from "../components/IconButton.js";
|
|
7
12
|
import { Indicator } from "../components/Indicator.js";
|
|
8
13
|
import Loader from "../components/Loader.js";
|
|
9
14
|
import { LogViewer } from "../logviewer/LogViewer.js";
|
|
10
15
|
import { toAbsHumanDuration } from "../duration.js";
|
|
16
|
+
import { initializeValues } from "../form/lib.js";
|
|
11
17
|
import { AnnotationBanner } from "./AnnotationBanner.js";
|
|
12
18
|
import { Collapse } from "./Collapse.js";
|
|
19
|
+
import { emptyColumnsStyle, emptyRowsStyle } from "./gridSpacing.js";
|
|
13
20
|
import { Reveal } from "./Reveal.js";
|
|
14
21
|
import { jobLabel, toggled } from "./util.js";
|
|
15
22
|
import { Joblist } from "./JobSummary.js";
|
|
@@ -39,6 +46,65 @@ function ViewToggle({ viewMode, setViewMode }) {
|
|
|
39
46
|
})]
|
|
40
47
|
});
|
|
41
48
|
}
|
|
49
|
+
var VIEW_BAR = "flex max-w-full flex-wrap items-center justify-end gap-0.5 rounded-md border theme-border bg-(--theme-panel-bg) p-0.5";
|
|
50
|
+
/** The graph's view buttons, the same wherever a graph is drawn. */
|
|
51
|
+
function GraphViewControls({ history, expand, onReset, onZoom, zoomedAll }) {
|
|
52
|
+
const { dag } = useStrings();
|
|
53
|
+
const chip = "flex h-7 cursor-pointer items-center whitespace-nowrap rounded px-2 text-xs theme-hover";
|
|
54
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
55
|
+
className: VIEW_BAR,
|
|
56
|
+
children: [
|
|
57
|
+
history && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
58
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
59
|
+
icon: /* @__PURE__ */ jsx(LuChevronLeft, { className: "h-4 w-4" }),
|
|
60
|
+
label: dag.previousGraph,
|
|
61
|
+
size: "sm",
|
|
62
|
+
variant: "ghost",
|
|
63
|
+
disabled: !history.back,
|
|
64
|
+
onClick: history.back
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
67
|
+
icon: /* @__PURE__ */ jsx(LuChevronRight, { className: "h-4 w-4" }),
|
|
68
|
+
label: dag.nextGraph,
|
|
69
|
+
size: "sm",
|
|
70
|
+
variant: "ghost",
|
|
71
|
+
disabled: !history.forward,
|
|
72
|
+
onClick: history.forward
|
|
73
|
+
}),
|
|
74
|
+
/* @__PURE__ */ jsx("div", { className: "mx-0.5 h-5 w-px bg-(--theme-border)" })
|
|
75
|
+
] }),
|
|
76
|
+
expand && /* @__PURE__ */ jsx("button", {
|
|
77
|
+
type: "button",
|
|
78
|
+
className: chip,
|
|
79
|
+
onClick: expand.onClick,
|
|
80
|
+
children: expand.label
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ jsx("button", {
|
|
83
|
+
type: "button",
|
|
84
|
+
className: chip,
|
|
85
|
+
onClick: onReset,
|
|
86
|
+
children: dag.resetView
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ jsx("div", { className: "mx-0.5 h-5 w-px bg-(--theme-border)" }),
|
|
89
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
90
|
+
icon: /* @__PURE__ */ jsx(LuZoomOut, { className: "h-4 w-4" }),
|
|
91
|
+
label: dag.zoomOut,
|
|
92
|
+
size: "sm",
|
|
93
|
+
variant: "ghost",
|
|
94
|
+
disabled: zoomedAll === "out",
|
|
95
|
+
onClick: () => onZoom(-1)
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
98
|
+
icon: /* @__PURE__ */ jsx(LuZoomIn, { className: "h-4 w-4" }),
|
|
99
|
+
label: dag.zoomIn,
|
|
100
|
+
size: "sm",
|
|
101
|
+
variant: "ghost",
|
|
102
|
+
disabled: zoomedAll === "in",
|
|
103
|
+
onClick: () => onZoom(1)
|
|
104
|
+
})
|
|
105
|
+
]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
42
108
|
var addCleanupSteps = ({ jobs }) => {
|
|
43
109
|
const clonedJobs = structuredClone(jobs);
|
|
44
110
|
for (const job in jobs) {
|
|
@@ -87,8 +153,12 @@ var addCleanupSteps = ({ jobs }) => {
|
|
|
87
153
|
return clonedJobs;
|
|
88
154
|
};
|
|
89
155
|
var PREVIEW_PADDING = 24;
|
|
156
|
+
function outerNodes(content) {
|
|
157
|
+
const top = content.querySelectorAll(":scope > div > div > div > div[id^=\"node_\"]");
|
|
158
|
+
return top.length > 0 ? top : content.querySelectorAll("[id^=\"node_\"]");
|
|
159
|
+
}
|
|
90
160
|
function measurePreviewHeight(content, viewRef) {
|
|
91
|
-
const nodes = content
|
|
161
|
+
const nodes = content ? outerNodes(content) : void 0;
|
|
92
162
|
const transform = content?.parentElement ? getComputedStyle(content.parentElement).transform : "none";
|
|
93
163
|
if (!content || !nodes?.length || transform === "none") return null;
|
|
94
164
|
if (!viewRef.current) {
|
|
@@ -127,20 +197,62 @@ function parsePrefixToPath(prefix) {
|
|
|
127
197
|
}
|
|
128
198
|
return path;
|
|
129
199
|
}
|
|
200
|
+
function unitsOnly(columns, together) {
|
|
201
|
+
return columns.map((col) => {
|
|
202
|
+
const boxes = [];
|
|
203
|
+
const rows = [];
|
|
204
|
+
let last = -1;
|
|
205
|
+
col.boxes.forEach((box, i) => {
|
|
206
|
+
const groups = [];
|
|
207
|
+
for (const job of box) {
|
|
208
|
+
const group = groups.find((g) => together(g[0] ?? job, job));
|
|
209
|
+
if (group) group.push(job);
|
|
210
|
+
else groups.push([job]);
|
|
211
|
+
}
|
|
212
|
+
const main = groups.reduce((a, b) => b.length > a.length ? b : a);
|
|
213
|
+
let row = Math.max(col.rows[i] ?? i, last + 1);
|
|
214
|
+
for (const group of [main, ...groups.filter((g) => g !== main)]) {
|
|
215
|
+
boxes.push(group);
|
|
216
|
+
rows.push(row);
|
|
217
|
+
last = row;
|
|
218
|
+
row += 1;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return {
|
|
222
|
+
...col,
|
|
223
|
+
boxes,
|
|
224
|
+
rows
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function withLoneMatrixSlots({ layoutPosition, mapLayout }, layout, jobs, matrixGroups) {
|
|
229
|
+
const lone = Object.entries(jobs).flatMap(([name, job]) => {
|
|
230
|
+
const original = job._matrix?.originaljob;
|
|
231
|
+
const slot = original && !matrixGroups[original] ? layoutPosition(layout, original) : void 0;
|
|
232
|
+
return slot && !layoutPosition(layout, name) ? [{
|
|
233
|
+
name,
|
|
234
|
+
slot
|
|
235
|
+
}] : [];
|
|
236
|
+
});
|
|
237
|
+
if (lone.length === 0) return layout;
|
|
238
|
+
const next = mapLayout(layout, (position) => position);
|
|
239
|
+
for (const { name, slot } of lone) next[name] = slot;
|
|
240
|
+
return next;
|
|
241
|
+
}
|
|
130
242
|
function displayJobsOf(engine, jobs, matrixGroups) {
|
|
131
243
|
const visibleJobs = structuredClone(jobs);
|
|
132
244
|
for (const jobName of Object.keys(jobs)) if (jobs[jobName]?.if === false) delete visibleJobs[jobName];
|
|
133
245
|
engine.collapseMatrixGroups(matrixGroups, visibleJobs);
|
|
134
246
|
return visibleJobs;
|
|
135
247
|
}
|
|
136
|
-
function computeGraphLayout(engine, jobs, matrixGroups) {
|
|
248
|
+
function computeGraphLayout(engine, jobs, matrixGroups, layout) {
|
|
137
249
|
const visibleJobs = displayJobsOf(engine, jobs, matrixGroups);
|
|
138
250
|
const allDeps = {};
|
|
139
251
|
for (const jobName of Object.keys(visibleJobs)) allDeps[jobName] = engine.jobDependencies(jobName, visibleJobs, allDeps);
|
|
140
252
|
const filteredDeps = {};
|
|
141
253
|
for (const jobName of Object.keys(visibleJobs)) {
|
|
142
254
|
const needs = visibleJobs[jobName]?.needs;
|
|
143
|
-
const oldNeeds = Array.isArray(needs) ? needs : [];
|
|
255
|
+
const oldNeeds = Array.isArray(needs) ? [...new Set(needs.map((need) => typeof need === "string" && engine.editing ? engine.editing.needTarget(need) : need))] : [];
|
|
144
256
|
filteredDeps[jobName] = oldNeeds.filter((dep) => {
|
|
145
257
|
return !oldNeeds.some((other) => {
|
|
146
258
|
if (other === dep) return false;
|
|
@@ -172,8 +284,21 @@ function computeGraphLayout(engine, jobs, matrixGroups) {
|
|
|
172
284
|
}
|
|
173
285
|
if (toAppend.length > 0) deps.push(toAppend);
|
|
174
286
|
} while (prevLen !== unfinished.size);
|
|
175
|
-
const
|
|
176
|
-
|
|
287
|
+
const together = (head, jobName) => {
|
|
288
|
+
const depsA = depended_on[head];
|
|
289
|
+
const depsB = depended_on[jobName];
|
|
290
|
+
const depsA2 = filteredDeps[head];
|
|
291
|
+
const depsB2 = filteredDeps[jobName];
|
|
292
|
+
return (!depsA && !depsB || !!depsA && !!depsB && depsA.length === depsB.length) && (!depsA2 && !depsB2 || !!depsA2 && !!depsB2 && depsA2.length === depsB2.length) && (!depsA || depsA.every((dep, i) => dep === depsB?.[i])) && (!depsA2 || depsA2.every((dep, i) => dep === depsB2?.[i]));
|
|
293
|
+
};
|
|
294
|
+
const alone = (job) => !!visibleJobs[job]?._matrixGroup;
|
|
295
|
+
const editing = engine.editing;
|
|
296
|
+
const laidOut = layout && editing?.hasLayout(layout) ? unitsOnly(editing.boxesFromLayout(Object.keys(visibleJobs), filteredDeps, withLoneMatrixSlots(editing, layout, visibleJobs, matrixGroups), {
|
|
297
|
+
together,
|
|
298
|
+
alone
|
|
299
|
+
}), together) : null;
|
|
300
|
+
const finalDeps = laidOut ? laidOut.map((col) => col.boxes) : [];
|
|
301
|
+
if (!laidOut) deps.forEach((col) => {
|
|
177
302
|
const toAppend = [];
|
|
178
303
|
while (col.length > 0) {
|
|
179
304
|
const head = col[0];
|
|
@@ -181,18 +306,9 @@ function computeGraphLayout(engine, jobs, matrixGroups) {
|
|
|
181
306
|
const grouped = [head];
|
|
182
307
|
const toRm = [0];
|
|
183
308
|
col.slice(1).forEach((jobName, j) => {
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const depsA2 = filteredDeps[head];
|
|
188
|
-
const depsB2 = filteredDeps[jobName];
|
|
189
|
-
if (!depsA && !depsB || depsA && depsB && depsA.length === depsB.length) {
|
|
190
|
-
if (!depsA2 && !depsB2 || depsA2 && depsB2 && depsA2.length === depsB2.length) {
|
|
191
|
-
if ((!depsA || depsA.every((dep, i) => dep === depsB?.[i])) && (!depsA2 || depsA2.every((dep, i) => dep === depsB2?.[i]))) {
|
|
192
|
-
grouped.push(jobName);
|
|
193
|
-
toRm.push(j + 1);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
309
|
+
if (!alone(head) && !alone(jobName) && together(head, jobName)) {
|
|
310
|
+
grouped.push(jobName);
|
|
311
|
+
toRm.push(j + 1);
|
|
196
312
|
}
|
|
197
313
|
});
|
|
198
314
|
col.splice(0, col.length, ...col.filter((_, i) => !toRm.includes(i)));
|
|
@@ -200,7 +316,10 @@ function computeGraphLayout(engine, jobs, matrixGroups) {
|
|
|
200
316
|
}
|
|
201
317
|
finalDeps.push(toAppend);
|
|
202
318
|
});
|
|
203
|
-
if (finalDeps[0]?.length === 0)
|
|
319
|
+
if (finalDeps[0]?.length === 0) {
|
|
320
|
+
finalDeps.shift();
|
|
321
|
+
laidOut?.shift();
|
|
322
|
+
}
|
|
204
323
|
const ancestorDists = {};
|
|
205
324
|
const descendantDists = {};
|
|
206
325
|
const jobNames = Object.keys(visibleJobs);
|
|
@@ -233,6 +352,10 @@ function computeGraphLayout(engine, jobs, matrixGroups) {
|
|
|
233
352
|
}
|
|
234
353
|
return {
|
|
235
354
|
dependencyCols: finalDeps,
|
|
355
|
+
/** Each box's row; above a box, rows the layout leaves empty stay as space. */
|
|
356
|
+
rowSlots: laidOut ? laidOut.map((col) => col.rows) : finalDeps.map((col) => col.map((_, i) => i)),
|
|
357
|
+
/** Each column's number; between two drawn columns, numbers skipped stay as space. */
|
|
358
|
+
colSlots: laidOut ? laidOut.map((col) => col.column) : finalDeps.map((_, i) => i),
|
|
236
359
|
directDeps: filteredDeps,
|
|
237
360
|
displayJobs: visibleJobs,
|
|
238
361
|
ancestorDists,
|
|
@@ -279,9 +402,28 @@ function SubworkflowWell({ expanded, onSettled, className, children }) {
|
|
|
279
402
|
}
|
|
280
403
|
var SUBGRAPH_Z_STEP = 100;
|
|
281
404
|
var CONNECTOR_COLOR = "var(--theme-border)";
|
|
282
|
-
var HIGHLIGHT_COLOR = "
|
|
405
|
+
var HIGHLIGHT_COLOR = "var(--theme-element)";
|
|
283
406
|
var FIT_ANIMATION_MS = 300;
|
|
284
|
-
function
|
|
407
|
+
function sizesSettled(els) {
|
|
408
|
+
return new Promise((resolve) => {
|
|
409
|
+
let frame = 0;
|
|
410
|
+
const observer = new ResizeObserver(() => {
|
|
411
|
+
cancelAnimationFrame(frame);
|
|
412
|
+
frame = requestAnimationFrame(() => {
|
|
413
|
+
frame = requestAnimationFrame(() => {
|
|
414
|
+
observer.disconnect();
|
|
415
|
+
resolve();
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
for (const el of els) observer.observe(el);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
function sizingTransitions(el) {
|
|
423
|
+
return el.getAnimations({ subtree: true }).filter((animation) => animation instanceof CSSTransition && (animation.transitionProperty === "grid-template-rows" || animation.transitionProperty === "width"));
|
|
424
|
+
}
|
|
425
|
+
var ZOOM_STEP = .25;
|
|
426
|
+
function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, invalidateConnectors, requestFit, stepsOpen, toggleSteps, matrixOpen, toggleMatrix, onReady, layout }) {
|
|
285
427
|
const engine = useWorkflowEngine();
|
|
286
428
|
const wrapperRef = useRef(null);
|
|
287
429
|
const zBase = depth * SUBGRAPH_Z_STEP;
|
|
@@ -290,10 +432,16 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
290
432
|
const maxHoveredDistRef = useRef(0);
|
|
291
433
|
const retractPathLensRef = useRef(/* @__PURE__ */ new Map());
|
|
292
434
|
const matrixGroups = useMemo(() => engine.matrixGroups(jobs), [engine, jobs]);
|
|
293
|
-
const
|
|
435
|
+
const placed = useMemo(() => layout ?? (depth > 0 ? positionsOf(jobs) : void 0), [
|
|
436
|
+
layout,
|
|
437
|
+
depth,
|
|
438
|
+
jobs
|
|
439
|
+
]);
|
|
440
|
+
const { dependencyCols, rowSlots, colSlots, directDeps, displayJobs, ancestorDists, descendantDists } = useMemo(() => computeGraphLayout(engine, jobs, matrixGroups, placed), [
|
|
294
441
|
engine,
|
|
295
442
|
jobs,
|
|
296
|
-
matrixGroups
|
|
443
|
+
matrixGroups,
|
|
444
|
+
placed
|
|
297
445
|
]);
|
|
298
446
|
const hoveredDistances = useMemo(() => {
|
|
299
447
|
if (!hoveredJob) return null;
|
|
@@ -410,56 +558,66 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
410
558
|
});
|
|
411
559
|
return /* @__PURE__ */ jsx("div", {
|
|
412
560
|
className: "flex relative",
|
|
413
|
-
children: dependencyCols.map((col) => {
|
|
414
|
-
return /* @__PURE__ */ jsx("div", {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
matrixGroup
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
onBlur: () => setHoveredJob(null),
|
|
443
|
-
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-2xl bg-(--theme-panel-bg)" }), /* @__PURE__ */ jsx("div", {
|
|
444
|
-
className: "relative border-solid shadow py-4 px-8 rounded-xl border-4 whitespace-nowrap bg-(--theme-panel-bg) text-2xl",
|
|
561
|
+
children: dependencyCols.map((col, c) => {
|
|
562
|
+
return /* @__PURE__ */ jsx("div", {
|
|
563
|
+
style: emptyColumnsStyle((colSlots[c] ?? c) - (c === 0 ? 0 : (colSlots[c - 1] ?? c - 1) + 1)),
|
|
564
|
+
children: col.map((jobNames, i) => {
|
|
565
|
+
const first = jobNames[0];
|
|
566
|
+
if (first === void 0) return null;
|
|
567
|
+
const matrixGroup = displayJobs[first]?._matrixGroup;
|
|
568
|
+
const rowsAbove = (rowSlots[c]?.[i] ?? i) - (i === 0 ? 0 : (rowSlots[c]?.[i - 1] ?? i - 1) + 1);
|
|
569
|
+
if (matrixGroup) return /* @__PURE__ */ jsx(MatrixGroupNode, {
|
|
570
|
+
matrixGroup,
|
|
571
|
+
jobNames,
|
|
572
|
+
idPrefix: pathPrefix,
|
|
573
|
+
isExpanded: matrixOpen.has(pathPrefix + matrixGroup.originaljob),
|
|
574
|
+
onToggle: () => toggleMatrix(pathPrefix + matrixGroup.originaljob),
|
|
575
|
+
jobs,
|
|
576
|
+
activeDists,
|
|
577
|
+
onMouseEnter: () => setHoveredJob(first),
|
|
578
|
+
onMouseLeave: () => setHoveredJob(null),
|
|
579
|
+
hoveredRelated,
|
|
580
|
+
animT,
|
|
581
|
+
zBase,
|
|
582
|
+
handlers,
|
|
583
|
+
preview,
|
|
584
|
+
rowsAbove
|
|
585
|
+
}, `node_${first}`);
|
|
586
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
587
|
+
id: `node_${pathPrefix}${first}`,
|
|
588
|
+
role: "none",
|
|
589
|
+
className: "relative m-24",
|
|
445
590
|
style: {
|
|
446
|
-
|
|
447
|
-
|
|
591
|
+
zIndex: (activeDists?.has(first) ? 25 : 1) + zBase,
|
|
592
|
+
...emptyRowsStyle(rowsAbove)
|
|
448
593
|
},
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
594
|
+
onMouseEnter: () => setHoveredJob(first),
|
|
595
|
+
onMouseLeave: () => setHoveredJob(null),
|
|
596
|
+
onFocus: () => setHoveredJob(first),
|
|
597
|
+
onBlur: () => setHoveredJob(null),
|
|
598
|
+
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-2xl bg-(--theme-panel-bg)" }), /* @__PURE__ */ jsx("div", {
|
|
599
|
+
className: "relative border-solid shadow py-4 px-8 rounded-xl border-4 whitespace-nowrap bg-(--theme-panel-bg) text-2xl",
|
|
600
|
+
style: {
|
|
601
|
+
opacity: hoveredRelated && !hoveredRelated.has(first) ? .5 : 1,
|
|
602
|
+
transition: `opacity ${animT}s`
|
|
603
|
+
},
|
|
604
|
+
children: /* @__PURE__ */ jsx(Joblist, {
|
|
605
|
+
jobs: displayJobs,
|
|
606
|
+
jobNames,
|
|
607
|
+
...handlers,
|
|
608
|
+
growWidth: true,
|
|
609
|
+
preview
|
|
610
|
+
})
|
|
611
|
+
})]
|
|
612
|
+
}, `node_${first}`);
|
|
613
|
+
})
|
|
614
|
+
}, col[0]?.[0]);
|
|
459
615
|
})
|
|
460
616
|
});
|
|
461
617
|
}, [
|
|
462
618
|
dependencyCols,
|
|
619
|
+
rowSlots,
|
|
620
|
+
colSlots,
|
|
463
621
|
displayJobs,
|
|
464
622
|
jobs,
|
|
465
623
|
stepsOpen,
|
|
@@ -492,17 +650,23 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
492
650
|
const gid = (name) => document.getElementById(`node_${pathPrefix}${name}`);
|
|
493
651
|
const ox = (el) => offsetWithin(el, wrapper).x;
|
|
494
652
|
const nodeConnectorY = (el) => offsetWithin(el, wrapper).y + 37;
|
|
653
|
+
const depsOf = (head) => directDeps[head] ?? [];
|
|
495
654
|
let colGap = 32;
|
|
496
655
|
if (dependencyCols.length >= 2) {
|
|
497
656
|
const col0 = gid(dependencyCols[0]?.[0]?.[0] ?? "");
|
|
498
657
|
const col1 = gid(dependencyCols[1]?.[0]?.[0] ?? "");
|
|
499
658
|
if (col0 && col1) colGap = ox(col1) - (ox(col0) + col0.offsetWidth);
|
|
500
659
|
}
|
|
660
|
+
if (colSlots.some((column, c) => column !== c)) for (let c = 1; c < dependencyCols.length; c++) {
|
|
661
|
+
const left = gid(dependencyCols[c - 1]?.[0]?.[0] ?? "");
|
|
662
|
+
const right = gid(dependencyCols[c]?.[0]?.[0] ?? "");
|
|
663
|
+
if (left && right) colGap = Math.min(colGap, ox(right) - (ox(left) + left.offsetWidth));
|
|
664
|
+
}
|
|
501
665
|
let minAdy = Number.POSITIVE_INFINITY;
|
|
502
666
|
for (const col of dependencyCols) for (const jobNames of col) {
|
|
503
667
|
const first = jobNames[0];
|
|
504
668
|
if (first === void 0) continue;
|
|
505
|
-
for (const dep of
|
|
669
|
+
for (const dep of depsOf(first)) {
|
|
506
670
|
const s = gid(dep);
|
|
507
671
|
const e = gid(first);
|
|
508
672
|
if (!s || !e) continue;
|
|
@@ -512,7 +676,7 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
512
676
|
}
|
|
513
677
|
const MAX_ARC_R = 16;
|
|
514
678
|
const arcR = Math.min(minAdy === Number.POSITIVE_INFINITY ? MAX_ARC_R : minAdy / 4, colGap / 2, MAX_ARC_R);
|
|
515
|
-
return dependencyCols.map((col) => /* @__PURE__ */ jsx(React.Fragment, { children: col.map(([first]) => first === void 0 ? null : /* @__PURE__ */ jsx(React.Fragment, { children: (
|
|
679
|
+
return dependencyCols.map((col) => /* @__PURE__ */ jsx(React.Fragment, { children: col.map(([first]) => first === void 0 ? null : /* @__PURE__ */ jsx(React.Fragment, { children: depsOf(first).map((dep) => {
|
|
516
680
|
const isHighlighted = hoveredRelated?.has(first) && hoveredRelated?.has(dep);
|
|
517
681
|
const depDist = activeDists?.get(dep) ?? 0;
|
|
518
682
|
const targetDist = activeDists?.get(first) ?? 0;
|
|
@@ -706,7 +870,7 @@ function SidebarJobs({ jobs, pathPrefix, preview, stepsOpen, toggleSteps, expand
|
|
|
706
870
|
const seenMatrixGroups = /* @__PURE__ */ new Set();
|
|
707
871
|
const orderedKeys = Object.keys(jobs).flatMap((jobName) => {
|
|
708
872
|
const originaljob = jobs[jobName]?._matrix?.originaljob;
|
|
709
|
-
if (!originaljob) return [jobName];
|
|
873
|
+
if (!originaljob || !displayJobs[originaljob]?._matrixGroup) return [jobName];
|
|
710
874
|
if (seenMatrixGroups.has(originaljob)) return [];
|
|
711
875
|
seenMatrixGroups.add(originaljob);
|
|
712
876
|
return [originaljob];
|
|
@@ -754,7 +918,7 @@ function walkJobPath(root, path) {
|
|
|
754
918
|
}
|
|
755
919
|
return isJobRecord(cursor) ? cursor : {};
|
|
756
920
|
}
|
|
757
|
-
function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag", setViewMode }) {
|
|
921
|
+
function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag", setViewMode, layout, yamlJobs, fixedHeight }) {
|
|
758
922
|
const engine = useWorkflowEngine();
|
|
759
923
|
const animT = .125;
|
|
760
924
|
const minScale = .2;
|
|
@@ -812,7 +976,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
812
976
|
const previewViewRef = useRef(null);
|
|
813
977
|
useEffect(() => {
|
|
814
978
|
const container = containerRef.current;
|
|
815
|
-
if (!preview || !container) return;
|
|
979
|
+
if (!preview || !container || fixedHeight) return;
|
|
816
980
|
let raf = 0;
|
|
817
981
|
let attempts = 0;
|
|
818
982
|
const measure = () => {
|
|
@@ -837,7 +1001,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
837
1001
|
observer.disconnect();
|
|
838
1002
|
cancelAnimationFrame(raf);
|
|
839
1003
|
};
|
|
840
|
-
}, [preview]);
|
|
1004
|
+
}, [preview, fixedHeight]);
|
|
841
1005
|
const { dag: dagStrings } = useStrings();
|
|
842
1006
|
const slots = useSlots();
|
|
843
1007
|
const [executedJobsPath, setExecutedJobsPath] = useState([[]]);
|
|
@@ -853,6 +1017,14 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
853
1017
|
}, [isRunFinished]);
|
|
854
1018
|
const currentPath = executedJobsPath[executedJobsPathIdx] ?? [];
|
|
855
1019
|
const jobs = walkJobPath(rootJobs, currentPath);
|
|
1020
|
+
const root = currentPath.length === 0;
|
|
1021
|
+
const placed = useMemo(() => root && engine.editing?.hasLayout(layout) ? layout : positionsOf(root ? yamlJobs ?? jobs : jobs), [
|
|
1022
|
+
engine,
|
|
1023
|
+
root,
|
|
1024
|
+
layout,
|
|
1025
|
+
yamlJobs,
|
|
1026
|
+
jobs
|
|
1027
|
+
]);
|
|
856
1028
|
const resetGraph = useCallback(() => {
|
|
857
1029
|
setSublogOpen("");
|
|
858
1030
|
setStepsOpen(/* @__PURE__ */ new Set());
|
|
@@ -910,8 +1082,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
910
1082
|
const content = graphContentRef.current;
|
|
911
1083
|
const transform = transformRef.current;
|
|
912
1084
|
if (!container || !content || !transform) return;
|
|
913
|
-
const
|
|
914
|
-
const nodes = topNodes.length > 0 ? topNodes : content.querySelectorAll("[id^=\"node_\"]");
|
|
1085
|
+
const nodes = outerNodes(content);
|
|
915
1086
|
if (nodes.length === 0) return;
|
|
916
1087
|
let minX = Number.POSITIVE_INFINITY;
|
|
917
1088
|
let minY = Number.POSITIVE_INFINITY;
|
|
@@ -947,7 +1118,45 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
947
1118
|
invalidateConnectors();
|
|
948
1119
|
});
|
|
949
1120
|
}, [invalidateConnectors]);
|
|
950
|
-
const
|
|
1121
|
+
const fitWhenSettled = useCallback(async () => {
|
|
1122
|
+
const container = containerRef.current;
|
|
1123
|
+
const content = graphContentRef.current;
|
|
1124
|
+
if (!container || !content) return;
|
|
1125
|
+
let running = sizingTransitions(content);
|
|
1126
|
+
while (running.length > 0) {
|
|
1127
|
+
await Promise.allSettled(running.map((transition) => transition.finished));
|
|
1128
|
+
running = sizingTransitions(content);
|
|
1129
|
+
}
|
|
1130
|
+
const panelHeight = preview && !fixedHeight ? measurePreviewHeight(content, previewViewRef) : null;
|
|
1131
|
+
if (panelHeight !== null) flushSync(() => setPreviewHeight(panelHeight));
|
|
1132
|
+
await sizesSettled([
|
|
1133
|
+
container,
|
|
1134
|
+
content,
|
|
1135
|
+
...outerNodes(content)
|
|
1136
|
+
]);
|
|
1137
|
+
invalidateConnectors();
|
|
1138
|
+
fitGraph(FIT_ANIMATION_MS);
|
|
1139
|
+
}, [
|
|
1140
|
+
fitGraph,
|
|
1141
|
+
invalidateConnectors,
|
|
1142
|
+
preview,
|
|
1143
|
+
fixedHeight
|
|
1144
|
+
]);
|
|
1145
|
+
const [zoomedAll, setZoomedAll] = useState("in");
|
|
1146
|
+
const onTransform = useCallback((_, { scale }) => {
|
|
1147
|
+
setZoomedAll(scale >= .599 ? "in" : scale <= .201 ? "out" : null);
|
|
1148
|
+
invalidateConnectors();
|
|
1149
|
+
}, [invalidateConnectors]);
|
|
1150
|
+
const zoomBy = useCallback((step) => {
|
|
1151
|
+
const container = containerRef.current;
|
|
1152
|
+
const transform = transformRef.current;
|
|
1153
|
+
if (!container || !transform) return;
|
|
1154
|
+
const { positionX, positionY, scale } = transform.instance.state;
|
|
1155
|
+
const next = Math.min(maxScale, Math.max(minScale, scale * Math.exp(step)));
|
|
1156
|
+
const x = container.clientWidth / 2;
|
|
1157
|
+
const y = container.clientHeight / 2;
|
|
1158
|
+
transform.setTransform(x - (x - positionX) / scale * next, y - (y - positionY) / scale * next, next, FIT_ANIMATION_MS, "easeOut");
|
|
1159
|
+
}, []);
|
|
951
1160
|
useEffect(() => {
|
|
952
1161
|
if (preview) return;
|
|
953
1162
|
const raf = requestAnimationFrame(() => fitGraph());
|
|
@@ -977,20 +1186,26 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
977
1186
|
]);
|
|
978
1187
|
const hasExpandable = expansionKeys.subworkflowKeys.length > 0 || expansionKeys.matrixKeys.length > 0;
|
|
979
1188
|
const allExpanded = hasExpandable && expansionKeys.subworkflowKeys.every((k) => expandedSubworkflows.has(k)) && expansionKeys.matrixKeys.every((k) => matrixOpen.has(k));
|
|
1189
|
+
const resetView = () => {
|
|
1190
|
+
if (currentPath.length > 0) {
|
|
1191
|
+
resetGraph();
|
|
1192
|
+
setExecutedJobsPath([[], ...executedJobsPath.slice(executedJobsPathIdx, 10)]);
|
|
1193
|
+
setExecutedJobsPathIdx(0);
|
|
1194
|
+
} else fitGraph(FIT_ANIMATION_MS);
|
|
1195
|
+
};
|
|
980
1196
|
const toggleExpandAll = () => {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
invalidateConnectors();
|
|
992
|
-
fitGraph();
|
|
1197
|
+
flushSync(() => {
|
|
1198
|
+
if (allExpanded) {
|
|
1199
|
+
setExpandedSubworkflows(/* @__PURE__ */ new Set());
|
|
1200
|
+
setStepsOpen(/* @__PURE__ */ new Set());
|
|
1201
|
+
setMatrixOpen(/* @__PURE__ */ new Set());
|
|
1202
|
+
} else {
|
|
1203
|
+
setExpandedSubworkflows(new Set(expansionKeys.subworkflowKeys));
|
|
1204
|
+
setStepsOpen(new Set(expansionKeys.jobKeys));
|
|
1205
|
+
setMatrixOpen(new Set(expansionKeys.matrixKeys));
|
|
1206
|
+
}
|
|
993
1207
|
});
|
|
1208
|
+
fitWhenSettled();
|
|
994
1209
|
};
|
|
995
1210
|
const nextStep = useCallback((backward) => {
|
|
996
1211
|
const sublogSplit = sublogOpen.split("/");
|
|
@@ -1196,8 +1411,8 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1196
1411
|
ref: setContainerElement,
|
|
1197
1412
|
className: cx("panel w-full overflow-hidden relative", removeBorder ? "border-none" : "border"),
|
|
1198
1413
|
style: {
|
|
1199
|
-
height: containerHeight !== null ? `${containerHeight}px` : previewHeight !== null ? `${Math.min(previewHeight, windowSize.h * .62)}px` : "62vh",
|
|
1200
|
-
minHeight: previewHeight !== null ? 0 : 160
|
|
1414
|
+
height: fixedHeight ?? (containerHeight !== null ? `${containerHeight}px` : previewHeight !== null ? `${Math.min(previewHeight, windowSize.h * .62)}px` : "62vh"),
|
|
1415
|
+
minHeight: previewHeight !== null && !fixedHeight ? 0 : 160
|
|
1201
1416
|
},
|
|
1202
1417
|
children: /* @__PURE__ */ jsx(TransformWrapper, {
|
|
1203
1418
|
ref: transformRef,
|
|
@@ -1211,56 +1426,30 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1211
1426
|
},
|
|
1212
1427
|
onPanning: invalidateConnectors,
|
|
1213
1428
|
onPinch: invalidateConnectors,
|
|
1214
|
-
onTransform
|
|
1429
|
+
onTransform,
|
|
1215
1430
|
onWheel: invalidateConnectors,
|
|
1216
1431
|
onZoom: invalidateConnectors,
|
|
1217
|
-
children: () => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */
|
|
1218
|
-
className: "absolute z-10 top-2 right-2 flex flex-col items-end gap-y-1",
|
|
1219
|
-
children:
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
}),
|
|
1239
|
-
executedJobsPath.length > 1 && /* @__PURE__ */ jsxs("div", {
|
|
1240
|
-
className: "flex",
|
|
1241
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
1242
|
-
type: "button",
|
|
1243
|
-
onClick: () => {
|
|
1244
|
-
if (executedJobsPath.length > executedJobsPathIdx + 1) {
|
|
1245
|
-
resetGraph();
|
|
1246
|
-
setExecutedJobsPathIdx(executedJobsPathIdx + 1);
|
|
1247
|
-
}
|
|
1248
|
-
},
|
|
1249
|
-
className: "btn btn-info mr-1 cursor-pointer w-10 h-6",
|
|
1250
|
-
children: "<"
|
|
1251
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
1252
|
-
type: "button",
|
|
1253
|
-
onClick: () => {
|
|
1254
|
-
if (executedJobsPathIdx - 1 >= 0) {
|
|
1255
|
-
resetGraph();
|
|
1256
|
-
setExecutedJobsPathIdx(executedJobsPathIdx - 1);
|
|
1257
|
-
}
|
|
1258
|
-
},
|
|
1259
|
-
className: "btn btn-info cursor-pointer w-10 h-6",
|
|
1260
|
-
children: ">"
|
|
1261
|
-
})]
|
|
1262
|
-
})
|
|
1263
|
-
]
|
|
1432
|
+
children: () => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
1433
|
+
className: "absolute z-10 top-2 right-2 flex max-w-[calc(100%-1rem)] flex-col items-end gap-y-1",
|
|
1434
|
+
children: /* @__PURE__ */ jsx(GraphViewControls, {
|
|
1435
|
+
history: executedJobsPath.length > 1 ? {
|
|
1436
|
+
back: executedJobsPathIdx + 1 < executedJobsPath.length ? () => {
|
|
1437
|
+
resetGraph();
|
|
1438
|
+
setExecutedJobsPathIdx(executedJobsPathIdx + 1);
|
|
1439
|
+
} : void 0,
|
|
1440
|
+
forward: executedJobsPathIdx > 0 ? () => {
|
|
1441
|
+
resetGraph();
|
|
1442
|
+
setExecutedJobsPathIdx(executedJobsPathIdx - 1);
|
|
1443
|
+
} : void 0
|
|
1444
|
+
} : void 0,
|
|
1445
|
+
expand: hasExpandable ? {
|
|
1446
|
+
label: allExpanded ? dagStrings.collapseAll : dagStrings.expandAll,
|
|
1447
|
+
onClick: toggleExpandAll
|
|
1448
|
+
} : void 0,
|
|
1449
|
+
onReset: resetView,
|
|
1450
|
+
onZoom: (direction) => zoomBy(direction * ZOOM_STEP),
|
|
1451
|
+
zoomedAll
|
|
1452
|
+
})
|
|
1264
1453
|
}), /* @__PURE__ */ jsx(TransformComponent, { children: /* @__PURE__ */ jsx("div", {
|
|
1265
1454
|
ref: graphContentRef,
|
|
1266
1455
|
className: "flex relative mr-[8000px]",
|
|
@@ -1276,12 +1465,13 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1276
1465
|
openInNewGraph,
|
|
1277
1466
|
setSublogOpen,
|
|
1278
1467
|
invalidateConnectors,
|
|
1279
|
-
requestFit:
|
|
1468
|
+
requestFit: fitWhenSettled,
|
|
1280
1469
|
stepsOpen,
|
|
1281
1470
|
toggleSteps,
|
|
1282
1471
|
matrixOpen,
|
|
1283
1472
|
toggleMatrix,
|
|
1284
|
-
onReady: fitGraph
|
|
1473
|
+
onReady: fitGraph,
|
|
1474
|
+
layout: placed
|
|
1285
1475
|
}, `sg-${executedJobsPathIdx}-${pathAppend}`)
|
|
1286
1476
|
}) })] })
|
|
1287
1477
|
})
|
|
@@ -1334,17 +1524,122 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1334
1524
|
]
|
|
1335
1525
|
});
|
|
1336
1526
|
}
|
|
1527
|
+
var isSlot = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
1528
|
+
/** Each job's place on the graph from its `position`; none when no job has one. */
|
|
1529
|
+
function positionsOf(jobs) {
|
|
1530
|
+
const layout = Object.create(null);
|
|
1531
|
+
let any = false;
|
|
1532
|
+
for (const [name, job] of Object.entries(jobs)) {
|
|
1533
|
+
const { position, _matrix } = isJobRecord(job) ? job : {};
|
|
1534
|
+
const { column, row } = isJobRecord(position) ? position : {};
|
|
1535
|
+
const original = isJobRecord(_matrix) ? _matrix["originaljob"] : void 0;
|
|
1536
|
+
const key = typeof original === "string" && original ? original : name;
|
|
1537
|
+
if (isSlot(column) && isSlot(row) && !(key in layout)) {
|
|
1538
|
+
layout[key] = {
|
|
1539
|
+
column,
|
|
1540
|
+
row
|
|
1541
|
+
};
|
|
1542
|
+
any = true;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return any ? layout : void 0;
|
|
1546
|
+
}
|
|
1547
|
+
/** Jobs as a run evaluates them before it starts: each `strategy`, and a `needs` expression, from the inputs' defaults. */
|
|
1548
|
+
function withRunExpressions(engine, jobs, workflowInputs) {
|
|
1549
|
+
let values;
|
|
1550
|
+
const evaluate = (obj) => {
|
|
1551
|
+
values ??= defaultInputValues(engine, workflowInputs);
|
|
1552
|
+
return engine.evaluate({
|
|
1553
|
+
inputs: values,
|
|
1554
|
+
obj
|
|
1555
|
+
});
|
|
1556
|
+
};
|
|
1557
|
+
const out = {};
|
|
1558
|
+
for (const [name, job] of Object.entries(jobs)) {
|
|
1559
|
+
const { strategy, needs } = job;
|
|
1560
|
+
const next = { ...job };
|
|
1561
|
+
if (engine.editing && isJobRecord(strategy) && engine.inputDependencies(strategy).hasExpressions) next["strategy"] = evaluate(strategy);
|
|
1562
|
+
if (typeof needs === "string" && engine.inputDependencies(needs).hasExpressions) {
|
|
1563
|
+
const evaluated = evaluate({ needs })["needs"];
|
|
1564
|
+
if (Array.isArray(evaluated) && evaluated.every((need) => typeof need === "string")) next["needs"] = evaluated;
|
|
1565
|
+
}
|
|
1566
|
+
out[name] = next;
|
|
1567
|
+
}
|
|
1568
|
+
return out;
|
|
1569
|
+
}
|
|
1570
|
+
/** The input values a run started without any gets: each one's default. */
|
|
1571
|
+
function defaultInputValues(engine, workflowInputs) {
|
|
1572
|
+
try {
|
|
1573
|
+
const fields = prefilled(engine.convertInputs(workflowInputs ?? {}));
|
|
1574
|
+
const initial = initializeValues(fields) ?? {};
|
|
1575
|
+
return engine.evaluate({
|
|
1576
|
+
inputs: initial,
|
|
1577
|
+
obj: initial
|
|
1578
|
+
});
|
|
1579
|
+
} catch {
|
|
1580
|
+
return {};
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
function prefilled(value) {
|
|
1584
|
+
if (Array.isArray(value)) return value.map(prefilled);
|
|
1585
|
+
if (!isJobRecord(value)) return value;
|
|
1586
|
+
const field = Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, prefilled(entry)]));
|
|
1587
|
+
return "type" in field && "default" in field ? {
|
|
1588
|
+
...field,
|
|
1589
|
+
prefillDefault: true
|
|
1590
|
+
} : field;
|
|
1591
|
+
}
|
|
1337
1592
|
function DependencyGraphPreview(inputs) {
|
|
1593
|
+
const engine = useWorkflowEngine();
|
|
1594
|
+
const { editing } = engine;
|
|
1338
1595
|
const ymlJobs = inputs.yml?.["jobs"];
|
|
1596
|
+
const jobs = isJobRecord(ymlJobs) ? ymlJobs : {};
|
|
1597
|
+
const evaluates = useMemo(() => Object.values(jobs).some((job) => {
|
|
1598
|
+
const { strategy, needs } = job;
|
|
1599
|
+
return engine.inputDependencies({
|
|
1600
|
+
strategy: editing ? strategy : void 0,
|
|
1601
|
+
needs
|
|
1602
|
+
}).hasExpressions;
|
|
1603
|
+
}), [
|
|
1604
|
+
engine,
|
|
1605
|
+
editing,
|
|
1606
|
+
jobs
|
|
1607
|
+
]);
|
|
1608
|
+
const [ready, setReady] = useState(() => engine.isReady());
|
|
1609
|
+
useEffect(() => {
|
|
1610
|
+
if (!evaluates) return;
|
|
1611
|
+
engine.init();
|
|
1612
|
+
const unsubscribe = engine.onReady(setReady);
|
|
1613
|
+
setReady(engine.isReady());
|
|
1614
|
+
return unsubscribe;
|
|
1615
|
+
}, [engine, evaluates]);
|
|
1616
|
+
const on = inputs.yml?.["on"];
|
|
1617
|
+
const execute = isJobRecord(on) ? on["execute"] : void 0;
|
|
1618
|
+
const executeInputs = isJobRecord(execute) ? execute["inputs"] : void 0;
|
|
1619
|
+
const workflowInputs = isJobRecord(executeInputs) ? executeInputs : void 0;
|
|
1620
|
+
const executedJobs = useMemo(() => {
|
|
1621
|
+
const withCleanup = addCleanupSteps({ jobs });
|
|
1622
|
+
const evaluated = ready ? withRunExpressions(engine, withCleanup, workflowInputs) : withCleanup;
|
|
1623
|
+
return editing ? editing.expandMatrixJobs(evaluated) : evaluated;
|
|
1624
|
+
}, [
|
|
1625
|
+
engine,
|
|
1626
|
+
editing,
|
|
1627
|
+
ready,
|
|
1628
|
+
jobs,
|
|
1629
|
+
workflowInputs
|
|
1630
|
+
]);
|
|
1339
1631
|
return /* @__PURE__ */ jsx(DependencyGraph, {
|
|
1340
1632
|
run: {
|
|
1341
|
-
executedJobs
|
|
1633
|
+
executedJobs,
|
|
1342
1634
|
number: 0,
|
|
1343
1635
|
workflowName: ""
|
|
1344
1636
|
},
|
|
1345
1637
|
preview: true,
|
|
1346
|
-
removeBorder: inputs.removeBorder
|
|
1638
|
+
removeBorder: inputs.removeBorder,
|
|
1639
|
+
layout: inputs.layout,
|
|
1640
|
+
yamlJobs: jobs,
|
|
1641
|
+
fixedHeight: inputs.height
|
|
1347
1642
|
});
|
|
1348
1643
|
}
|
|
1349
1644
|
//#endregion
|
|
1350
|
-
export { DependencyGraphPreview, addCleanupSteps, DependencyGraph as default };
|
|
1645
|
+
export { DependencyGraphPreview, addCleanupSteps, computeGraphLayout, DependencyGraph as default };
|