@parallelworks/ui 0.38.0 → 0.39.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 +1 -1
- package/dist/ai/components/ChatInput.js +8 -23
- package/dist/ai/components/chatDraft.d.ts +7 -0
- package/dist/ai/components/chatDraft.js +66 -0
- package/dist/editing.d.ts +2 -0
- package/dist/editor/Monaco.js +1 -1
- package/dist/editor/index.js +1 -1
- package/dist/editor/lintContext.js +15 -3
- package/dist/graph/DependencyGraph.d.ts +8 -1
- package/dist/graph/DependencyGraph.js +433 -204
- package/dist/graph/GraphEditor.d.ts +27 -0
- package/dist/graph/GraphEditor.js +1543 -0
- package/dist/graph/GraphEditorDialogs.d.ts +87 -0
- package/dist/graph/GraphEditorDialogs.js +1808 -0
- package/dist/graph/InputDialog.js +4 -4
- package/dist/graph/InputsEditor.js +2 -2
- package/dist/graph/JobSummary.d.ts +3 -0
- package/dist/graph/JobSummary.js +34 -21
- package/dist/graph/MatrixGroup.d.ts +2 -1
- package/dist/graph/MatrixGroup.js +10 -3
- package/dist/graph/WorkflowSettingsDialog.d.ts +21 -0
- package/dist/graph/WorkflowSettingsDialog.js +670 -0
- package/dist/graph/editorFields.js +144 -3
- package/dist/graph/editorRows.d.ts +58 -0
- package/dist/graph/editorRows.js +460 -0
- package/dist/graph/editorStrings.d.ts +1 -0
- package/dist/graph/editorStrings.js +1 -0
- package/dist/graph/expressionRefs.js +39 -0
- package/dist/graph/fieldProblems.js +36 -2
- package/dist/graph/graphEditorState.d.ts +191 -0
- package/dist/graph/graphEditorState.js +74 -0
- package/dist/graph/index.d.ts +3 -0
- package/dist/graph/index.js +5 -2
- package/dist/graph/inputLayout.js +1 -1
- package/dist/graph/inputRefs.js +196 -4
- package/dist/graph/refusalText.js +13 -0
- package/dist/graph/stepWith.d.ts +38 -0
- package/dist/graph/stepWith.js +536 -0
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -16,15 +16,17 @@ import { toAbsHumanDuration } from "../duration.js";
|
|
|
16
16
|
import { initializeValues } from "../form/lib.js";
|
|
17
17
|
import { AnnotationBanner } from "./AnnotationBanner.js";
|
|
18
18
|
import { Collapse } from "./Collapse.js";
|
|
19
|
+
import { jobLabel, toggled } from "./util.js";
|
|
20
|
+
import { EDITOR_HANDLE_CLASS, GraphEditorProvider, useGraphEditor, useSelectedEdges } from "./graphEditorState.js";
|
|
21
|
+
import { BoxGrip, EdgeEnds, EdgeHitPath, EmptyGraphEditor, GraphEditorCanvas, NodePorts } from "./editorRows.js";
|
|
19
22
|
import { emptyColumnsStyle, emptyRowsStyle } from "./gridSpacing.js";
|
|
20
23
|
import { Reveal } from "./Reveal.js";
|
|
21
|
-
import { jobLabel, toggled } from "./util.js";
|
|
22
24
|
import { Joblist } from "./JobSummary.js";
|
|
23
25
|
import { MatrixGroupNode, MatrixGroupSummaryItem } from "./MatrixGroup.js";
|
|
24
26
|
import TreeView from "./TreeView.js";
|
|
25
27
|
import { isJobRecord } from "./types.js";
|
|
26
28
|
import cx from "classnames";
|
|
27
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
29
|
+
import React, { Suspense, lazy, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
28
30
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
29
31
|
import { flushSync } from "react-dom";
|
|
30
32
|
import { DateTime } from "luxon";
|
|
@@ -362,7 +364,7 @@ function computeGraphLayout(engine, jobs, matrixGroups, layout) {
|
|
|
362
364
|
descendantDists
|
|
363
365
|
};
|
|
364
366
|
}
|
|
365
|
-
function jobHandlers({ engine, jobs, displayJobs, pathPrefix, stepsOpen, toggleSteps, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, renderWell }) {
|
|
367
|
+
function jobHandlers({ engine, jobs, displayJobs, pathPrefix, stepsOpen, toggleSteps, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, renderWell, editStep }) {
|
|
366
368
|
const isStepsOpen = (j) => stepsOpen.has(pathPrefix + j);
|
|
367
369
|
const subworkflowKey = (j, s) => `${pathPrefix}${j}:${s}`;
|
|
368
370
|
const openLog = (j, s) => setSublogOpen(engine.stepLogPath(pathPrefix, j, s));
|
|
@@ -376,6 +378,10 @@ function jobHandlers({ engine, jobs, displayJobs, pathPrefix, stepsOpen, toggleS
|
|
|
376
378
|
onStepClick: (j, s) => {
|
|
377
379
|
const step = jobs[j]?.steps?.[s];
|
|
378
380
|
if (step?.status === "skipped" || step?.status === "skipped-failed") return;
|
|
381
|
+
if (editStep && !step?.linkedStep) {
|
|
382
|
+
editStep(jobs[j]?._matrix?.originaljob ?? j, s);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
379
385
|
if (step?.subworkflow) toggleSubworkflow(subworkflowKey(j, s));
|
|
380
386
|
else openLog(j, s);
|
|
381
387
|
},
|
|
@@ -401,6 +407,7 @@ function SubworkflowWell({ expanded, onSettled, className, children }) {
|
|
|
401
407
|
});
|
|
402
408
|
}
|
|
403
409
|
var SUBGRAPH_Z_STEP = 100;
|
|
410
|
+
var GraphEditorOverlays = lazy(() => import("./GraphEditor.js"));
|
|
404
411
|
var CONNECTOR_COLOR = "var(--theme-border)";
|
|
405
412
|
var HIGHLIGHT_COLOR = "var(--theme-element)";
|
|
406
413
|
var FIT_ANIMATION_MS = 300;
|
|
@@ -422,10 +429,18 @@ function sizesSettled(els) {
|
|
|
422
429
|
function sizingTransitions(el) {
|
|
423
430
|
return el.getAnimations({ subtree: true }).filter((animation) => animation instanceof CSSTransition && (animation.transitionProperty === "grid-template-rows" || animation.transitionProperty === "width"));
|
|
424
431
|
}
|
|
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
|
+
var HOLD_MS = 2e3;
|
|
425
438
|
var ZOOM_STEP = .25;
|
|
426
|
-
function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, invalidateConnectors, requestFit, stepsOpen, toggleSteps, matrixOpen, toggleMatrix, onReady, layout }) {
|
|
439
|
+
function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflows, toggleSubworkflow, openInNewGraph, setSublogOpen, invalidateConnectors, requestFit, stepsOpen, toggleSteps, matrixOpen, toggleMatrix, onReady, layout, editable = false }) {
|
|
427
440
|
const engine = useWorkflowEngine();
|
|
428
441
|
const wrapperRef = useRef(null);
|
|
442
|
+
const editorApi = useGraphEditor();
|
|
443
|
+
const selectedEdges = useSelectedEdges(editable ? editorApi : null);
|
|
429
444
|
const zBase = depth * SUBGRAPH_Z_STEP;
|
|
430
445
|
const [hoveredJob, setHoveredJob] = useState(null);
|
|
431
446
|
const lastHoveredDistancesRef = useRef(null);
|
|
@@ -443,6 +458,23 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
443
458
|
matrixGroups,
|
|
444
459
|
placed
|
|
445
460
|
]);
|
|
461
|
+
useEffect(() => {
|
|
462
|
+
const wrapper = wrapperRef.current;
|
|
463
|
+
if (!editable || !editorApi || !wrapper) return;
|
|
464
|
+
editorApi.registerGrid({
|
|
465
|
+
wrapper,
|
|
466
|
+
cols: dependencyCols,
|
|
467
|
+
rows: rowSlots,
|
|
468
|
+
columns: colSlots
|
|
469
|
+
});
|
|
470
|
+
return () => editorApi.registerGrid(null);
|
|
471
|
+
}, [
|
|
472
|
+
editable,
|
|
473
|
+
editorApi,
|
|
474
|
+
dependencyCols,
|
|
475
|
+
rowSlots,
|
|
476
|
+
colSlots
|
|
477
|
+
]);
|
|
446
478
|
const hoveredDistances = useMemo(() => {
|
|
447
479
|
if (!hoveredJob) return null;
|
|
448
480
|
const dist = /* @__PURE__ */ new Map();
|
|
@@ -533,6 +565,7 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
533
565
|
},
|
|
534
566
|
openInNewGraph,
|
|
535
567
|
setSublogOpen,
|
|
568
|
+
editStep: editable && editorApi ? (j, s) => editorApi.editStep(j, s) : void 0,
|
|
536
569
|
renderWell: (subJobs, subPrefix, expanded) => /* @__PURE__ */ jsx(SubworkflowWell, {
|
|
537
570
|
expanded,
|
|
538
571
|
onSettled: requestFit,
|
|
@@ -581,6 +614,7 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
581
614
|
zBase,
|
|
582
615
|
handlers,
|
|
583
616
|
preview,
|
|
617
|
+
editable,
|
|
584
618
|
rowsAbove
|
|
585
619
|
}, `node_${first}`);
|
|
586
620
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -595,19 +629,20 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
595
629
|
onMouseLeave: () => setHoveredJob(null),
|
|
596
630
|
onFocus: () => setHoveredJob(first),
|
|
597
631
|
onBlur: () => setHoveredJob(null),
|
|
598
|
-
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-2xl bg-(--theme-panel-bg)" }), /* @__PURE__ */
|
|
632
|
+
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-2xl bg-(--theme-panel-bg)" }), /* @__PURE__ */ jsxs("div", {
|
|
599
633
|
className: "relative border-solid shadow py-4 px-8 rounded-xl border-4 whitespace-nowrap bg-(--theme-panel-bg) text-2xl",
|
|
600
634
|
style: {
|
|
601
635
|
opacity: hoveredRelated && !hoveredRelated.has(first) ? .5 : 1,
|
|
602
636
|
transition: `opacity ${animT}s`
|
|
603
637
|
},
|
|
604
|
-
children: /* @__PURE__ */ jsx(Joblist, {
|
|
638
|
+
children: [editable && jobNames.length > 1 && /* @__PURE__ */ jsx(BoxGrip, { jobs: jobNames }), /* @__PURE__ */ jsx(Joblist, {
|
|
605
639
|
jobs: displayJobs,
|
|
606
640
|
jobNames,
|
|
607
641
|
...handlers,
|
|
608
642
|
growWidth: true,
|
|
609
|
-
preview
|
|
610
|
-
|
|
643
|
+
preview,
|
|
644
|
+
editable
|
|
645
|
+
})]
|
|
611
646
|
})]
|
|
612
647
|
}, `node_${first}`);
|
|
613
648
|
})
|
|
@@ -637,7 +672,9 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
637
672
|
setSublogOpen,
|
|
638
673
|
engine,
|
|
639
674
|
invalidateConnectors,
|
|
640
|
-
requestFit
|
|
675
|
+
requestFit,
|
|
676
|
+
editable,
|
|
677
|
+
editorApi
|
|
641
678
|
]);
|
|
642
679
|
const memoizedBoxLayer = useMemo(() => buildBoxLayer(), [buildBoxLayer]);
|
|
643
680
|
const hasLiveNestedGraph = Array.from(expandedSubworkflows).some((k) => k.startsWith(pathPrefix));
|
|
@@ -645,191 +682,259 @@ function Subgraph({ jobs, pathPrefix, depth, preview, animT, expandedSubworkflow
|
|
|
645
682
|
return /* @__PURE__ */ jsxs("div", {
|
|
646
683
|
ref: wrapperRef,
|
|
647
684
|
className: "relative",
|
|
648
|
-
children: [
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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
|
-
}
|
|
665
|
-
let minAdy = Number.POSITIVE_INFINITY;
|
|
666
|
-
for (const col of dependencyCols) for (const jobNames of col) {
|
|
667
|
-
const first = jobNames[0];
|
|
668
|
-
if (first === void 0) continue;
|
|
669
|
-
for (const dep of depsOf(first)) {
|
|
670
|
-
const s = gid(dep);
|
|
671
|
-
const e = gid(first);
|
|
672
|
-
if (!s || !e) continue;
|
|
673
|
-
const dy = Math.abs(nodeConnectorY(e) - nodeConnectorY(s));
|
|
674
|
-
if (dy > 0 && dy < minAdy) minAdy = dy;
|
|
685
|
+
children: [
|
|
686
|
+
(() => {
|
|
687
|
+
const wrapper = wrapperRef.current;
|
|
688
|
+
const gid = (name) => document.getElementById(`node_${pathPrefix}${name}`);
|
|
689
|
+
const ox = (el) => offsetWithin(el, wrapper).x;
|
|
690
|
+
const nodeConnectorY = (el) => offsetWithin(el, wrapper).y + 37;
|
|
691
|
+
const depsOf = (head) => directDeps[head] ?? [];
|
|
692
|
+
let colGap = 32;
|
|
693
|
+
if (dependencyCols.length >= 2) {
|
|
694
|
+
const col0 = gid(dependencyCols[0]?.[0]?.[0] ?? "");
|
|
695
|
+
const col1 = gid(dependencyCols[1]?.[0]?.[0] ?? "");
|
|
696
|
+
if (col0 && col1) colGap = ox(col1) - (ox(col0) + col0.offsetWidth);
|
|
675
697
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
const isHighlighted = hoveredRelated?.has(first) && hoveredRelated?.has(dep);
|
|
681
|
-
const depDist = activeDists?.get(dep) ?? 0;
|
|
682
|
-
const targetDist = activeDists?.get(first) ?? 0;
|
|
683
|
-
const closerDist = Math.min(depDist, targetDist);
|
|
684
|
-
const connectorDelay = closerDist * animT;
|
|
685
|
-
const retractDelay = (maxHoveredDistRef.current - closerDist) * animT;
|
|
686
|
-
const drawRightToLeft = targetDist < depDist;
|
|
687
|
-
const start = gid(dep);
|
|
688
|
-
const end = gid(first);
|
|
689
|
-
if (!start || !end) return null;
|
|
690
|
-
const x1 = ox(start) + start.offsetWidth - 2;
|
|
691
|
-
const y1 = nodeConnectorY(start);
|
|
692
|
-
const x2 = ox(end) + 2;
|
|
693
|
-
const y2 = nodeConnectorY(end);
|
|
694
|
-
const dy = y2 - y1;
|
|
695
|
-
const ady = Math.abs(dy);
|
|
696
|
-
let pathD;
|
|
697
|
-
let pathLen;
|
|
698
|
-
let pathDReversed;
|
|
699
|
-
const r = arcR;
|
|
700
|
-
if (ady === 0) {
|
|
701
|
-
pathD = `M ${x1} ${y1} L ${x2} ${y2}`;
|
|
702
|
-
pathDReversed = `M ${x2} ${y2} L ${x1} ${y1}`;
|
|
703
|
-
pathLen = x2 - x1;
|
|
704
|
-
} else {
|
|
705
|
-
const s = dy > 0 ? 1 : -1;
|
|
706
|
-
const ax2end = x2 - (colGap / 2 - r);
|
|
707
|
-
const ax = ax2end - 2 * r;
|
|
708
|
-
const sw1 = dy > 0 ? 1 : 0;
|
|
709
|
-
const sw2 = dy > 0 ? 0 : 1;
|
|
710
|
-
pathD = [
|
|
711
|
-
`M ${x1} ${y1}`,
|
|
712
|
-
`L ${ax} ${y1}`,
|
|
713
|
-
`A ${r} ${r} 0 0 ${sw1} ${ax + r} ${y1 + s * r}`,
|
|
714
|
-
`L ${ax + r} ${y2 - s * r}`,
|
|
715
|
-
`A ${r} ${r} 0 0 ${sw2} ${ax2end} ${y2}`,
|
|
716
|
-
`L ${x2} ${y2}`
|
|
717
|
-
].join(" ");
|
|
718
|
-
pathDReversed = [
|
|
719
|
-
`M ${x2} ${y2}`,
|
|
720
|
-
`L ${ax2end} ${y2}`,
|
|
721
|
-
`A ${r} ${r} 0 0 ${sw1} ${ax + r} ${y2 - s * r}`,
|
|
722
|
-
`L ${ax + r} ${y1 + s * r}`,
|
|
723
|
-
`A ${r} ${r} 0 0 ${sw2} ${ax} ${y1}`,
|
|
724
|
-
`L ${x1} ${y1}`
|
|
725
|
-
].join(" ");
|
|
726
|
-
const arcLen = Math.PI * r / 2;
|
|
727
|
-
const vSeg = Math.max(0, ady - 2 * r);
|
|
728
|
-
pathLen = ax - x1 + arcLen + vSeg + arcLen + (x2 - ax2end);
|
|
698
|
+
if (colSlots.some((column, c) => column !== c)) for (let c = 1; c < dependencyCols.length; c++) {
|
|
699
|
+
const left = gid(dependencyCols[c - 1]?.[0]?.[0] ?? "");
|
|
700
|
+
const right = gid(dependencyCols[c]?.[0]?.[0] ?? "");
|
|
701
|
+
if (left && right) colGap = Math.min(colGap, ox(right) - (ox(left) + left.offsetWidth));
|
|
729
702
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
703
|
+
let minAdy = Number.POSITIVE_INFINITY;
|
|
704
|
+
for (const col of dependencyCols) for (const jobNames of col) {
|
|
705
|
+
const first = jobNames[0];
|
|
706
|
+
if (first === void 0) continue;
|
|
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", {
|
|
779
796
|
d: pathD,
|
|
780
|
-
stroke: "var(--theme-
|
|
781
|
-
strokeWidth: "
|
|
797
|
+
stroke: "var(--theme-element)",
|
|
798
|
+
strokeWidth: "10",
|
|
782
799
|
fill: "transparent"
|
|
783
|
-
}), /* @__PURE__ */ jsx(
|
|
800
|
+
}), /* @__PURE__ */ jsx(EdgeHitPath, {
|
|
784
801
|
d: pathD,
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
style: {
|
|
789
|
-
opacity: hoveredRelated && !isHighlighted ? .3 : 1,
|
|
790
|
-
transition: `opacity 0s`
|
|
802
|
+
edge: {
|
|
803
|
+
from: dep,
|
|
804
|
+
to: first
|
|
791
805
|
}
|
|
792
|
-
})]
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
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
|
+
]
|
|
833
938
|
});
|
|
834
939
|
}
|
|
835
940
|
var NestedSubgraph = Subgraph;
|
|
@@ -918,7 +1023,7 @@ function walkJobPath(root, path) {
|
|
|
918
1023
|
}
|
|
919
1024
|
return isJobRecord(cursor) ? cursor : {};
|
|
920
1025
|
}
|
|
921
|
-
function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag", setViewMode, layout, yamlJobs, fixedHeight }) {
|
|
1026
|
+
function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag", setViewMode, layout, editor, yamlJobs, inputs, workflow, fixedHeight }) {
|
|
922
1027
|
const engine = useWorkflowEngine();
|
|
923
1028
|
const animT = .125;
|
|
924
1029
|
const minScale = .2;
|
|
@@ -950,8 +1055,10 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
950
1055
|
}, []);
|
|
951
1056
|
const [topOffset, setTopOffset] = useState(null);
|
|
952
1057
|
const topObserverRef = useRef(null);
|
|
1058
|
+
const [containerEl, setContainerEl] = useState(null);
|
|
953
1059
|
const setContainerElement = useCallback((el) => {
|
|
954
1060
|
containerRef.current = el;
|
|
1061
|
+
setContainerEl(el);
|
|
955
1062
|
topObserverRef.current?.disconnect();
|
|
956
1063
|
topObserverRef.current = null;
|
|
957
1064
|
if (!el || preview) return;
|
|
@@ -1025,6 +1132,20 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1025
1132
|
yamlJobs,
|
|
1026
1133
|
jobs
|
|
1027
1134
|
]);
|
|
1135
|
+
const [editorApi, setEditorApi] = useState(null);
|
|
1136
|
+
const editorOverlays = editor ? /* @__PURE__ */ jsx(Suspense, {
|
|
1137
|
+
fallback: null,
|
|
1138
|
+
children: /* @__PURE__ */ jsx(GraphEditorOverlays, {
|
|
1139
|
+
editor,
|
|
1140
|
+
jobs,
|
|
1141
|
+
yamlJobs,
|
|
1142
|
+
inputs,
|
|
1143
|
+
workflow,
|
|
1144
|
+
layout: placed,
|
|
1145
|
+
container: containerEl,
|
|
1146
|
+
onApi: setEditorApi
|
|
1147
|
+
})
|
|
1148
|
+
}) : null;
|
|
1028
1149
|
const resetGraph = useCallback(() => {
|
|
1029
1150
|
setSublogOpen("");
|
|
1030
1151
|
setStepsOpen(/* @__PURE__ */ new Set());
|
|
@@ -1077,6 +1198,26 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1077
1198
|
jobs,
|
|
1078
1199
|
matrixGroups
|
|
1079
1200
|
]);
|
|
1201
|
+
const held = useRef(null);
|
|
1202
|
+
const viewed = useRef(false);
|
|
1203
|
+
const nodeOf = useCallback((job) => {
|
|
1204
|
+
const row = [...containerRef.current?.querySelectorAll("[data-dag-job]") ?? []].find((el) => el.dataset["dagJob"] === job);
|
|
1205
|
+
return row?.closest("[id^=\"node_\"]") ?? row ?? null;
|
|
1206
|
+
}, []);
|
|
1207
|
+
const hold = useCallback((job) => {
|
|
1208
|
+
const content = graphContentRef.current;
|
|
1209
|
+
const transform = transformRef.current;
|
|
1210
|
+
const node = nodeOf(job);
|
|
1211
|
+
if (!content || !transform || !node) return;
|
|
1212
|
+
const { positionX, positionY, scale } = transform.instance.state;
|
|
1213
|
+
const pos = offsetWithin(node, content);
|
|
1214
|
+
held.current = {
|
|
1215
|
+
job,
|
|
1216
|
+
x: positionX + pos.x * scale,
|
|
1217
|
+
y: positionY + pos.y * scale,
|
|
1218
|
+
at: performance.now()
|
|
1219
|
+
};
|
|
1220
|
+
}, [nodeOf]);
|
|
1080
1221
|
const fitGraph = useCallback((animationMs = 0) => {
|
|
1081
1222
|
const container = containerRef.current;
|
|
1082
1223
|
const content = graphContentRef.current;
|
|
@@ -1100,8 +1241,26 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1100
1241
|
const graphH = maxY - minY;
|
|
1101
1242
|
const containerW = container.clientWidth;
|
|
1102
1243
|
const containerH = container.clientHeight;
|
|
1103
|
-
if (graphW === 0 || graphH === 0) return;
|
|
1104
1244
|
const margin = Math.min(containerW, containerH) * .05;
|
|
1245
|
+
const pending = held.current;
|
|
1246
|
+
held.current = null;
|
|
1247
|
+
const node = pending && performance.now() - pending.at < HOLD_MS ? nodeOf(pending.job) : null;
|
|
1248
|
+
const viewing = editor && viewed.current && animationMs === 0;
|
|
1249
|
+
if (pending && node || viewing) {
|
|
1250
|
+
const { positionX, positionY, scale: current } = transform.instance.state;
|
|
1251
|
+
const pos = pending && node ? offsetWithin(node, content) : null;
|
|
1252
|
+
const x = pending && pos ? pending.x - pos.x * current : positionX;
|
|
1253
|
+
const y = pending && pos ? pending.y - pos.y * current : positionY;
|
|
1254
|
+
transform.setTransform(x, y, current, 0);
|
|
1255
|
+
const dx = intoView(x + minX * current, x + maxX * current, margin, containerW - margin);
|
|
1256
|
+
const dy = intoView(y + minY * current, y + maxY * current, margin, containerH - margin);
|
|
1257
|
+
requestAnimationFrame(() => {
|
|
1258
|
+
if (dx !== 0 || dy !== 0) transform.setTransform(x + dx, y + dy, current, FIT_ANIMATION_MS, "easeOut");
|
|
1259
|
+
invalidateConnectors();
|
|
1260
|
+
});
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
if (graphW === 0 || graphH === 0) return;
|
|
1105
1264
|
const scaleW = (containerW - margin * 2) / graphW;
|
|
1106
1265
|
const scaleH = (containerH - margin * 2) / graphH;
|
|
1107
1266
|
const scale = Math.min(Math.max(Math.min(scaleW, scaleH), minScale), maxScale);
|
|
@@ -1117,7 +1276,11 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1117
1276
|
transform.setTransform(offsetX, offsetY, scale, 0);
|
|
1118
1277
|
invalidateConnectors();
|
|
1119
1278
|
});
|
|
1120
|
-
}, [
|
|
1279
|
+
}, [
|
|
1280
|
+
invalidateConnectors,
|
|
1281
|
+
nodeOf,
|
|
1282
|
+
editor
|
|
1283
|
+
]);
|
|
1121
1284
|
const fitWhenSettled = useCallback(async () => {
|
|
1122
1285
|
const container = containerRef.current;
|
|
1123
1286
|
const content = graphContentRef.current;
|
|
@@ -1142,15 +1305,55 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1142
1305
|
preview,
|
|
1143
1306
|
fixedHeight
|
|
1144
1307
|
]);
|
|
1308
|
+
const centerOn = useCallback((el) => {
|
|
1309
|
+
const container = containerRef.current;
|
|
1310
|
+
const content = graphContentRef.current;
|
|
1311
|
+
const transform = transformRef.current;
|
|
1312
|
+
if (!container || !content || !transform) return;
|
|
1313
|
+
const { scale } = transform.instance.state;
|
|
1314
|
+
const pos = offsetWithin(el, content);
|
|
1315
|
+
transform.setTransform(container.clientWidth / 2 - (pos.x + el.offsetWidth / 2) * scale, container.clientHeight / 2 - (pos.y + el.offsetHeight / 2) * scale, scale, FIT_ANIMATION_MS, "easeOut");
|
|
1316
|
+
}, []);
|
|
1317
|
+
const registerShow = editor?.registerShow;
|
|
1318
|
+
useEffect(() => {
|
|
1319
|
+
if (!editorApi) return;
|
|
1320
|
+
editorApi.registerView({ hold });
|
|
1321
|
+
return () => editorApi.registerView(null);
|
|
1322
|
+
}, [editorApi, hold]);
|
|
1323
|
+
useEffect(() => {
|
|
1324
|
+
if (!registerShow || !editorApi) return;
|
|
1325
|
+
return registerShow(({ job, step }) => {
|
|
1326
|
+
const row = [...containerRef.current?.querySelectorAll("[data-dag-job]") ?? []].find((el) => el.dataset["dagJob"] === job);
|
|
1327
|
+
if (job === void 0 || !row) return false;
|
|
1328
|
+
if (step !== void 0) setStepsOpen((prev) => new Set(prev).add(job));
|
|
1329
|
+
editorApi.focus(step === void 0 ? { job } : {
|
|
1330
|
+
job,
|
|
1331
|
+
step
|
|
1332
|
+
});
|
|
1333
|
+
requestAnimationFrame(() => centerOn(row.closest("[id^=\"node_\"]") ?? row));
|
|
1334
|
+
if (step === void 0) editorApi.editJob(job);
|
|
1335
|
+
else editorApi.editStep(job, step);
|
|
1336
|
+
return true;
|
|
1337
|
+
});
|
|
1338
|
+
}, [
|
|
1339
|
+
registerShow,
|
|
1340
|
+
editorApi,
|
|
1341
|
+
centerOn
|
|
1342
|
+
]);
|
|
1145
1343
|
const [zoomedAll, setZoomedAll] = useState("in");
|
|
1146
1344
|
const onTransform = useCallback((_, { scale }) => {
|
|
1147
1345
|
setZoomedAll(scale >= .599 ? "in" : scale <= .201 ? "out" : null);
|
|
1148
1346
|
invalidateConnectors();
|
|
1149
1347
|
}, [invalidateConnectors]);
|
|
1348
|
+
const moved = useCallback(() => {
|
|
1349
|
+
viewed.current = true;
|
|
1350
|
+
invalidateConnectors();
|
|
1351
|
+
}, [invalidateConnectors]);
|
|
1150
1352
|
const zoomBy = useCallback((step) => {
|
|
1151
1353
|
const container = containerRef.current;
|
|
1152
1354
|
const transform = transformRef.current;
|
|
1153
1355
|
if (!container || !transform) return;
|
|
1356
|
+
viewed.current = true;
|
|
1154
1357
|
const { positionX, positionY, scale } = transform.instance.state;
|
|
1155
1358
|
const next = Math.min(maxScale, Math.max(minScale, scale * Math.exp(step)));
|
|
1156
1359
|
const x = container.clientWidth / 2;
|
|
@@ -1191,7 +1394,10 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1191
1394
|
resetGraph();
|
|
1192
1395
|
setExecutedJobsPath([[], ...executedJobsPath.slice(executedJobsPathIdx, 10)]);
|
|
1193
1396
|
setExecutedJobsPathIdx(0);
|
|
1194
|
-
} else
|
|
1397
|
+
} else {
|
|
1398
|
+
viewed.current = false;
|
|
1399
|
+
fitGraph(FIT_ANIMATION_MS);
|
|
1400
|
+
}
|
|
1195
1401
|
};
|
|
1196
1402
|
const toggleExpandAll = () => {
|
|
1197
1403
|
flushSync(() => {
|
|
@@ -1261,7 +1467,15 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1261
1467
|
toggleMatrix,
|
|
1262
1468
|
openInNewGraph
|
|
1263
1469
|
]);
|
|
1264
|
-
if (!dependencyCols[0]?.length) return
|
|
1470
|
+
if (!dependencyCols[0]?.length) return editor ? /* @__PURE__ */ jsx(GraphEditorProvider, {
|
|
1471
|
+
value: editorApi,
|
|
1472
|
+
children: /* @__PURE__ */ jsx(EmptyGraphEditor, {
|
|
1473
|
+
containerRef: setContainerElement,
|
|
1474
|
+
overlays: editorOverlays,
|
|
1475
|
+
height: fixedHeight ?? "240px",
|
|
1476
|
+
removeBorder
|
|
1477
|
+
})
|
|
1478
|
+
}) : void 0;
|
|
1265
1479
|
const startDt = run.createdAt ? DateTime.fromISO(run.createdAt) : now;
|
|
1266
1480
|
const endDt = run.completedAt ? DateTime.fromISO(run.completedAt) : now;
|
|
1267
1481
|
const runtime = toAbsHumanDuration(startDt, endDt);
|
|
@@ -1294,7 +1508,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1294
1508
|
},
|
|
1295
1509
|
children: /* @__PURE__ */ jsx("span", { children: sublogIsSubworkflow ? "Open Subworkflow" : sublogShowsLog ? "Show Script" : "Show Logs" })
|
|
1296
1510
|
}) : void 0;
|
|
1297
|
-
|
|
1511
|
+
const graph = /* @__PURE__ */ jsxs("div", {
|
|
1298
1512
|
className: "flex flex-col lg:flex-row w-full",
|
|
1299
1513
|
children: [
|
|
1300
1514
|
!preview && /* @__PURE__ */ jsxs("div", {
|
|
@@ -1407,27 +1621,29 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1407
1621
|
expandedJobs,
|
|
1408
1622
|
setExpandedJobs
|
|
1409
1623
|
})
|
|
1410
|
-
}) : /* @__PURE__ */
|
|
1624
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
1411
1625
|
ref: setContainerElement,
|
|
1412
|
-
|
|
1626
|
+
tabIndex: editor ? -1 : void 0,
|
|
1627
|
+
className: cx("panel w-full overflow-hidden relative", removeBorder ? "border-none" : "border", editor && "outline-none"),
|
|
1413
1628
|
style: {
|
|
1414
1629
|
height: fixedHeight ?? (containerHeight !== null ? `${containerHeight}px` : previewHeight !== null ? `${Math.min(previewHeight, windowSize.h * .62)}px` : "62vh"),
|
|
1415
1630
|
minHeight: previewHeight !== null && !fixedHeight ? 0 : 160
|
|
1416
1631
|
},
|
|
1417
|
-
children: /* @__PURE__ */ jsx(TransformWrapper, {
|
|
1632
|
+
children: [/* @__PURE__ */ jsx(TransformWrapper, {
|
|
1418
1633
|
ref: transformRef,
|
|
1419
1634
|
minScale,
|
|
1420
1635
|
maxScale,
|
|
1421
1636
|
initialScale: maxScale,
|
|
1637
|
+
...editor ? { panning: { excluded: [EDITOR_HANDLE_CLASS] } } : {},
|
|
1422
1638
|
doubleClick: { disabled: true },
|
|
1423
1639
|
limitToBounds: false,
|
|
1424
1640
|
onInit: () => {
|
|
1425
1641
|
setTimeout(invalidateConnectors, 0);
|
|
1426
1642
|
},
|
|
1427
|
-
onPanning:
|
|
1428
|
-
onPinch:
|
|
1643
|
+
onPanning: moved,
|
|
1644
|
+
onPinch: moved,
|
|
1429
1645
|
onTransform,
|
|
1430
|
-
onWheel:
|
|
1646
|
+
onWheel: moved,
|
|
1431
1647
|
onZoom: invalidateConnectors,
|
|
1432
1648
|
children: () => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
1433
1649
|
className: "absolute z-10 top-2 right-2 flex max-w-[calc(100%-1rem)] flex-col items-end gap-y-1",
|
|
@@ -1471,10 +1687,11 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1471
1687
|
matrixOpen,
|
|
1472
1688
|
toggleMatrix,
|
|
1473
1689
|
onReady: fitGraph,
|
|
1474
|
-
layout: placed
|
|
1690
|
+
layout: placed,
|
|
1691
|
+
editable: !!editorApi && currentPath.length === 0
|
|
1475
1692
|
}, `sg-${executedJobsPathIdx}-${pathAppend}`)
|
|
1476
1693
|
}) })] })
|
|
1477
|
-
})
|
|
1694
|
+
}), editorOverlays]
|
|
1478
1695
|
})
|
|
1479
1696
|
]
|
|
1480
1697
|
}),
|
|
@@ -1523,6 +1740,10 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
|
|
|
1523
1740
|
})
|
|
1524
1741
|
]
|
|
1525
1742
|
});
|
|
1743
|
+
return /* @__PURE__ */ jsx(GraphEditorProvider, {
|
|
1744
|
+
value: editorApi,
|
|
1745
|
+
children: graph
|
|
1746
|
+
});
|
|
1526
1747
|
}
|
|
1527
1748
|
var isSlot = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
1528
1749
|
/** Each job's place on the graph from its `position`; none when no job has one. */
|
|
@@ -1617,14 +1838,19 @@ function DependencyGraphPreview(inputs) {
|
|
|
1617
1838
|
const execute = isJobRecord(on) ? on["execute"] : void 0;
|
|
1618
1839
|
const executeInputs = isJobRecord(execute) ? execute["inputs"] : void 0;
|
|
1619
1840
|
const workflowInputs = isJobRecord(executeInputs) ? executeInputs : void 0;
|
|
1841
|
+
const editable = !!inputs.editor;
|
|
1620
1842
|
const executedJobs = useMemo(() => {
|
|
1621
|
-
const withCleanup = addCleanupSteps({ jobs
|
|
1843
|
+
const withCleanup = addCleanupSteps({ jobs: editable ? Object.fromEntries(Object.entries(jobs).map(([name, job]) => {
|
|
1844
|
+
const { if: condition, ...rest } = job;
|
|
1845
|
+
return [name, condition === false ? rest : job];
|
|
1846
|
+
})) : jobs });
|
|
1622
1847
|
const evaluated = ready ? withRunExpressions(engine, withCleanup, workflowInputs) : withCleanup;
|
|
1623
1848
|
return editing ? editing.expandMatrixJobs(evaluated) : evaluated;
|
|
1624
1849
|
}, [
|
|
1625
1850
|
engine,
|
|
1626
1851
|
editing,
|
|
1627
1852
|
ready,
|
|
1853
|
+
editable,
|
|
1628
1854
|
jobs,
|
|
1629
1855
|
workflowInputs
|
|
1630
1856
|
]);
|
|
@@ -1637,9 +1863,12 @@ function DependencyGraphPreview(inputs) {
|
|
|
1637
1863
|
preview: true,
|
|
1638
1864
|
removeBorder: inputs.removeBorder,
|
|
1639
1865
|
layout: inputs.layout,
|
|
1866
|
+
editor: inputs.editor,
|
|
1640
1867
|
yamlJobs: jobs,
|
|
1868
|
+
inputs: workflowInputs,
|
|
1869
|
+
workflow: inputs.yml,
|
|
1641
1870
|
fixedHeight: inputs.height
|
|
1642
1871
|
});
|
|
1643
1872
|
}
|
|
1644
1873
|
//#endregion
|
|
1645
|
-
export { DependencyGraphPreview, addCleanupSteps, computeGraphLayout, DependencyGraph as default };
|
|
1874
|
+
export { DependencyGraphPreview, addCleanupSteps, computeGraphLayout, DependencyGraph as default, intoView };
|