@parallelworks/ui 0.40.0 → 0.40.1
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 +6 -0
- package/dist/ai/ai.css +4 -2
- package/dist/ai/ui/Markdown.js +4 -1
- package/dist/graph/Connectors.d.ts +11 -0
- package/dist/graph/Connectors.js +158 -0
- package/dist/graph/DependencyGraph.d.ts +2 -16
- package/dist/graph/DependencyGraph.js +375 -725
- package/dist/graph/GraphNode.d.ts +35 -0
- package/dist/graph/GraphNode.js +70 -0
- package/dist/graph/MatrixGroup.d.ts +4 -8
- package/dist/graph/MatrixGroup.js +27 -40
- package/dist/graph/connectorGeometry.d.ts +44 -0
- package/dist/graph/connectorGeometry.js +103 -0
- package/dist/graph/graphLayout.d.ts +24 -0
- package/dist/graph/graphLayout.js +205 -0
- package/dist/graph/lineage.d.ts +51 -0
- package/dist/graph/lineage.js +94 -0
- package/dist/graph/store.d.ts +10 -0
- package/dist/graph/store.js +25 -0
- package/dist/graph/viewport.d.ts +40 -0
- package/dist/graph/viewport.js +56 -0
- package/dist/styles.css +1 -1
- package/package.json +5 -2
|
@@ -18,15 +18,22 @@ import { AnnotationBanner } from "./AnnotationBanner.js";
|
|
|
18
18
|
import { Collapse } from "./Collapse.js";
|
|
19
19
|
import { jobLabel, toggled } from "./util.js";
|
|
20
20
|
import { EDITOR_HANDLE_CLASS, GraphEditorProvider, useGraphEditor, useSelectedEdges } from "./graphEditorState.js";
|
|
21
|
-
import {
|
|
22
|
-
import { emptyColumnsStyle
|
|
21
|
+
import { EdgeEnds, EdgeHitPath, EmptyGraphEditor, GraphEditorCanvas, NodePorts } from "./editorRows.js";
|
|
22
|
+
import { emptyColumnsStyle } from "./gridSpacing.js";
|
|
23
23
|
import { Reveal } from "./Reveal.js";
|
|
24
24
|
import { Joblist } from "./JobSummary.js";
|
|
25
|
+
import { Store, useStore } from "./store.js";
|
|
26
|
+
import { Lineage, LineageContext } from "./lineage.js";
|
|
27
|
+
import { DimRules, JobNode, setDimmed } from "./GraphNode.js";
|
|
28
|
+
import { ConnectorLayers } from "./Connectors.js";
|
|
29
|
+
import { routeConnectors, sameBoxes } from "./connectorGeometry.js";
|
|
30
|
+
import { isJobRecord } from "./types.js";
|
|
31
|
+
import { computeGraphLayout, displayJobsOf, hopDistances, positionsOf } from "./graphLayout.js";
|
|
25
32
|
import { MatrixGroupNode, MatrixGroupSummaryItem } from "./MatrixGroup.js";
|
|
26
33
|
import TreeView from "./TreeView.js";
|
|
27
|
-
import {
|
|
34
|
+
import { FIT_MAX_SCALE, MIN_SCALE, ZOOM_STEP, fitMargin, fitView, intoView, wheelFactor, zoomAround, zoomLimit } from "./viewport.js";
|
|
28
35
|
import cx from "classnames";
|
|
29
|
-
import
|
|
36
|
+
import { Fragment, Suspense, createContext, lazy, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
30
37
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
31
38
|
import { flushSync } from "react-dom";
|
|
32
39
|
import { DateTime } from "luxon";
|
|
@@ -199,171 +206,6 @@ function parsePrefixToPath(prefix) {
|
|
|
199
206
|
}
|
|
200
207
|
return path;
|
|
201
208
|
}
|
|
202
|
-
function unitsOnly(columns, together) {
|
|
203
|
-
return columns.map((col) => {
|
|
204
|
-
const boxes = [];
|
|
205
|
-
const rows = [];
|
|
206
|
-
let last = -1;
|
|
207
|
-
col.boxes.forEach((box, i) => {
|
|
208
|
-
const groups = [];
|
|
209
|
-
for (const job of box) {
|
|
210
|
-
const group = groups.find((g) => together(g[0] ?? job, job));
|
|
211
|
-
if (group) group.push(job);
|
|
212
|
-
else groups.push([job]);
|
|
213
|
-
}
|
|
214
|
-
const main = groups.reduce((a, b) => b.length > a.length ? b : a);
|
|
215
|
-
let row = Math.max(col.rows[i] ?? i, last + 1);
|
|
216
|
-
for (const group of [main, ...groups.filter((g) => g !== main)]) {
|
|
217
|
-
boxes.push(group);
|
|
218
|
-
rows.push(row);
|
|
219
|
-
last = row;
|
|
220
|
-
row += 1;
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
return {
|
|
224
|
-
...col,
|
|
225
|
-
boxes,
|
|
226
|
-
rows
|
|
227
|
-
};
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
function withLoneMatrixSlots({ layoutPosition, mapLayout }, layout, jobs, matrixGroups) {
|
|
231
|
-
const lone = Object.entries(jobs).flatMap(([name, job]) => {
|
|
232
|
-
const original = job._matrix?.originaljob;
|
|
233
|
-
const slot = original && !matrixGroups[original] ? layoutPosition(layout, original) : void 0;
|
|
234
|
-
return slot && !layoutPosition(layout, name) ? [{
|
|
235
|
-
name,
|
|
236
|
-
slot
|
|
237
|
-
}] : [];
|
|
238
|
-
});
|
|
239
|
-
if (lone.length === 0) return layout;
|
|
240
|
-
const next = mapLayout(layout, (position) => position);
|
|
241
|
-
for (const { name, slot } of lone) next[name] = slot;
|
|
242
|
-
return next;
|
|
243
|
-
}
|
|
244
|
-
function displayJobsOf(engine, jobs, matrixGroups) {
|
|
245
|
-
const visibleJobs = structuredClone(jobs);
|
|
246
|
-
for (const jobName of Object.keys(jobs)) if (jobs[jobName]?.if === false) delete visibleJobs[jobName];
|
|
247
|
-
engine.collapseMatrixGroups(matrixGroups, visibleJobs);
|
|
248
|
-
return visibleJobs;
|
|
249
|
-
}
|
|
250
|
-
function computeGraphLayout(engine, jobs, matrixGroups, layout) {
|
|
251
|
-
const visibleJobs = displayJobsOf(engine, jobs, matrixGroups);
|
|
252
|
-
const allDeps = {};
|
|
253
|
-
for (const jobName of Object.keys(visibleJobs)) allDeps[jobName] = engine.jobDependencies(jobName, visibleJobs, allDeps);
|
|
254
|
-
const filteredDeps = {};
|
|
255
|
-
for (const jobName of Object.keys(visibleJobs)) {
|
|
256
|
-
const needs = visibleJobs[jobName]?.needs;
|
|
257
|
-
const oldNeeds = Array.isArray(needs) ? [...new Set(needs.map((need) => typeof need === "string" && engine.editing ? engine.editing.needTarget(need) : need))] : [];
|
|
258
|
-
filteredDeps[jobName] = oldNeeds.filter((dep) => {
|
|
259
|
-
return !oldNeeds.some((other) => {
|
|
260
|
-
if (other === dep) return false;
|
|
261
|
-
return allDeps[other]?.has(dep) === true;
|
|
262
|
-
});
|
|
263
|
-
}).sort();
|
|
264
|
-
}
|
|
265
|
-
const depended_on = {};
|
|
266
|
-
for (const jobName of Object.keys(visibleJobs)) for (const dep of filteredDeps[jobName] ?? []) {
|
|
267
|
-
depended_on[dep] ??= [];
|
|
268
|
-
depended_on[dep].push(jobName);
|
|
269
|
-
}
|
|
270
|
-
for (const dependents of Object.values(depended_on)) dependents.sort();
|
|
271
|
-
const unfinished = new Set(Object.keys(visibleJobs));
|
|
272
|
-
const rootLevel = [];
|
|
273
|
-
const deps = [rootLevel];
|
|
274
|
-
for (const jobName of unfinished) if (filteredDeps[jobName]?.length === 0) {
|
|
275
|
-
rootLevel.push(jobName);
|
|
276
|
-
unfinished.delete(jobName);
|
|
277
|
-
}
|
|
278
|
-
let prevLen;
|
|
279
|
-
do {
|
|
280
|
-
const toAppend = [];
|
|
281
|
-
const pending = new Set(unfinished);
|
|
282
|
-
prevLen = pending.size;
|
|
283
|
-
for (const jobName of pending) if ((filteredDeps[jobName] ?? []).every((dep) => !pending.has(dep))) {
|
|
284
|
-
toAppend.push(jobName);
|
|
285
|
-
unfinished.delete(jobName);
|
|
286
|
-
}
|
|
287
|
-
if (toAppend.length > 0) deps.push(toAppend);
|
|
288
|
-
} while (prevLen !== unfinished.size);
|
|
289
|
-
const together = (head, jobName) => {
|
|
290
|
-
const depsA = depended_on[head];
|
|
291
|
-
const depsB = depended_on[jobName];
|
|
292
|
-
const depsA2 = filteredDeps[head];
|
|
293
|
-
const depsB2 = filteredDeps[jobName];
|
|
294
|
-
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]));
|
|
295
|
-
};
|
|
296
|
-
const alone = (job) => !!visibleJobs[job]?._matrixGroup;
|
|
297
|
-
const editing = engine.editing;
|
|
298
|
-
const laidOut = layout && editing?.hasLayout(layout) ? unitsOnly(editing.boxesFromLayout(Object.keys(visibleJobs), filteredDeps, withLoneMatrixSlots(editing, layout, visibleJobs, matrixGroups), {
|
|
299
|
-
together,
|
|
300
|
-
alone
|
|
301
|
-
}), together) : null;
|
|
302
|
-
const finalDeps = laidOut ? laidOut.map((col) => col.boxes) : [];
|
|
303
|
-
if (!laidOut) deps.forEach((col) => {
|
|
304
|
-
const toAppend = [];
|
|
305
|
-
while (col.length > 0) {
|
|
306
|
-
const head = col[0];
|
|
307
|
-
if (head === void 0) break;
|
|
308
|
-
const grouped = [head];
|
|
309
|
-
const toRm = [0];
|
|
310
|
-
col.slice(1).forEach((jobName, j) => {
|
|
311
|
-
if (!alone(head) && !alone(jobName) && together(head, jobName)) {
|
|
312
|
-
grouped.push(jobName);
|
|
313
|
-
toRm.push(j + 1);
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
col.splice(0, col.length, ...col.filter((_, i) => !toRm.includes(i)));
|
|
317
|
-
toAppend.push(grouped);
|
|
318
|
-
}
|
|
319
|
-
finalDeps.push(toAppend);
|
|
320
|
-
});
|
|
321
|
-
if (finalDeps[0]?.length === 0) {
|
|
322
|
-
finalDeps.shift();
|
|
323
|
-
laidOut?.shift();
|
|
324
|
-
}
|
|
325
|
-
const ancestorDists = {};
|
|
326
|
-
const descendantDists = {};
|
|
327
|
-
const jobNames = Object.keys(visibleJobs);
|
|
328
|
-
const reverseDeps = {};
|
|
329
|
-
for (const [job, depList] of Object.entries(filteredDeps)) for (const dep of depList) {
|
|
330
|
-
if (!reverseDeps[dep]) reverseDeps[dep] = [];
|
|
331
|
-
reverseDeps[dep].push(job);
|
|
332
|
-
}
|
|
333
|
-
for (const start of jobNames) {
|
|
334
|
-
const aDist = /* @__PURE__ */ new Map();
|
|
335
|
-
const q1 = [[start, 0]];
|
|
336
|
-
for (let next = q1.shift(); next; next = q1.shift()) {
|
|
337
|
-
const [job, d] = next;
|
|
338
|
-
for (const dep of filteredDeps[job] ?? []) if (!aDist.has(dep)) {
|
|
339
|
-
aDist.set(dep, d + 1);
|
|
340
|
-
q1.push([dep, d + 1]);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
ancestorDists[start] = aDist;
|
|
344
|
-
const dDist = /* @__PURE__ */ new Map();
|
|
345
|
-
const q2 = [[start, 0]];
|
|
346
|
-
for (let next = q2.shift(); next; next = q2.shift()) {
|
|
347
|
-
const [job, d] = next;
|
|
348
|
-
for (const child of reverseDeps[job] ?? []) if (!dDist.has(child)) {
|
|
349
|
-
dDist.set(child, d + 1);
|
|
350
|
-
q2.push([child, d + 1]);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
descendantDists[start] = dDist;
|
|
354
|
-
}
|
|
355
|
-
return {
|
|
356
|
-
dependencyCols: finalDeps,
|
|
357
|
-
/** Each box's row; above a box, rows the layout leaves empty stay as space. */
|
|
358
|
-
rowSlots: laidOut ? laidOut.map((col) => col.rows) : finalDeps.map((col) => col.map((_, i) => i)),
|
|
359
|
-
/** Each column's number; between two drawn columns, numbers skipped stay as space. */
|
|
360
|
-
colSlots: laidOut ? laidOut.map((col) => col.column) : finalDeps.map((_, i) => i),
|
|
361
|
-
directDeps: filteredDeps,
|
|
362
|
-
displayJobs: visibleJobs,
|
|
363
|
-
ancestorDists,
|
|
364
|
-
descendantDists
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
209
|
function jobHandlers({ engine, jobs, displayJobs, pathPrefix, stepsOpen, toggleSteps, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, renderWell, editStep }) {
|
|
368
210
|
const isStepsOpen = (j) => stepsOpen.has(pathPrefix + j);
|
|
369
211
|
const subworkflowKey = (j, s) => `${pathPrefix}${j}:${s}`;
|
|
@@ -407,10 +249,13 @@ function SubworkflowWell({ expanded, onSettled, className, children }) {
|
|
|
407
249
|
});
|
|
408
250
|
}
|
|
409
251
|
var SUBGRAPH_Z_STEP = 100;
|
|
252
|
+
var FADE_NODES = 300;
|
|
410
253
|
var GraphEditorOverlays = lazy(() => import("./GraphEditor.js"));
|
|
411
|
-
var CONNECTOR_COLOR = "var(--theme-border)";
|
|
412
|
-
var HIGHLIGHT_COLOR = "var(--theme-element)";
|
|
413
254
|
var FIT_ANIMATION_MS = 300;
|
|
255
|
+
var ConnectorClock = class extends Store {
|
|
256
|
+
bump = () => this.notify();
|
|
257
|
+
};
|
|
258
|
+
var ConnectorClockContext = createContext(null);
|
|
414
259
|
function sizesSettled(els) {
|
|
415
260
|
return new Promise((resolve) => {
|
|
416
261
|
let frame = 0;
|
|
@@ -429,33 +274,36 @@ function sizesSettled(els) {
|
|
|
429
274
|
function sizingTransitions(el) {
|
|
430
275
|
return el.getAnimations({ subtree: true }).filter((animation) => animation instanceof CSSTransition && (animation.transitionProperty === "grid-template-rows" || animation.transitionProperty === "width"));
|
|
431
276
|
}
|
|
432
|
-
function intoView(start, end, low, high) {
|
|
433
|
-
if (end - start > high - low) return 0;
|
|
434
|
-
if (start < low) return low - start;
|
|
435
|
-
return end > high ? high - end : 0;
|
|
436
|
-
}
|
|
437
277
|
var HOLD_MS = 2e3;
|
|
438
|
-
var
|
|
439
|
-
function
|
|
278
|
+
var skippedBefore = (slots, i) => (slots?.[i] ?? i) - (i === 0 ? 0 : (slots?.[i - 1] ?? i - 1) + 1);
|
|
279
|
+
function measureBoxes(cols, pathPrefix, wrapper) {
|
|
280
|
+
const boxes = /* @__PURE__ */ new Map();
|
|
281
|
+
for (const col of cols) for (const [head] of col) {
|
|
282
|
+
const el = head === void 0 ? null : document.getElementById(`node_${pathPrefix}${head}`);
|
|
283
|
+
if (head !== void 0 && el) boxes.set(head, {
|
|
284
|
+
...offsetWithin(el, wrapper),
|
|
285
|
+
width: el.offsetWidth
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return boxes;
|
|
289
|
+
}
|
|
290
|
+
var Subgraph = memo(function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, invalidateConnectors, requestFit, stepsOpen, toggleSteps, matrixOpen, toggleMatrix, onReady, layout, graph, editable = false }) {
|
|
440
291
|
const engine = useWorkflowEngine();
|
|
292
|
+
useStore(useContext(ConnectorClockContext), (clock) => clock.version, 0);
|
|
441
293
|
const wrapperRef = useRef(null);
|
|
294
|
+
const routedRef = useRef(null);
|
|
442
295
|
const editorApi = useGraphEditor();
|
|
443
296
|
const selectedEdges = useSelectedEdges(editable ? editorApi : null);
|
|
444
297
|
const zBase = depth * SUBGRAPH_Z_STEP;
|
|
445
|
-
const [hoveredJob, setHoveredJob] = useState(null);
|
|
446
|
-
const lastHoveredDistancesRef = useRef(null);
|
|
447
|
-
const maxHoveredDistRef = useRef(0);
|
|
448
|
-
const retractPathLensRef = useRef(/* @__PURE__ */ new Map());
|
|
449
|
-
const matrixGroups = useMemo(() => engine.matrixGroups(jobs), [engine, jobs]);
|
|
450
298
|
const placed = useMemo(() => layout ?? (depth > 0 ? positionsOf(jobs) : void 0), [
|
|
451
299
|
layout,
|
|
452
300
|
depth,
|
|
453
301
|
jobs
|
|
454
302
|
]);
|
|
455
|
-
const { dependencyCols, rowSlots, colSlots, directDeps,
|
|
303
|
+
const { dependencyCols, rowSlots, colSlots, directDeps, dependents, displayJobs } = useMemo(() => graph ?? computeGraphLayout(engine, jobs, engine.matrixGroups(jobs), placed), [
|
|
304
|
+
graph,
|
|
456
305
|
engine,
|
|
457
306
|
jobs,
|
|
458
|
-
matrixGroups,
|
|
459
307
|
placed
|
|
460
308
|
]);
|
|
461
309
|
useEffect(() => {
|
|
@@ -475,43 +323,27 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
475
323
|
rowSlots,
|
|
476
324
|
colSlots
|
|
477
325
|
]);
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
hoveredJob,
|
|
489
|
-
ancestorDists,
|
|
490
|
-
descendantDists
|
|
326
|
+
const lineage = useMemo(() => new Lineage((job) => hopDistances(job, directDeps, dependents), {
|
|
327
|
+
animT,
|
|
328
|
+
depth,
|
|
329
|
+
fade: dependencyCols.reduce((n, col) => n + col.length, 0) <= FADE_NODES
|
|
330
|
+
}), [
|
|
331
|
+
directDeps,
|
|
332
|
+
dependents,
|
|
333
|
+
animT,
|
|
334
|
+
depth,
|
|
335
|
+
dependencyCols
|
|
491
336
|
]);
|
|
492
|
-
if (hoveredDistances) {
|
|
493
|
-
lastHoveredDistancesRef.current = hoveredDistances;
|
|
494
|
-
maxHoveredDistRef.current = Math.max(...hoveredDistances.values());
|
|
495
|
-
}
|
|
496
|
-
const activeDists = hoveredDistances ?? lastHoveredDistancesRef.current;
|
|
497
337
|
useEffect(() => {
|
|
498
|
-
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}, [
|
|
507
|
-
hoveredJob,
|
|
508
|
-
invalidateConnectors,
|
|
509
|
-
animT
|
|
510
|
-
]);
|
|
511
|
-
const hoveredRelated = useMemo(() => {
|
|
512
|
-
if (!hoveredDistances) return null;
|
|
513
|
-
return new Set(hoveredDistances.keys());
|
|
514
|
-
}, [hoveredDistances]);
|
|
338
|
+
const wrapper = wrapperRef.current;
|
|
339
|
+
const dim = () => wrapper && setDimmed(wrapper, lineage.depth, lineage.hovering);
|
|
340
|
+
dim();
|
|
341
|
+
const unsubscribe = lineage.subscribe(dim);
|
|
342
|
+
return () => {
|
|
343
|
+
unsubscribe();
|
|
344
|
+
lineage.dispose();
|
|
345
|
+
};
|
|
346
|
+
}, [lineage]);
|
|
515
347
|
useEffect(() => {
|
|
516
348
|
const raf = requestAnimationFrame(() => {
|
|
517
349
|
invalidateConnectors();
|
|
@@ -550,394 +382,207 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
550
382
|
expandedSubworkflows,
|
|
551
383
|
invalidateConnectors
|
|
552
384
|
]);
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
toggleSubworkflow
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
toggleMatrix
|
|
589
|
-
})
|
|
385
|
+
const handlers = useMemo(() => jobHandlers({
|
|
386
|
+
engine,
|
|
387
|
+
jobs,
|
|
388
|
+
displayJobs,
|
|
389
|
+
pathPrefix,
|
|
390
|
+
stepsOpen,
|
|
391
|
+
toggleSteps,
|
|
392
|
+
expandedSubworkflows,
|
|
393
|
+
toggleSubworkflow: (key) => {
|
|
394
|
+
toggleSubworkflow(key);
|
|
395
|
+
requestAnimationFrame(invalidateConnectors);
|
|
396
|
+
},
|
|
397
|
+
openInNewGraph,
|
|
398
|
+
setSublogOpen,
|
|
399
|
+
editStep: editable && editorApi ? (j, s) => editorApi.editStep(j, s) : void 0,
|
|
400
|
+
renderWell: (subJobs, subPrefix, expanded) => /* @__PURE__ */ jsx(SubworkflowWell, {
|
|
401
|
+
expanded,
|
|
402
|
+
onSettled: requestFit,
|
|
403
|
+
className: "my-2 rounded-lg border-4 border-(--theme-border)",
|
|
404
|
+
children: /* @__PURE__ */ jsx(NestedSubgraph, {
|
|
405
|
+
jobs: subJobs,
|
|
406
|
+
pathPrefix: subPrefix,
|
|
407
|
+
depth: depth + 1,
|
|
408
|
+
preview,
|
|
409
|
+
animT,
|
|
410
|
+
expandedSubworkflows,
|
|
411
|
+
toggleSubworkflow,
|
|
412
|
+
openInNewGraph,
|
|
413
|
+
setSublogOpen,
|
|
414
|
+
invalidateConnectors,
|
|
415
|
+
requestFit,
|
|
416
|
+
stepsOpen,
|
|
417
|
+
toggleSteps,
|
|
418
|
+
matrixOpen,
|
|
419
|
+
toggleMatrix
|
|
590
420
|
})
|
|
591
|
-
})
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
})]
|
|
646
|
-
})]
|
|
647
|
-
}, `node_${first}`);
|
|
648
|
-
})
|
|
649
|
-
}, col[0]?.[0]);
|
|
421
|
+
})
|
|
422
|
+
}), [
|
|
423
|
+
engine,
|
|
424
|
+
jobs,
|
|
425
|
+
displayJobs,
|
|
426
|
+
pathPrefix,
|
|
427
|
+
stepsOpen,
|
|
428
|
+
toggleSteps,
|
|
429
|
+
expandedSubworkflows,
|
|
430
|
+
toggleSubworkflow,
|
|
431
|
+
openInNewGraph,
|
|
432
|
+
setSublogOpen,
|
|
433
|
+
editable,
|
|
434
|
+
editorApi,
|
|
435
|
+
requestFit,
|
|
436
|
+
depth,
|
|
437
|
+
preview,
|
|
438
|
+
animT,
|
|
439
|
+
invalidateConnectors,
|
|
440
|
+
matrixOpen,
|
|
441
|
+
toggleMatrix
|
|
442
|
+
]);
|
|
443
|
+
const nodes = useMemo(() => /* @__PURE__ */ jsx("div", {
|
|
444
|
+
className: "flex relative",
|
|
445
|
+
children: dependencyCols.map((col, c) => /* @__PURE__ */ jsx("div", {
|
|
446
|
+
style: emptyColumnsStyle(skippedBefore(colSlots, c)),
|
|
447
|
+
children: col.map((jobNames, i) => {
|
|
448
|
+
const first = jobNames[0];
|
|
449
|
+
if (first === void 0) return null;
|
|
450
|
+
const shell = {
|
|
451
|
+
rowsAbove: skippedBefore(rowSlots[c], i),
|
|
452
|
+
zBase
|
|
453
|
+
};
|
|
454
|
+
const matrixGroup = displayJobs[first]?._matrixGroup;
|
|
455
|
+
return matrixGroup ? /* @__PURE__ */ jsx(MatrixGroupNode, {
|
|
456
|
+
...shell,
|
|
457
|
+
matrixGroup,
|
|
458
|
+
jobNames,
|
|
459
|
+
idPrefix: pathPrefix,
|
|
460
|
+
isExpanded: matrixOpen.has(pathPrefix + matrixGroup.originaljob),
|
|
461
|
+
toggleMatrix,
|
|
462
|
+
jobs,
|
|
463
|
+
handlers,
|
|
464
|
+
preview,
|
|
465
|
+
editable
|
|
466
|
+
}, `node_${first}`) : /* @__PURE__ */ jsx(JobNode, {
|
|
467
|
+
...shell,
|
|
468
|
+
id: `node_${pathPrefix}${first}`,
|
|
469
|
+
jobNames,
|
|
470
|
+
jobs: displayJobs,
|
|
471
|
+
handlers,
|
|
472
|
+
preview,
|
|
473
|
+
editable
|
|
474
|
+
}, `node_${first}`);
|
|
650
475
|
})
|
|
651
|
-
})
|
|
652
|
-
}, [
|
|
476
|
+
}, col[0]?.[0]))
|
|
477
|
+
}), [
|
|
653
478
|
dependencyCols,
|
|
654
479
|
rowSlots,
|
|
655
480
|
colSlots,
|
|
656
481
|
displayJobs,
|
|
657
482
|
jobs,
|
|
658
|
-
stepsOpen,
|
|
659
483
|
matrixOpen,
|
|
660
|
-
expandedSubworkflows,
|
|
661
|
-
hoveredRelated,
|
|
662
|
-
activeDists,
|
|
663
|
-
animT,
|
|
664
484
|
zBase,
|
|
665
485
|
preview,
|
|
666
486
|
pathPrefix,
|
|
667
|
-
depth,
|
|
668
|
-
toggleSteps,
|
|
669
|
-
toggleSubworkflow,
|
|
670
487
|
toggleMatrix,
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
engine,
|
|
674
|
-
invalidateConnectors,
|
|
675
|
-
requestFit,
|
|
676
|
-
editable,
|
|
677
|
-
editorApi
|
|
488
|
+
handlers,
|
|
489
|
+
editable
|
|
678
490
|
]);
|
|
679
|
-
const memoizedBoxLayer = useMemo(() => buildBoxLayer(), [buildBoxLayer]);
|
|
680
|
-
const hasLiveNestedGraph = Array.from(expandedSubworkflows).some((k) => k.startsWith(pathPrefix));
|
|
681
491
|
if (!dependencyCols[0]?.length) return null;
|
|
492
|
+
const wrapper = wrapperRef.current;
|
|
493
|
+
const measured = wrapper ? measureBoxes(dependencyCols, pathPrefix, wrapper) : /* @__PURE__ */ new Map();
|
|
494
|
+
const last = routedRef.current;
|
|
495
|
+
const routed = last && last.directDeps === directDeps && sameBoxes(last.boxes, measured) ? last : {
|
|
496
|
+
boxes: measured,
|
|
497
|
+
directDeps,
|
|
498
|
+
edges: routeConnectors(dependencyCols, colSlots.some((column, c) => column !== c), directDeps, measured, 37)
|
|
499
|
+
};
|
|
500
|
+
routedRef.current = routed;
|
|
501
|
+
const { boxes, edges } = routed;
|
|
682
502
|
return /* @__PURE__ */ jsxs("div", {
|
|
683
503
|
ref: wrapperRef,
|
|
684
504
|
className: "relative",
|
|
685
|
-
children: [
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
for (const dep of depsOf(first)) {
|
|
708
|
-
const s = gid(dep);
|
|
709
|
-
const e = gid(first);
|
|
710
|
-
if (!s || !e) continue;
|
|
711
|
-
const dy = Math.abs(nodeConnectorY(e) - nodeConnectorY(s));
|
|
712
|
-
if (dy > 0 && dy < minAdy) minAdy = dy;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
const MAX_ARC_R = 16;
|
|
716
|
-
const arcR = Math.min(minAdy === Number.POSITIVE_INFINITY ? MAX_ARC_R : minAdy / 4, colGap / 2, MAX_ARC_R);
|
|
717
|
-
const ports = (jobNames) => {
|
|
718
|
-
const [head] = jobNames;
|
|
719
|
-
const el = head === void 0 ? null : gid(head);
|
|
720
|
-
if (head === void 0 || !el) return null;
|
|
721
|
-
const y = nodeConnectorY(el);
|
|
722
|
-
const wiredIn = depsOf(head).some((dep) => gid(dep));
|
|
723
|
-
const wiredOut = dependencyCols.some((c) => c.some(([other = ""]) => depsOf(other).includes(head) && !!gid(other)));
|
|
724
|
-
return /* @__PURE__ */ jsx(NodePorts, {
|
|
725
|
-
jobs: jobNames,
|
|
726
|
-
left: {
|
|
727
|
-
x: ox(el) + 2,
|
|
728
|
-
y
|
|
729
|
-
},
|
|
730
|
-
right: {
|
|
731
|
-
x: ox(el) + el.offsetWidth - 2,
|
|
732
|
-
y
|
|
733
|
-
},
|
|
734
|
-
drawLeft: !wiredIn,
|
|
735
|
-
drawRight: !wiredOut,
|
|
736
|
-
zIndex: 40 + zBase
|
|
737
|
-
});
|
|
738
|
-
};
|
|
739
|
-
const hits = [];
|
|
740
|
-
const connectors = dependencyCols.map((col) => /* @__PURE__ */ jsx(React.Fragment, { children: col.map((jobNames) => {
|
|
741
|
-
const first = jobNames[0];
|
|
742
|
-
if (first === void 0) return null;
|
|
743
|
-
return /* @__PURE__ */ jsxs(React.Fragment, { children: [editable && ports(jobNames), depsOf(first).map((dep) => {
|
|
744
|
-
const isHighlighted = hoveredRelated?.has(first) && hoveredRelated?.has(dep);
|
|
745
|
-
const depDist = activeDists?.get(dep) ?? 0;
|
|
746
|
-
const targetDist = activeDists?.get(first) ?? 0;
|
|
747
|
-
const closerDist = Math.min(depDist, targetDist);
|
|
748
|
-
const connectorDelay = closerDist * animT;
|
|
749
|
-
const retractDelay = (maxHoveredDistRef.current - closerDist) * animT;
|
|
750
|
-
const drawRightToLeft = targetDist < depDist;
|
|
751
|
-
const start = gid(dep);
|
|
752
|
-
const end = gid(first);
|
|
753
|
-
if (!start || !end) return null;
|
|
754
|
-
const x1 = ox(start) + start.offsetWidth - 2;
|
|
755
|
-
const y1 = nodeConnectorY(start);
|
|
756
|
-
const x2 = ox(end) + 2;
|
|
757
|
-
const y2 = nodeConnectorY(end);
|
|
758
|
-
const selected = selectedEdges.some((edge) => edge.from === dep && edge.to === first);
|
|
759
|
-
const dy = y2 - y1;
|
|
760
|
-
const ady = Math.abs(dy);
|
|
761
|
-
let pathD;
|
|
762
|
-
let pathLen;
|
|
763
|
-
let pathDReversed;
|
|
764
|
-
const r = arcR;
|
|
765
|
-
if (ady === 0) {
|
|
766
|
-
pathD = `M ${x1} ${y1} L ${x2} ${y2}`;
|
|
767
|
-
pathDReversed = `M ${x2} ${y2} L ${x1} ${y1}`;
|
|
768
|
-
pathLen = x2 - x1;
|
|
769
|
-
} else {
|
|
770
|
-
const s = dy > 0 ? 1 : -1;
|
|
771
|
-
const ax2end = x2 - (colGap / 2 - r);
|
|
772
|
-
const ax = ax2end - 2 * r;
|
|
773
|
-
const sw1 = dy > 0 ? 1 : 0;
|
|
774
|
-
const sw2 = dy > 0 ? 0 : 1;
|
|
775
|
-
pathD = [
|
|
776
|
-
`M ${x1} ${y1}`,
|
|
777
|
-
`L ${ax} ${y1}`,
|
|
778
|
-
`A ${r} ${r} 0 0 ${sw1} ${ax + r} ${y1 + s * r}`,
|
|
779
|
-
`L ${ax + r} ${y2 - s * r}`,
|
|
780
|
-
`A ${r} ${r} 0 0 ${sw2} ${ax2end} ${y2}`,
|
|
781
|
-
`L ${x2} ${y2}`
|
|
782
|
-
].join(" ");
|
|
783
|
-
pathDReversed = [
|
|
784
|
-
`M ${x2} ${y2}`,
|
|
785
|
-
`L ${ax2end} ${y2}`,
|
|
786
|
-
`A ${r} ${r} 0 0 ${sw1} ${ax + r} ${y2 - s * r}`,
|
|
787
|
-
`L ${ax + r} ${y1 + s * r}`,
|
|
788
|
-
`A ${r} ${r} 0 0 ${sw2} ${ax} ${y1}`,
|
|
789
|
-
`L ${x1} ${y1}`
|
|
790
|
-
].join(" ");
|
|
791
|
-
const arcLen = Math.PI * r / 2;
|
|
792
|
-
const vSeg = Math.max(0, ady - 2 * r);
|
|
793
|
-
pathLen = ax - x1 + arcLen + vSeg + arcLen + (x2 - ax2end);
|
|
794
|
-
}
|
|
795
|
-
if (editable) hits.push(/* @__PURE__ */ jsxs(React.Fragment, { children: [selected && /* @__PURE__ */ jsx("path", {
|
|
796
|
-
d: pathD,
|
|
797
|
-
stroke: "var(--theme-element)",
|
|
798
|
-
strokeWidth: "10",
|
|
799
|
-
fill: "transparent"
|
|
800
|
-
}), /* @__PURE__ */ jsx(EdgeHitPath, {
|
|
801
|
-
d: pathD,
|
|
802
|
-
edge: {
|
|
803
|
-
from: dep,
|
|
804
|
-
to: first
|
|
805
|
-
}
|
|
806
|
-
})] }, `${dep}→${first}`));
|
|
807
|
-
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
808
|
-
/* @__PURE__ */ jsxs("svg", {
|
|
809
|
-
"aria-hidden": "true",
|
|
810
|
-
overflow: "visible",
|
|
811
|
-
className: "absolute pointer-events-none",
|
|
812
|
-
style: { zIndex: (isHighlighted || activeDists?.has(dep) && activeDists?.has(first) ? 30 : 10) + zBase },
|
|
813
|
-
children: [
|
|
814
|
-
/* @__PURE__ */ jsx("rect", {
|
|
815
|
-
x: x1 - 16,
|
|
816
|
-
y: y1 - 16,
|
|
817
|
-
width: 32,
|
|
818
|
-
height: 32,
|
|
819
|
-
fill: "var(--theme-panel-bg)"
|
|
820
|
-
}),
|
|
821
|
-
/* @__PURE__ */ jsx("rect", {
|
|
822
|
-
x: x2 - 16,
|
|
823
|
-
y: y2 - 16,
|
|
824
|
-
width: 32,
|
|
825
|
-
height: 32,
|
|
826
|
-
fill: "var(--theme-panel-bg)"
|
|
827
|
-
}),
|
|
828
|
-
/* @__PURE__ */ jsx("circle", {
|
|
829
|
-
cx: x1,
|
|
830
|
-
cy: y1,
|
|
831
|
-
r: "8",
|
|
832
|
-
fill: isHighlighted ? HIGHLIGHT_COLOR : CONNECTOR_COLOR,
|
|
833
|
-
style: {
|
|
834
|
-
opacity: hoveredRelated && !isHighlighted ? .3 : 1,
|
|
835
|
-
transition: isHighlighted ? `fill ${animT}s ${depDist * animT}s, opacity 0s` : `fill ${animT}s ${(maxHoveredDistRef.current - depDist) * animT}s, opacity 0s`
|
|
836
|
-
}
|
|
837
|
-
}),
|
|
838
|
-
/* @__PURE__ */ jsx("circle", {
|
|
839
|
-
cx: x2,
|
|
840
|
-
cy: y2,
|
|
841
|
-
r: "8",
|
|
842
|
-
fill: isHighlighted ? HIGHLIGHT_COLOR : CONNECTOR_COLOR,
|
|
843
|
-
style: {
|
|
844
|
-
opacity: hoveredRelated && !isHighlighted ? .3 : 1,
|
|
845
|
-
transition: isHighlighted ? `fill ${animT}s ${targetDist * animT}s, opacity 0s` : `fill ${animT}s ${(maxHoveredDistRef.current - targetDist) * animT}s, opacity 0s`
|
|
846
|
-
}
|
|
847
|
-
})
|
|
848
|
-
]
|
|
849
|
-
}),
|
|
850
|
-
/* @__PURE__ */ jsxs("svg", {
|
|
851
|
-
"aria-hidden": "true",
|
|
852
|
-
overflow: "visible",
|
|
853
|
-
className: "absolute pointer-events-none",
|
|
854
|
-
style: { zIndex: (isHighlighted ? 20 : -1) + zBase },
|
|
855
|
-
children: [/* @__PURE__ */ jsx("path", {
|
|
856
|
-
d: pathD,
|
|
857
|
-
stroke: "var(--theme-panel-bg)",
|
|
858
|
-
strokeWidth: "6",
|
|
859
|
-
fill: "transparent"
|
|
860
|
-
}), /* @__PURE__ */ jsx("path", {
|
|
861
|
-
d: pathD,
|
|
862
|
-
stroke: CONNECTOR_COLOR,
|
|
863
|
-
strokeWidth: "6",
|
|
864
|
-
fill: "transparent",
|
|
865
|
-
style: {
|
|
866
|
-
opacity: hoveredRelated && !isHighlighted ? .3 : 1,
|
|
867
|
-
transition: `opacity 0s`
|
|
868
|
-
}
|
|
869
|
-
})]
|
|
870
|
-
}),
|
|
871
|
-
/* @__PURE__ */ jsxs("svg", {
|
|
872
|
-
"aria-hidden": "true",
|
|
873
|
-
overflow: "visible",
|
|
874
|
-
className: "absolute pointer-events-none",
|
|
875
|
-
style: { zIndex: 20 + zBase },
|
|
876
|
-
children: [/* @__PURE__ */ jsx("path", {
|
|
877
|
-
d: drawRightToLeft ? pathDReversed : pathD,
|
|
878
|
-
fill: "transparent",
|
|
879
|
-
style: {
|
|
880
|
-
stroke: HIGHLIGHT_COLOR,
|
|
881
|
-
strokeWidth: 6,
|
|
882
|
-
strokeDasharray: `${pathLen} ${pathLen}`,
|
|
883
|
-
strokeDashoffset: isHighlighted ? 0 : pathLen,
|
|
884
|
-
opacity: isHighlighted ? 1 : 0,
|
|
885
|
-
transition: isHighlighted ? `stroke-dashoffset ${animT}s ease ${connectorDelay}s, opacity 0s ease ${connectorDelay}s` : "stroke-dashoffset 0s, opacity 0s"
|
|
886
|
-
}
|
|
887
|
-
}), (() => {
|
|
888
|
-
const connKey = `${dep}→${first}`;
|
|
889
|
-
if (isHighlighted) retractPathLensRef.current.set(connKey, pathLen);
|
|
890
|
-
const isRetracting = !isHighlighted && !!activeDists?.has(dep) && !!activeDists?.has(first);
|
|
891
|
-
if (!isHighlighted && !isRetracting) return null;
|
|
892
|
-
const frozenLen = retractPathLensRef.current.get(connKey) ?? pathLen;
|
|
893
|
-
return /* @__PURE__ */ jsx("path", {
|
|
894
|
-
d: drawRightToLeft ? pathDReversed : pathD,
|
|
895
|
-
fill: "transparent",
|
|
896
|
-
style: {
|
|
897
|
-
stroke: HIGHLIGHT_COLOR,
|
|
898
|
-
strokeWidth: 6,
|
|
899
|
-
strokeDasharray: `${frozenLen} ${frozenLen}`,
|
|
900
|
-
strokeDashoffset: isHighlighted ? 0 : frozenLen,
|
|
901
|
-
opacity: isHighlighted ? 0 : 1,
|
|
902
|
-
transition: isHighlighted ? "stroke-dashoffset 0s, opacity 0s" : `stroke-dashoffset ${animT}s ease ${retractDelay}s, opacity 0s`
|
|
903
|
-
}
|
|
904
|
-
});
|
|
905
|
-
})()]
|
|
906
|
-
}),
|
|
907
|
-
editable && selected && /* @__PURE__ */ jsx(EdgeEnds, {
|
|
908
|
-
edge: {
|
|
909
|
-
from: dep,
|
|
910
|
-
to: first
|
|
911
|
-
},
|
|
912
|
-
start: {
|
|
913
|
-
x: x1,
|
|
914
|
-
y: y1
|
|
915
|
-
},
|
|
916
|
-
end: {
|
|
917
|
-
x: x2,
|
|
918
|
-
y: y2
|
|
919
|
-
},
|
|
920
|
-
zIndex: 45 + zBase
|
|
921
|
-
})
|
|
922
|
-
] }, dep);
|
|
923
|
-
})] }, first);
|
|
924
|
-
}) }, col[0]?.[0]));
|
|
925
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [connectors, editable && /* @__PURE__ */ jsx("svg", {
|
|
926
|
-
role: "none",
|
|
927
|
-
overflow: "visible",
|
|
928
|
-
className: "absolute pointer-events-none",
|
|
929
|
-
width: wrapper?.offsetWidth,
|
|
930
|
-
height: wrapper?.offsetHeight,
|
|
931
|
-
style: { zIndex: 1 + zBase },
|
|
932
|
-
children: hits
|
|
933
|
-
})] });
|
|
934
|
-
})(),
|
|
935
|
-
hasLiveNestedGraph ? buildBoxLayer() : memoizedBoxLayer,
|
|
936
|
-
editable && /* @__PURE__ */ jsx(GraphEditorCanvas, {})
|
|
937
|
-
]
|
|
505
|
+
children: [/* @__PURE__ */ jsxs(LineageContext, {
|
|
506
|
+
value: lineage,
|
|
507
|
+
children: [
|
|
508
|
+
/* @__PURE__ */ jsx(DimRules, { depth }),
|
|
509
|
+
/* @__PURE__ */ jsx(ConnectorLayers, {
|
|
510
|
+
edges,
|
|
511
|
+
zBase
|
|
512
|
+
}),
|
|
513
|
+
editable && /* @__PURE__ */ jsx(EditorEdges, {
|
|
514
|
+
edges,
|
|
515
|
+
cols: dependencyCols,
|
|
516
|
+
boxes,
|
|
517
|
+
selected: selectedEdges,
|
|
518
|
+
zBase,
|
|
519
|
+
size: wrapper ? {
|
|
520
|
+
width: wrapper.offsetWidth,
|
|
521
|
+
height: wrapper.offsetHeight
|
|
522
|
+
} : void 0
|
|
523
|
+
}),
|
|
524
|
+
nodes
|
|
525
|
+
]
|
|
526
|
+
}), editable && /* @__PURE__ */ jsx(GraphEditorCanvas, {})]
|
|
938
527
|
});
|
|
939
|
-
}
|
|
528
|
+
});
|
|
940
529
|
var NestedSubgraph = Subgraph;
|
|
530
|
+
function EditorEdges({ edges, cols, boxes, selected, zBase, size }) {
|
|
531
|
+
const wiredIn = new Set(edges.map((edge) => edge.to));
|
|
532
|
+
const wiredOut = new Set(edges.map((edge) => edge.from));
|
|
533
|
+
const chosen = new Set(selected.map((edge) => `${edge.from}→${edge.to}`));
|
|
534
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
535
|
+
cols.flatMap((col) => col.map((jobNames) => {
|
|
536
|
+
const [head] = jobNames;
|
|
537
|
+
const box = head === void 0 ? void 0 : boxes.get(head);
|
|
538
|
+
if (head === void 0 || !box) return null;
|
|
539
|
+
const y = box.y + 37;
|
|
540
|
+
return /* @__PURE__ */ jsx(NodePorts, {
|
|
541
|
+
jobs: jobNames,
|
|
542
|
+
left: {
|
|
543
|
+
x: box.x + 2,
|
|
544
|
+
y
|
|
545
|
+
},
|
|
546
|
+
right: {
|
|
547
|
+
x: box.x + box.width - 2,
|
|
548
|
+
y
|
|
549
|
+
},
|
|
550
|
+
drawLeft: !wiredIn.has(head),
|
|
551
|
+
drawRight: !wiredOut.has(head),
|
|
552
|
+
zIndex: 40 + zBase
|
|
553
|
+
}, head);
|
|
554
|
+
})),
|
|
555
|
+
edges.map(({ from, to, start, end }) => chosen.has(`${from}→${to}`) && /* @__PURE__ */ jsx(EdgeEnds, {
|
|
556
|
+
edge: {
|
|
557
|
+
from,
|
|
558
|
+
to
|
|
559
|
+
},
|
|
560
|
+
start,
|
|
561
|
+
end,
|
|
562
|
+
zIndex: 45 + zBase
|
|
563
|
+
}, `${from}→${to}`)),
|
|
564
|
+
/* @__PURE__ */ jsx("svg", {
|
|
565
|
+
role: "none",
|
|
566
|
+
overflow: "visible",
|
|
567
|
+
className: "absolute pointer-events-none",
|
|
568
|
+
width: size?.width,
|
|
569
|
+
height: size?.height,
|
|
570
|
+
style: { zIndex: 1 + zBase },
|
|
571
|
+
children: edges.map(({ from, to, path }) => /* @__PURE__ */ jsxs(Fragment, { children: [chosen.has(`${from}→${to}`) && /* @__PURE__ */ jsx("path", {
|
|
572
|
+
d: path.d,
|
|
573
|
+
stroke: "var(--theme-element)",
|
|
574
|
+
strokeWidth: "10",
|
|
575
|
+
fill: "transparent"
|
|
576
|
+
}), /* @__PURE__ */ jsx(EdgeHitPath, {
|
|
577
|
+
d: path.d,
|
|
578
|
+
edge: {
|
|
579
|
+
from,
|
|
580
|
+
to
|
|
581
|
+
}
|
|
582
|
+
})] }, `${from}→${to}`))
|
|
583
|
+
})
|
|
584
|
+
] });
|
|
585
|
+
}
|
|
941
586
|
function SidebarJobs({ jobs, pathPrefix, preview, stepsOpen, toggleSteps, expandedSubworkflows, toggleSubworkflow, matrixOpen, toggleMatrix, openInNewGraph, setSublogOpen }) {
|
|
942
587
|
const engine = useWorkflowEngine();
|
|
943
588
|
const displayJobs = useMemo(() => displayJobsOf(engine, jobs, engine.matrixGroups(jobs)), [engine, jobs]);
|
|
@@ -1023,11 +668,37 @@ function walkJobPath(root, path) {
|
|
|
1023
668
|
}
|
|
1024
669
|
return isJobRecord(cursor) ? cursor : {};
|
|
1025
670
|
}
|
|
671
|
+
function RunTime({ start, end, finished }) {
|
|
672
|
+
const [now, setNow] = useState(() => DateTime.now());
|
|
673
|
+
const ticking = !end && !finished;
|
|
674
|
+
useEffect(() => {
|
|
675
|
+
if (!ticking) return;
|
|
676
|
+
const timer = setInterval(() => setNow(DateTime.now()), 1e3);
|
|
677
|
+
return () => clearInterval(timer);
|
|
678
|
+
}, [ticking]);
|
|
679
|
+
return toAbsHumanDuration(start, end ?? now);
|
|
680
|
+
}
|
|
681
|
+
function graphBounds(content) {
|
|
682
|
+
const nodes = outerNodes(content);
|
|
683
|
+
if (nodes.length === 0) return null;
|
|
684
|
+
const bounds = {
|
|
685
|
+
minX: Number.POSITIVE_INFINITY,
|
|
686
|
+
minY: Number.POSITIVE_INFINITY,
|
|
687
|
+
maxX: 0,
|
|
688
|
+
maxY: 0
|
|
689
|
+
};
|
|
690
|
+
for (const node of nodes) {
|
|
691
|
+
const { x, y } = offsetWithin(node, content);
|
|
692
|
+
bounds.minX = Math.min(bounds.minX, x);
|
|
693
|
+
bounds.minY = Math.min(bounds.minY, y);
|
|
694
|
+
bounds.maxX = Math.max(bounds.maxX, x + node.offsetWidth);
|
|
695
|
+
bounds.maxY = Math.max(bounds.maxY, y + node.offsetHeight);
|
|
696
|
+
}
|
|
697
|
+
return bounds;
|
|
698
|
+
}
|
|
1026
699
|
function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag", setViewMode, layout, editor, yamlJobs, inputs, workflow, fixedHeight }) {
|
|
1027
700
|
const engine = useWorkflowEngine();
|
|
1028
701
|
const animT = .125;
|
|
1029
|
-
const minScale = .2;
|
|
1030
|
-
const maxScale = .6;
|
|
1031
702
|
const rootJobs = isJobRecord(run.executedJobs) ? run.executedJobs : {};
|
|
1032
703
|
const runNumber = run.number ?? 0;
|
|
1033
704
|
const runSlug = run.slug ?? "";
|
|
@@ -1039,8 +710,8 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1039
710
|
const containerRef = useRef(null);
|
|
1040
711
|
const graphContentRef = useRef(null);
|
|
1041
712
|
const transformRef = useRef(null);
|
|
1042
|
-
const [
|
|
1043
|
-
const invalidateConnectors =
|
|
713
|
+
const [clock] = useState(() => new ConnectorClock());
|
|
714
|
+
const invalidateConnectors = clock.bump;
|
|
1044
715
|
const [windowSize, setWindowSize] = useState(() => ({
|
|
1045
716
|
w: typeof window !== "undefined" ? window.innerWidth : 800,
|
|
1046
717
|
h: typeof window !== "undefined" ? window.innerHeight : 600
|
|
@@ -1115,13 +786,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1115
786
|
const [executedJobsPathIdx, setExecutedJobsPathIdx] = useState(0);
|
|
1116
787
|
const [expandedJobs, setExpandedJobs] = useState(/* @__PURE__ */ new Set());
|
|
1117
788
|
const [matrixOpen, setMatrixOpen] = useState(/* @__PURE__ */ new Set());
|
|
1118
|
-
const
|
|
1119
|
-
const [now, setNow] = useState(() => DateTime.now());
|
|
1120
|
-
useEffect(() => {
|
|
1121
|
-
if (isRunFinished) return;
|
|
1122
|
-
const timer = setInterval(() => setNow(DateTime.now()), 1e3);
|
|
1123
|
-
return () => clearInterval(timer);
|
|
1124
|
-
}, [isRunFinished]);
|
|
789
|
+
const [shownAt] = useState(() => DateTime.now());
|
|
1125
790
|
const currentPath = executedJobsPath[executedJobsPathIdx] ?? [];
|
|
1126
791
|
const jobs = walkJobPath(rootJobs, currentPath);
|
|
1127
792
|
const root = currentPath.length === 0;
|
|
@@ -1192,18 +857,19 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1192
857
|
const sublogIsSubworkflow = !!sublogStepData?.subworkflow;
|
|
1193
858
|
const sublogFileStart = sublogOpen.lastIndexOf("/") + 1;
|
|
1194
859
|
const sublogShowsLog = sublogOpen.slice(sublogFileStart) === "logs.out";
|
|
1195
|
-
const
|
|
1196
|
-
const { dependencyCols } = useMemo(() => computeGraphLayout(engine, jobs, matrixGroups), [
|
|
860
|
+
const rootGraph = useMemo(() => computeGraphLayout(engine, jobs, engine.matrixGroups(jobs), placed), [
|
|
1197
861
|
engine,
|
|
1198
862
|
jobs,
|
|
1199
|
-
|
|
863
|
+
placed
|
|
1200
864
|
]);
|
|
865
|
+
const { dependencyCols } = rootGraph;
|
|
1201
866
|
const held = useRef(null);
|
|
1202
867
|
const viewed = useRef(false);
|
|
868
|
+
const rowOf = useCallback((job) => [...containerRef.current?.querySelectorAll("[data-dag-job]") ?? []].find((el) => el.dataset["dagJob"] === job) ?? null, []);
|
|
1203
869
|
const nodeOf = useCallback((job) => {
|
|
1204
|
-
const row =
|
|
1205
|
-
return row?.closest("[id^=\"node_\"]") ?? row
|
|
1206
|
-
}, []);
|
|
870
|
+
const row = rowOf(job);
|
|
871
|
+
return row?.closest("[id^=\"node_\"]") ?? row;
|
|
872
|
+
}, [rowOf]);
|
|
1207
873
|
const hold = useCallback((job) => {
|
|
1208
874
|
const content = graphContentRef.current;
|
|
1209
875
|
const transform = transformRef.current;
|
|
@@ -1222,65 +888,38 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1222
888
|
const container = containerRef.current;
|
|
1223
889
|
const content = graphContentRef.current;
|
|
1224
890
|
const transform = transformRef.current;
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
let maxY = 0;
|
|
1232
|
-
for (const node of nodes) {
|
|
1233
|
-
const el = node;
|
|
1234
|
-
const pos = offsetWithin(el, content);
|
|
1235
|
-
minX = Math.min(minX, pos.x);
|
|
1236
|
-
minY = Math.min(minY, pos.y);
|
|
1237
|
-
maxX = Math.max(maxX, pos.x + el.offsetWidth);
|
|
1238
|
-
maxY = Math.max(maxY, pos.y + el.offsetHeight);
|
|
1239
|
-
}
|
|
1240
|
-
const graphW = maxX - minX;
|
|
1241
|
-
const graphH = maxY - minY;
|
|
1242
|
-
const containerW = container.clientWidth;
|
|
1243
|
-
const containerH = container.clientHeight;
|
|
1244
|
-
const margin = Math.min(containerW, containerH) * .05;
|
|
891
|
+
const bounds = content ? graphBounds(content) : null;
|
|
892
|
+
if (!container || !content || !transform || !bounds) return;
|
|
893
|
+
const panel = {
|
|
894
|
+
width: container.clientWidth,
|
|
895
|
+
height: container.clientHeight
|
|
896
|
+
};
|
|
1245
897
|
const pending = held.current;
|
|
1246
898
|
held.current = null;
|
|
1247
899
|
const node = pending && performance.now() - pending.at < HOLD_MS ? nodeOf(pending.job) : null;
|
|
1248
900
|
const viewing = editor && viewed.current && animationMs === 0;
|
|
1249
901
|
if (pending && node || viewing) {
|
|
1250
|
-
const { positionX, positionY, scale
|
|
902
|
+
const { positionX, positionY, scale } = transform.instance.state;
|
|
1251
903
|
const pos = pending && node ? offsetWithin(node, content) : null;
|
|
1252
|
-
const x = pending && pos ? pending.x - pos.x *
|
|
1253
|
-
const y = pending && pos ? pending.y - pos.y *
|
|
1254
|
-
transform.setTransform(x, y,
|
|
1255
|
-
const
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
invalidateConnectors();
|
|
1260
|
-
});
|
|
904
|
+
const x = pending && pos ? pending.x - pos.x * scale : positionX;
|
|
905
|
+
const y = pending && pos ? pending.y - pos.y * scale : positionY;
|
|
906
|
+
transform.setTransform(x, y, scale, 0);
|
|
907
|
+
const margin = fitMargin(panel);
|
|
908
|
+
const dx = intoView(x + bounds.minX * scale, x + bounds.maxX * scale, margin, panel.width - margin);
|
|
909
|
+
const dy = intoView(y + bounds.minY * scale, y + bounds.maxY * scale, margin, panel.height - margin);
|
|
910
|
+
if (dx !== 0 || dy !== 0) requestAnimationFrame(() => transform.setTransform(x + dx, y + dy, scale, FIT_ANIMATION_MS, "easeOut"));
|
|
1261
911
|
return;
|
|
1262
912
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
const scaleH = (containerH - margin * 2) / graphH;
|
|
1266
|
-
const scale = Math.min(Math.max(Math.min(scaleW, scaleH), minScale), maxScale);
|
|
1267
|
-
const offsetX = margin - minX * scale;
|
|
1268
|
-
const offsetY = margin - minY * scale;
|
|
913
|
+
const view = fitView(bounds, panel);
|
|
914
|
+
if (!view) return;
|
|
1269
915
|
if (animationMs > 0) {
|
|
1270
|
-
transform.setTransform(
|
|
916
|
+
transform.setTransform(view.x, view.y, view.scale, animationMs, "easeOut");
|
|
1271
917
|
return;
|
|
1272
918
|
}
|
|
1273
919
|
const wrapperEl = container.querySelector(".react-transform-component");
|
|
1274
|
-
if (wrapperEl) wrapperEl.style.transform = `translate(${
|
|
1275
|
-
requestAnimationFrame(() =>
|
|
1276
|
-
|
|
1277
|
-
invalidateConnectors();
|
|
1278
|
-
});
|
|
1279
|
-
}, [
|
|
1280
|
-
invalidateConnectors,
|
|
1281
|
-
nodeOf,
|
|
1282
|
-
editor
|
|
1283
|
-
]);
|
|
920
|
+
if (wrapperEl) wrapperEl.style.transform = `translate(${view.x}px, ${view.y}px) scale(${view.scale})`;
|
|
921
|
+
requestAnimationFrame(() => transform.setTransform(view.x, view.y, view.scale, 0));
|
|
922
|
+
}, [nodeOf, editor]);
|
|
1284
923
|
const fitWhenSettled = useCallback(async () => {
|
|
1285
924
|
const container = containerRef.current;
|
|
1286
925
|
const content = graphContentRef.current;
|
|
@@ -1323,7 +962,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1323
962
|
useEffect(() => {
|
|
1324
963
|
if (!registerShow || !editorApi) return;
|
|
1325
964
|
return registerShow(({ job, step }) => {
|
|
1326
|
-
const row =
|
|
965
|
+
const row = job === void 0 ? null : rowOf(job);
|
|
1327
966
|
if (job === void 0 || !row) return false;
|
|
1328
967
|
if (step !== void 0) setStepsOpen((prev) => new Set(prev).add(job));
|
|
1329
968
|
editorApi.focus(step === void 0 ? { job } : {
|
|
@@ -1338,28 +977,54 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1338
977
|
}, [
|
|
1339
978
|
registerShow,
|
|
1340
979
|
editorApi,
|
|
1341
|
-
centerOn
|
|
980
|
+
centerOn,
|
|
981
|
+
rowOf
|
|
1342
982
|
]);
|
|
1343
|
-
const [zoomedAll, setZoomedAll] = useState(
|
|
1344
|
-
const onTransform = useCallback((_, { scale }) =>
|
|
1345
|
-
setZoomedAll(scale >= .599 ? "in" : scale <= .201 ? "out" : null);
|
|
1346
|
-
invalidateConnectors();
|
|
1347
|
-
}, [invalidateConnectors]);
|
|
983
|
+
const [zoomedAll, setZoomedAll] = useState(() => zoomLimit(FIT_MAX_SCALE));
|
|
984
|
+
const onTransform = useCallback((_, { scale }) => setZoomedAll(zoomLimit(scale)), []);
|
|
1348
985
|
const moved = useCallback(() => {
|
|
1349
986
|
viewed.current = true;
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
const zoomBy = useCallback((step) => {
|
|
1353
|
-
const container = containerRef.current;
|
|
1354
|
-
const transform = transformRef.current;
|
|
1355
|
-
if (!container || !transform) return;
|
|
987
|
+
}, []);
|
|
988
|
+
const zoomTo = useCallback((view, animationMs) => {
|
|
1356
989
|
viewed.current = true;
|
|
1357
|
-
|
|
1358
|
-
const next = Math.min(maxScale, Math.max(minScale, scale * Math.exp(step)));
|
|
1359
|
-
const x = container.clientWidth / 2;
|
|
1360
|
-
const y = container.clientHeight / 2;
|
|
1361
|
-
transform.setTransform(x - (x - positionX) / scale * next, y - (y - positionY) / scale * next, next, FIT_ANIMATION_MS, "easeOut");
|
|
990
|
+
transformRef.current?.setTransform(view.x, view.y, view.scale, animationMs, "easeOut");
|
|
1362
991
|
}, []);
|
|
992
|
+
const currentView = () => {
|
|
993
|
+
const state = transformRef.current?.instance.state;
|
|
994
|
+
return state ? {
|
|
995
|
+
x: state.positionX,
|
|
996
|
+
y: state.positionY,
|
|
997
|
+
scale: state.scale
|
|
998
|
+
} : null;
|
|
999
|
+
};
|
|
1000
|
+
const zoomBy = (step) => {
|
|
1001
|
+
const container = containerRef.current;
|
|
1002
|
+
const view = currentView();
|
|
1003
|
+
if (container && view) {
|
|
1004
|
+
const middle = {
|
|
1005
|
+
x: container.clientWidth / 2,
|
|
1006
|
+
y: container.clientHeight / 2
|
|
1007
|
+
};
|
|
1008
|
+
zoomTo(zoomAround(view, middle, Math.exp(step)), FIT_ANIMATION_MS);
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
useEffect(() => {
|
|
1012
|
+
const wrapper = transformRef.current?.instance.wrapperComponent;
|
|
1013
|
+
if (!wrapper) return;
|
|
1014
|
+
const onWheel = (event) => {
|
|
1015
|
+
const view = currentView();
|
|
1016
|
+
if (!view) return;
|
|
1017
|
+
event.preventDefault();
|
|
1018
|
+
const rect = wrapper.getBoundingClientRect();
|
|
1019
|
+
const at = {
|
|
1020
|
+
x: event.clientX - rect.left,
|
|
1021
|
+
y: event.clientY - rect.top
|
|
1022
|
+
};
|
|
1023
|
+
zoomTo(zoomAround(view, at, wheelFactor(event)), 0);
|
|
1024
|
+
};
|
|
1025
|
+
wrapper.addEventListener("wheel", onWheel, { passive: false });
|
|
1026
|
+
return () => wrapper.removeEventListener("wheel", onWheel);
|
|
1027
|
+
}, [containerEl, zoomTo]);
|
|
1363
1028
|
useEffect(() => {
|
|
1364
1029
|
if (preview) return;
|
|
1365
1030
|
const raf = requestAnimationFrame(() => fitGraph());
|
|
@@ -1476,9 +1141,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1476
1141
|
removeBorder
|
|
1477
1142
|
})
|
|
1478
1143
|
}) : void 0;
|
|
1479
|
-
const startDt = run.createdAt ? DateTime.fromISO(run.createdAt) :
|
|
1480
|
-
const endDt = run.completedAt ? DateTime.fromISO(run.completedAt) : now;
|
|
1481
|
-
const runtime = toAbsHumanDuration(startDt, endDt);
|
|
1144
|
+
const startDt = run.createdAt ? DateTime.fromISO(run.createdAt) : shownAt;
|
|
1482
1145
|
const additionalBottomLeftBarComponents = sublogIsStep ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1483
1146
|
/* @__PURE__ */ jsxs("button", {
|
|
1484
1147
|
type: "button",
|
|
@@ -1586,7 +1249,11 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1586
1249
|
children: dagStrings.runtime
|
|
1587
1250
|
}), /* @__PURE__ */ jsx("div", {
|
|
1588
1251
|
className: "text-sm font-semibold flex items-center gap-x-1",
|
|
1589
|
-
children:
|
|
1252
|
+
children: /* @__PURE__ */ jsx(RunTime, {
|
|
1253
|
+
start: startDt,
|
|
1254
|
+
end: run.completedAt ? DateTime.fromISO(run.completedAt) : void 0,
|
|
1255
|
+
finished: run.status === "completed" || run.status === "error" || run.status === "canceled"
|
|
1256
|
+
})
|
|
1590
1257
|
})]
|
|
1591
1258
|
}),
|
|
1592
1259
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -1631,9 +1298,10 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1631
1298
|
},
|
|
1632
1299
|
children: [/* @__PURE__ */ jsx(TransformWrapper, {
|
|
1633
1300
|
ref: transformRef,
|
|
1634
|
-
minScale,
|
|
1635
|
-
maxScale,
|
|
1636
|
-
initialScale:
|
|
1301
|
+
minScale: MIN_SCALE,
|
|
1302
|
+
maxScale: 2,
|
|
1303
|
+
initialScale: FIT_MAX_SCALE,
|
|
1304
|
+
wheel: { disabled: true },
|
|
1637
1305
|
...editor ? { panning: { excluded: [EDITOR_HANDLE_CLASS] } } : {},
|
|
1638
1306
|
doubleClick: { disabled: true },
|
|
1639
1307
|
limitToBounds: false,
|
|
@@ -1643,8 +1311,6 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1643
1311
|
onPanning: moved,
|
|
1644
1312
|
onPinch: moved,
|
|
1645
1313
|
onTransform,
|
|
1646
|
-
onWheel: moved,
|
|
1647
|
-
onZoom: invalidateConnectors,
|
|
1648
1314
|
children: () => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
1649
1315
|
className: "absolute z-10 top-2 right-2 flex max-w-[calc(100%-1rem)] flex-col items-end gap-y-1",
|
|
1650
1316
|
children: /* @__PURE__ */ jsx(GraphViewControls, {
|
|
@@ -1666,30 +1332,34 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1666
1332
|
onZoom: (direction) => zoomBy(direction * ZOOM_STEP),
|
|
1667
1333
|
zoomedAll
|
|
1668
1334
|
})
|
|
1669
|
-
}), /* @__PURE__ */ jsx(TransformComponent, { children: /* @__PURE__ */ jsx(
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1335
|
+
}), /* @__PURE__ */ jsx(TransformComponent, { children: /* @__PURE__ */ jsx(ConnectorClockContext, {
|
|
1336
|
+
value: clock,
|
|
1337
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1338
|
+
ref: graphContentRef,
|
|
1339
|
+
className: "flex relative mr-[8000px]",
|
|
1340
|
+
style: { minHeight: 4e3 },
|
|
1341
|
+
children: /* @__PURE__ */ jsx(Subgraph, {
|
|
1342
|
+
jobs,
|
|
1343
|
+
pathPrefix: pathAppend,
|
|
1344
|
+
depth: 0,
|
|
1345
|
+
preview,
|
|
1346
|
+
animT,
|
|
1347
|
+
expandedSubworkflows,
|
|
1348
|
+
toggleSubworkflow,
|
|
1349
|
+
openInNewGraph,
|
|
1350
|
+
setSublogOpen,
|
|
1351
|
+
invalidateConnectors,
|
|
1352
|
+
requestFit: fitWhenSettled,
|
|
1353
|
+
stepsOpen,
|
|
1354
|
+
toggleSteps,
|
|
1355
|
+
matrixOpen,
|
|
1356
|
+
toggleMatrix,
|
|
1357
|
+
onReady: fitGraph,
|
|
1358
|
+
layout: placed,
|
|
1359
|
+
graph: rootGraph,
|
|
1360
|
+
editable: !!editorApi && currentPath.length === 0
|
|
1361
|
+
}, `sg-${executedJobsPathIdx}-${pathAppend}`)
|
|
1362
|
+
})
|
|
1693
1363
|
}) })] })
|
|
1694
1364
|
}), editorOverlays]
|
|
1695
1365
|
})
|
|
@@ -1745,26 +1415,6 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1745
1415
|
children: graph
|
|
1746
1416
|
});
|
|
1747
1417
|
}
|
|
1748
|
-
var isSlot = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
1749
|
-
/** Each job's place on the graph from its `position`; none when no job has one. */
|
|
1750
|
-
function positionsOf(jobs) {
|
|
1751
|
-
const layout = Object.create(null);
|
|
1752
|
-
let any = false;
|
|
1753
|
-
for (const [name, job] of Object.entries(jobs)) {
|
|
1754
|
-
const { position, _matrix } = isJobRecord(job) ? job : {};
|
|
1755
|
-
const { column, row } = isJobRecord(position) ? position : {};
|
|
1756
|
-
const original = isJobRecord(_matrix) ? _matrix["originaljob"] : void 0;
|
|
1757
|
-
const key = typeof original === "string" && original ? original : name;
|
|
1758
|
-
if (isSlot(column) && isSlot(row) && !(key in layout)) {
|
|
1759
|
-
layout[key] = {
|
|
1760
|
-
column,
|
|
1761
|
-
row
|
|
1762
|
-
};
|
|
1763
|
-
any = true;
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
return any ? layout : void 0;
|
|
1767
|
-
}
|
|
1768
1418
|
/** Jobs as a run evaluates them before it starts: each `strategy`, and a `needs` expression, from the inputs' defaults. */
|
|
1769
1419
|
function withRunExpressions(engine, jobs, workflowInputs) {
|
|
1770
1420
|
let values;
|
|
@@ -1871,4 +1521,4 @@ function DependencyGraphPreview(inputs) {
|
|
|
1871
1521
|
});
|
|
1872
1522
|
}
|
|
1873
1523
|
//#endregion
|
|
1874
|
-
export { DependencyGraphPreview, addCleanupSteps,
|
|
1524
|
+
export { DependencyGraphPreview, addCleanupSteps, DependencyGraph as default };
|