@revenexx/studio-integrations 1.3.0 → 1.4.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/CHANGELOG.md +457 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/Integrations/CanvasShortcutsDialog.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/CanvasShortcutsDialog.vue +53 -0
- package/dist/runtime/components/Integrations/CanvasShortcutsDialog.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +61 -29
- package/dist/runtime/components/Integrations/EditorTip.vue +2 -15
- package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +10 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue +94 -49
- package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +10 -0
- package/dist/runtime/components/Integrations/NodeInspector.vue +37 -60
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +80 -33
- package/dist/runtime/components/Integrations/TemplateCard.d.vue.ts +0 -4
- package/dist/runtime/components/Integrations/TemplateCard.vue +3 -6
- package/dist/runtime/components/Integrations/TemplateCard.vue.d.ts +0 -4
- package/dist/runtime/components/Integrations/TemplateInstallStep.d.vue.ts +25 -0
- package/dist/runtime/components/Integrations/TemplateInstallStep.vue +198 -0
- package/dist/runtime/components/Integrations/TemplateInstallStep.vue.d.ts +25 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +2 -2
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +22 -40
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +2 -2
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +94 -65
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +36 -2
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +165 -56
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +36 -2
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.d.vue.ts +6 -2
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +4 -106
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue.d.ts +6 -2
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +22 -11
- package/dist/runtime/composables/useCanvasShortcuts.d.ts +34 -0
- package/dist/runtime/composables/useCanvasShortcuts.js +11 -8
- package/dist/runtime/composables/useCredentialTypes.js +3 -9
- package/dist/runtime/composables/useIntegrationsCredentials.js +6 -14
- package/dist/runtime/composables/useIntegrationsNodes.js +2 -2
- package/dist/runtime/composables/useIntegrationsRuns.js +8 -13
- package/dist/runtime/composables/useIntegrationsSecrets.js +5 -5
- package/dist/runtime/composables/useIntegrationsTemplates.js +5 -8
- package/dist/runtime/composables/useIntegrationsTriggers.js +1 -4
- package/dist/runtime/composables/useIntegrationsWorkflows.js +5 -7
- package/dist/runtime/data/canvasShortcuts.d.ts +208 -0
- package/dist/runtime/data/canvasShortcuts.js +68 -0
- package/dist/runtime/i18n/messages/de.json +30 -16
- package/dist/runtime/i18n/messages/en.json +30 -16
- package/dist/runtime/pages/integrations/credentials.vue +40 -18
- package/dist/runtime/pages/integrations/templates/[slug].vue +22 -132
- package/dist/runtime/pages/integrations/workflows/[id].vue +128 -33
- package/dist/runtime/utils/apiEnvelope.d.ts +27 -0
- package/dist/runtime/utils/apiEnvelope.js +20 -0
- package/dist/runtime/utils/apiError.d.ts +35 -8
- package/dist/runtime/utils/apiError.js +12 -12
- package/dist/runtime/utils/configDefaults.d.ts +18 -0
- package/dist/runtime/utils/configDefaults.js +7 -0
- package/dist/runtime/utils/errorPathAdvice.d.ts +60 -0
- package/dist/runtime/utils/errorPathAdvice.js +19 -0
- package/dist/runtime/utils/notify.d.ts +2 -2
- package/dist/runtime/utils/runEnvelope.d.ts +12 -0
- package/dist/runtime/utils/runEnvelope.js +2 -1
- package/dist/runtime/utils/selectOptions.d.ts +48 -0
- package/dist/runtime/utils/selectOptions.js +19 -0
- package/dist/runtime/utils/shortcutLabel.d.ts +40 -0
- package/dist/runtime/utils/shortcutLabel.js +48 -0
- package/package.json +1 -1
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
DropdownMenuTrigger,
|
|
29
29
|
TooltipProvider
|
|
30
30
|
} from "@revenexx/studio";
|
|
31
|
-
import { Braces, Database, EllipsisVertical, GripVertical, Group as GroupIcon, Hand, Map as MapIcon, Minus, MousePointer2, Plus, Settings2, StickyNote } from "lucide-vue-next";
|
|
31
|
+
import { Braces, Database, EllipsisVertical, GripVertical, Group as GroupIcon, Hand, Keyboard, Map as MapIcon, Minus, MousePointer2, Plus, Settings2, StickyNote } from "lucide-vue-next";
|
|
32
32
|
import "@vue-flow/core/dist/style.css";
|
|
33
33
|
import "@vue-flow/core/dist/theme-default.css";
|
|
34
34
|
import "@vue-flow/minimap/dist/style.css";
|
|
@@ -40,15 +40,19 @@ import WorkflowTriggerView from "./WorkflowTriggerView.vue";
|
|
|
40
40
|
import StickyNoteView from "./StickyNoteView.vue";
|
|
41
41
|
import GroupFrameView from "./GroupFrameView.vue";
|
|
42
42
|
import WorkflowContextMenu, {} from "./WorkflowContextMenu.vue";
|
|
43
|
+
import CanvasShortcutsDialog from "./CanvasShortcutsDialog.vue";
|
|
43
44
|
import WorkflowStateNamespacesDialog from "./WorkflowStateNamespacesDialog.vue";
|
|
44
45
|
import WorkflowVariablesDialog from "./WorkflowVariablesDialog.vue";
|
|
45
46
|
import { useCanvasShortcuts } from "../../composables/useCanvasShortcuts";
|
|
47
|
+
import { libraryKeyCodes, primaryShortcut, shortcutKeys } from "../../data/canvasShortcuts";
|
|
46
48
|
import { usePaletteLayout } from "../../composables/usePaletteLayout";
|
|
47
49
|
import { useMiniMapLayout } from "../../composables/useMiniMapLayout";
|
|
48
50
|
import { toast } from "vue-sonner";
|
|
49
51
|
import WorkflowEdgeView from "./WorkflowEdgeView.vue";
|
|
50
52
|
import { layoutWorkflowNodes } from "./workflowLayout";
|
|
51
|
-
import {
|
|
53
|
+
import { defaultsFor } from "../../utils/configDefaults";
|
|
54
|
+
import { nodeDisplayLabel } from "../../utils/validationFindings";
|
|
55
|
+
import { TRIGGER_TEMPLATES, findManifest, newestExecutableVersion } from "../../data/integrationNodeCatalog";
|
|
52
56
|
import { isTerminalManifest, portsForNode } from "../../data/nodeInputData";
|
|
53
57
|
import { computeLoopBodies, iteratorNodeIds, nodeLoopData } from "../../data/loopBody";
|
|
54
58
|
import { inputHandleId, outputHandleId, portFromHandleId } from "../../data/handleId";
|
|
@@ -383,8 +387,32 @@ function edgeColorByKind(kind) {
|
|
|
383
387
|
syncFromBlob();
|
|
384
388
|
const paneReady = ref(false);
|
|
385
389
|
const pendingReveal = ref(null);
|
|
386
|
-
|
|
387
|
-
|
|
390
|
+
function liftAboveControlPane() {
|
|
391
|
+
const bar = controlBar.value?.getBoundingClientRect();
|
|
392
|
+
const wrap = canvasWrapRef.value?.getBoundingClientRect();
|
|
393
|
+
const vp = flow.viewport.value;
|
|
394
|
+
if (!bar || !wrap || !vp) return;
|
|
395
|
+
let top = Number.POSITIVE_INFINITY;
|
|
396
|
+
let bottom = Number.NEGATIVE_INFINITY;
|
|
397
|
+
for (const n of vfNodes.value) {
|
|
398
|
+
const height = flow.findNode(n.id)?.dimensions?.height ?? 76;
|
|
399
|
+
top = Math.min(top, n.position.y);
|
|
400
|
+
bottom = Math.max(bottom, n.position.y + height);
|
|
401
|
+
}
|
|
402
|
+
if (!Number.isFinite(top) || !Number.isFinite(bottom)) return;
|
|
403
|
+
const CLEARANCE = 8;
|
|
404
|
+
const overlap = wrap.top + vp.y + bottom * vp.zoom - bar.top + CLEARANCE;
|
|
405
|
+
if (overlap <= 0) return;
|
|
406
|
+
const roomAtTop = wrap.top + vp.y + top * vp.zoom - wrap.top - CLEARANCE;
|
|
407
|
+
const lift = Math.min(overlap, Math.max(roomAtTop, 0));
|
|
408
|
+
if (lift <= 0) return;
|
|
409
|
+
flow.setViewport({ ...vp, y: vp.y - lift });
|
|
410
|
+
}
|
|
411
|
+
flow.onPaneReady(async () => {
|
|
412
|
+
await nextTick();
|
|
413
|
+
void canvasWrapRef.value?.getBoundingClientRect();
|
|
414
|
+
await flow.fitView({ padding: { x: 0.2, top: 0.2, bottom: "96px" }, maxZoom: 1 });
|
|
415
|
+
liftAboveControlPane();
|
|
388
416
|
paneReady.value = true;
|
|
389
417
|
if (pendingReveal.value) {
|
|
390
418
|
centerOnNode(pendingReveal.value);
|
|
@@ -837,7 +865,17 @@ function revealNode(id) {
|
|
|
837
865
|
selectedId.value = id;
|
|
838
866
|
}
|
|
839
867
|
}
|
|
840
|
-
|
|
868
|
+
function showNodeOnCanvas(id) {
|
|
869
|
+
const folded = collapsedGroupOf().get(id);
|
|
870
|
+
if (folded) patchGroup(folded.id, { collapsed: false });
|
|
871
|
+
if (blob.value.nodes.some((n) => n.id === id)) {
|
|
872
|
+
markBorn(id);
|
|
873
|
+
syncFromBlob();
|
|
874
|
+
}
|
|
875
|
+
if (paneReady.value) centerOnNode(id);
|
|
876
|
+
else pendingReveal.value = id;
|
|
877
|
+
}
|
|
878
|
+
defineExpose({ revealNode, showNodeOnCanvas, attachErrorStop });
|
|
841
879
|
const selectedUpstreamOutputs = computed(() => {
|
|
842
880
|
const id = selectedId.value;
|
|
843
881
|
if (!id) return [];
|
|
@@ -960,7 +998,7 @@ function addFromPayload(payload, pos) {
|
|
|
960
998
|
id,
|
|
961
999
|
nodeSlug: manifest.slug,
|
|
962
1000
|
nodeVersion: manifest.version,
|
|
963
|
-
config:
|
|
1001
|
+
config: defaultsFor(manifest.config ?? []),
|
|
964
1002
|
position: at
|
|
965
1003
|
});
|
|
966
1004
|
adoptIntoGroupAt(id, at);
|
|
@@ -1005,7 +1043,7 @@ function onPaletteInsert(payload) {
|
|
|
1005
1043
|
id,
|
|
1006
1044
|
nodeSlug: manifest.slug,
|
|
1007
1045
|
nodeVersion: manifest.version,
|
|
1008
|
-
config:
|
|
1046
|
+
config: defaultsFor(manifest.config ?? []),
|
|
1009
1047
|
position: { x: pc.pos.x, y: pc.pos.y }
|
|
1010
1048
|
});
|
|
1011
1049
|
blob.value.edges.push({
|
|
@@ -1057,7 +1095,7 @@ function spliceIntoEdge(edgeId, payload) {
|
|
|
1057
1095
|
id,
|
|
1058
1096
|
nodeSlug: manifest.slug,
|
|
1059
1097
|
nodeVersion: manifest.version,
|
|
1060
|
-
config:
|
|
1098
|
+
config: defaultsFor(manifest.config ?? []),
|
|
1061
1099
|
position: { x: snap((a.x + b.x) / 2), y: snap((a.y + b.y) / 2) }
|
|
1062
1100
|
});
|
|
1063
1101
|
blob.value.edges = blob.value.edges.filter((e) => e.id !== edgeId);
|
|
@@ -1070,12 +1108,44 @@ function spliceIntoEdge(edgeId, payload) {
|
|
|
1070
1108
|
syncFromBlob();
|
|
1071
1109
|
push();
|
|
1072
1110
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
return
|
|
1111
|
+
const STOP_AND_ERROR_SLUG = "revenexx:stop-and-error";
|
|
1112
|
+
function attachErrorStop(sourceNodeId, port) {
|
|
1113
|
+
const source = blob.value.nodes.find((n) => n.id === sourceNodeId);
|
|
1114
|
+
const version = newestExecutableVersion(STOP_AND_ERROR_SLUG);
|
|
1115
|
+
const manifest = version ? findManifest(STOP_AND_ERROR_SLUG, version) : null;
|
|
1116
|
+
if (!source || !manifest) return;
|
|
1117
|
+
const at = nodePosition(sourceNodeId);
|
|
1118
|
+
const id = `n-${Date.now()}`;
|
|
1119
|
+
blob.value.nodes.push({
|
|
1120
|
+
id,
|
|
1121
|
+
nodeSlug: manifest.slug,
|
|
1122
|
+
nodeVersion: manifest.version,
|
|
1123
|
+
config: {
|
|
1124
|
+
...defaultsFor(manifest.config ?? []),
|
|
1125
|
+
// The template convention verbatim: name the step that failed, then quote
|
|
1126
|
+
// its own message, so the run record says what went wrong rather than only
|
|
1127
|
+
// that something did. `errorCode` keeps the node's own default.
|
|
1128
|
+
message: t("integration.editor.errorPath.message", {
|
|
1129
|
+
label: nodeDisplayLabel(source),
|
|
1130
|
+
nodeId: source.id,
|
|
1131
|
+
port
|
|
1132
|
+
})
|
|
1133
|
+
},
|
|
1134
|
+
// Below the source and on the grid, the way the templates place theirs.
|
|
1135
|
+
// `freeSpotNear` keeps two of them off each other.
|
|
1136
|
+
position: freeSpotNear({ x: at.x, y: at.y + 180 })
|
|
1137
|
+
});
|
|
1138
|
+
blob.value.edges.push({
|
|
1139
|
+
id: `e-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,
|
|
1140
|
+
from: { nodeId: sourceNodeId, output: port },
|
|
1141
|
+
to: { nodeId: id, input: void 0 }
|
|
1142
|
+
});
|
|
1143
|
+
markBorn(id);
|
|
1144
|
+
syncFromBlob();
|
|
1145
|
+
if (paneReady.value) centerOnNode(id);
|
|
1146
|
+
else pendingReveal.value = id;
|
|
1147
|
+
push();
|
|
1148
|
+
toast.info(t("integration.editor.errorPath.toast.added", { label: nodeDisplayLabel(source) }));
|
|
1079
1149
|
}
|
|
1080
1150
|
function nodeDims(id) {
|
|
1081
1151
|
const d = flow.findNode(id)?.dimensions;
|
|
@@ -1244,9 +1314,9 @@ function setPointerMode(mode) {
|
|
|
1244
1314
|
}
|
|
1245
1315
|
}
|
|
1246
1316
|
const zoomPct = computed(() => `${Math.round((flow.viewport.value?.zoom ?? 1) * 100)}%`);
|
|
1247
|
-
const ZOOM_PRESETS = [50, 75, 100, 150, 200
|
|
1317
|
+
const ZOOM_PRESETS = [25, 50, 75, 100, 150, 200];
|
|
1248
1318
|
const MIN_ZOOM_PCT = 25;
|
|
1249
|
-
const MAX_ZOOM_PCT =
|
|
1319
|
+
const MAX_ZOOM_PCT = 200;
|
|
1250
1320
|
const zoomMenuOpen = ref(false);
|
|
1251
1321
|
const zoomInputText = ref("");
|
|
1252
1322
|
function setZoomPct(pct) {
|
|
@@ -1295,6 +1365,7 @@ async function focusPalette() {
|
|
|
1295
1365
|
paletteRef.value?.focusSearch();
|
|
1296
1366
|
}
|
|
1297
1367
|
const lightboxOpen = computed(() => !!selection.value);
|
|
1368
|
+
const shortcutsOpen = ref(false);
|
|
1298
1369
|
watch(lightboxOpen, (open) => {
|
|
1299
1370
|
if (!open) renameIntent.value = false;
|
|
1300
1371
|
});
|
|
@@ -1303,67 +1374,71 @@ function onConfigOpenAutoFocus(event) {
|
|
|
1303
1374
|
event.preventDefault();
|
|
1304
1375
|
event.target?.focus();
|
|
1305
1376
|
}
|
|
1306
|
-
const canvasHasKeyboard = computed(() => !lightboxOpen.value && !variablesOpen.value && !stateOpen.value && !props.overlayOpen);
|
|
1377
|
+
const canvasHasKeyboard = computed(() => !lightboxOpen.value && !variablesOpen.value && !stateOpen.value && !shortcutsOpen.value && !props.overlayOpen);
|
|
1378
|
+
const DELETE_KEY_CODES = libraryKeyCodes("delete");
|
|
1307
1379
|
const singleSelected = computed(() => flow.getSelectedNodes.value.length === 1 ? flow.getSelectedNodes.value[0] : null);
|
|
1308
1380
|
useCanvasShortcuts(() => ({
|
|
1309
|
-
"
|
|
1381
|
+
[shortcutKeys("open")]: {
|
|
1310
1382
|
disabled: () => !singleSelected.value,
|
|
1311
1383
|
run: () => {
|
|
1312
1384
|
selectedId.value = singleSelected.value.id;
|
|
1313
1385
|
}
|
|
1314
1386
|
},
|
|
1315
|
-
"
|
|
1387
|
+
[shortcutKeys("rename")]: {
|
|
1316
1388
|
disabled: () => !singleSelected.value,
|
|
1317
1389
|
run: () => {
|
|
1318
1390
|
renameIntent.value = true;
|
|
1319
1391
|
selectedId.value = singleSelected.value.id;
|
|
1320
1392
|
}
|
|
1321
1393
|
},
|
|
1322
|
-
"
|
|
1323
|
-
"
|
|
1394
|
+
[shortcutKeys("selectAll")]: () => flow.addSelectedNodes(flow.getNodes.value),
|
|
1395
|
+
[shortcutKeys("copy")]: {
|
|
1324
1396
|
disabled: () => !flow.getSelectedNodes.value.length,
|
|
1325
1397
|
run: () => {
|
|
1326
1398
|
void copyNodes(flow.getSelectedNodes.value.map((n) => n.id));
|
|
1327
1399
|
}
|
|
1328
1400
|
},
|
|
1329
|
-
"
|
|
1401
|
+
[shortcutKeys("paste")]: () => {
|
|
1330
1402
|
void pasteNodes();
|
|
1331
1403
|
},
|
|
1332
|
-
"
|
|
1404
|
+
[shortcutKeys("duplicate")]: {
|
|
1333
1405
|
disabled: () => !flow.getSelectedNodes.value.length,
|
|
1334
1406
|
run: () => duplicateBlobNodes(flow.getSelectedNodes.value.map((n) => n.id))
|
|
1335
1407
|
},
|
|
1336
|
-
"
|
|
1408
|
+
[shortcutKeys("group")]: {
|
|
1337
1409
|
disabled: () => !flow.getSelectedNodes.value.length,
|
|
1338
1410
|
run: () => createGroupFromSelection(flow.getSelectedNodes.value.map((n) => n.id))
|
|
1339
1411
|
},
|
|
1340
|
-
"
|
|
1341
|
-
"
|
|
1412
|
+
[shortcutKeys("run")]: { disabled: () => !!props.runBusy, run: () => emit("run") },
|
|
1413
|
+
[shortcutKeys("tidyUp")]: () => {
|
|
1342
1414
|
void tidyUp();
|
|
1343
1415
|
},
|
|
1344
|
-
"
|
|
1345
|
-
"
|
|
1346
|
-
"
|
|
1347
|
-
"
|
|
1348
|
-
"
|
|
1416
|
+
[shortcutKeys("addSticky")]: () => addSticky(),
|
|
1417
|
+
[shortcutKeys("pointerSelect")]: () => setPointerMode("select"),
|
|
1418
|
+
[shortcutKeys("pointerHand")]: () => setPointerMode("hand"),
|
|
1419
|
+
[shortcutKeys("toggleActive")]: () => emit("toggleActive"),
|
|
1420
|
+
[shortcutKeys("variables")]: () => {
|
|
1349
1421
|
variablesOpen.value = true;
|
|
1350
1422
|
},
|
|
1351
|
-
"
|
|
1423
|
+
[shortcutKeys("state")]: () => {
|
|
1352
1424
|
stateOpen.value = true;
|
|
1353
1425
|
},
|
|
1354
|
-
"
|
|
1355
|
-
"
|
|
1426
|
+
[shortcutKeys("settings")]: () => emit("openSettings"),
|
|
1427
|
+
[shortcutKeys("zoomOut")]: () => {
|
|
1356
1428
|
void flow.zoomOut({ duration: 150 });
|
|
1357
1429
|
},
|
|
1358
|
-
"
|
|
1430
|
+
[shortcutKeys("zoomIn")]: () => {
|
|
1359
1431
|
void flow.zoomIn({ duration: 150 });
|
|
1360
1432
|
},
|
|
1361
|
-
"
|
|
1362
|
-
"
|
|
1363
|
-
"
|
|
1433
|
+
[shortcutKeys("zoomReset")]: () => setZoomPct(100),
|
|
1434
|
+
[shortcutKeys("fitView")]: () => flow.fitView({ padding: 0.2, duration: 400, maxZoom: 1 }),
|
|
1435
|
+
[shortcutKeys("addNode")]: () => {
|
|
1364
1436
|
void focusPalette();
|
|
1365
1437
|
},
|
|
1366
|
-
"
|
|
1438
|
+
[shortcutKeys("overview")]: () => {
|
|
1439
|
+
shortcutsOpen.value = true;
|
|
1440
|
+
},
|
|
1441
|
+
[shortcutKeys("clearSelection")]: () => {
|
|
1367
1442
|
pendingSpliceEdgeId.value = null;
|
|
1368
1443
|
pendingConnect.value = null;
|
|
1369
1444
|
flow.removeSelectedElements();
|
|
@@ -1398,6 +1473,19 @@ const edgeTypes = {
|
|
|
1398
1473
|
:run-busy="runBusy"
|
|
1399
1474
|
@action="onMenuAction"
|
|
1400
1475
|
>
|
|
1476
|
+
<!-- `pan-activation-key-code` is null rather than left at its default, which
|
|
1477
|
+
is Space. The canvas library binds that key on the document and calls
|
|
1478
|
+
preventDefault on it, and `useCanvasShortcuts` steps aside for a key
|
|
1479
|
+
somebody upstream has already claimed — so Space renaming a node, which
|
|
1480
|
+
the shortcuts overview offers, answered nothing at all (PO-472).
|
|
1481
|
+
Nothing is given up by switching it off, and the reason is not that the
|
|
1482
|
+
drag pans anyway: in select mode `pan-on-drag` below lists the middle
|
|
1483
|
+
button only, and the library's own filter refuses a left-drag for a pan
|
|
1484
|
+
on that ground before the activation key is consulted at all. Measured:
|
|
1485
|
+
with the key claimed, Space held over a left-drag did nothing — no pan,
|
|
1486
|
+
and no rubber band either, because holding it also switched selecting
|
|
1487
|
+
off; with it freed, that drag draws the rubber band. What does change is
|
|
1488
|
+
Space over the wheel, which zooms the way the wheel alone does. -->
|
|
1401
1489
|
<VueFlow
|
|
1402
1490
|
v-model:nodes="vfNodes"
|
|
1403
1491
|
v-model:edges="vfEdges"
|
|
@@ -1414,10 +1502,11 @@ const edgeTypes = {
|
|
|
1414
1502
|
:selection-key-code="pointerMode === 'select' ? true : 'Shift'"
|
|
1415
1503
|
:pan-on-drag="pointerMode === 'hand' ? true : [1]"
|
|
1416
1504
|
:zoom-on-double-click="false"
|
|
1417
|
-
:delete-key-code="canvasHasKeyboard ?
|
|
1505
|
+
:delete-key-code="canvasHasKeyboard ? DELETE_KEY_CODES : null"
|
|
1506
|
+
:pan-activation-key-code="null"
|
|
1418
1507
|
:edges-updatable="true"
|
|
1419
1508
|
:min-zoom="0.25"
|
|
1420
|
-
:max-zoom="
|
|
1509
|
+
:max-zoom="2"
|
|
1421
1510
|
>
|
|
1422
1511
|
<Background pattern-color="#cbd5e1" :gap="20" :size="1.2" />
|
|
1423
1512
|
</VueFlow>
|
|
@@ -1657,10 +1746,11 @@ const edgeTypes = {
|
|
|
1657
1746
|
<TooltipProvider :delay-duration="250">
|
|
1658
1747
|
<div class="rounded-lg border border-gray-400/10 outline-1 outline-white/30 backdrop-blur-sm">
|
|
1659
1748
|
<div class="flex items-center gap-0.5 whitespace-nowrap border border-white bg-white rounded-lg bg-gradient-to-br from-white via-violet-50/40 to-white px-2 py-1">
|
|
1660
|
-
<!-- Smart Run: the page decides what "run" means —
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1749
|
+
<!-- Smart Run: the page decides what "run" means — a workflow that
|
|
1750
|
+
consumes trigger.payload, or leaves the mode to the caller, opens
|
|
1751
|
+
the run dialog; one that asks neither fires immediately. One
|
|
1752
|
+
button either way. -->
|
|
1753
|
+
<IntegrationsEditorTip :label="runWaiting ? t('integration.editor.tool.run.tooltipWaiting') : t('integration.editor.tool.run.tooltip')" :shortcut="primaryShortcut('run')">
|
|
1664
1754
|
<button
|
|
1665
1755
|
type="button"
|
|
1666
1756
|
class="relative flex h-8 items-center gap-1.5 rounded-lg bg-gradient-to-b from-emerald-500 to-emerald-600 px-3.5 text-sm font-medium text-white transition after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:shadow-[inset_0_1px_0_rgba(255,255,255,0.3),inset_0_-2px_0_rgba(0,0,0,0.25)] hover:from-emerald-600 hover:to-emerald-600 active:translate-y-px disabled:opacity-60"
|
|
@@ -1678,7 +1768,7 @@ const edgeTypes = {
|
|
|
1678
1768
|
<div class="flex items-center gap-0.5 rounded-lg bg-black/[0.05] p-0.5 shadow-[inset_0_1px_2px_rgba(15,23,42,0.12)]">
|
|
1679
1769
|
<!-- Icon-only, and the tooltip is not an accessible name: each one
|
|
1680
1770
|
says what it does itself, and whether it is the active mode. -->
|
|
1681
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.select')" shortcut="
|
|
1771
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.select')" :shortcut="primaryShortcut('pointerSelect')">
|
|
1682
1772
|
<button
|
|
1683
1773
|
type="button"
|
|
1684
1774
|
:aria-label="t('integration.editor.tool.select')"
|
|
@@ -1690,7 +1780,7 @@ const edgeTypes = {
|
|
|
1690
1780
|
<MousePointer2 :size="14" />
|
|
1691
1781
|
</button>
|
|
1692
1782
|
</IntegrationsEditorTip>
|
|
1693
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.hand')" shortcut="
|
|
1783
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.hand')" :shortcut="primaryShortcut('pointerHand')">
|
|
1694
1784
|
<button
|
|
1695
1785
|
type="button"
|
|
1696
1786
|
:aria-label="t('integration.editor.tool.hand')"
|
|
@@ -1704,7 +1794,7 @@ const edgeTypes = {
|
|
|
1704
1794
|
</IntegrationsEditorTip>
|
|
1705
1795
|
</div>
|
|
1706
1796
|
|
|
1707
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.tidyUp')" shortcut="
|
|
1797
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.tidyUp')" :shortcut="primaryShortcut('tidyUp')">
|
|
1708
1798
|
<button
|
|
1709
1799
|
type="button"
|
|
1710
1800
|
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
@@ -1714,7 +1804,7 @@ const edgeTypes = {
|
|
|
1714
1804
|
{{ t("integration.editor.tool.tidyUp") }}
|
|
1715
1805
|
</button>
|
|
1716
1806
|
</IntegrationsEditorTip>
|
|
1717
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.fitView.tooltip')" shortcut="
|
|
1807
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.fitView.tooltip')" :shortcut="primaryShortcut('fitView')">
|
|
1718
1808
|
<button
|
|
1719
1809
|
type="button"
|
|
1720
1810
|
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
@@ -1724,7 +1814,7 @@ const edgeTypes = {
|
|
|
1724
1814
|
{{ t("integration.editor.tool.fitView.label") }}
|
|
1725
1815
|
</button>
|
|
1726
1816
|
</IntegrationsEditorTip>
|
|
1727
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.addSticky.tooltip')" shortcut="
|
|
1817
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.addSticky.tooltip')" :shortcut="primaryShortcut('addSticky')">
|
|
1728
1818
|
<button
|
|
1729
1819
|
type="button"
|
|
1730
1820
|
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
@@ -1744,7 +1834,7 @@ const edgeTypes = {
|
|
|
1744
1834
|
{{ t("integration.editor.tool.addGroup.label") }}
|
|
1745
1835
|
</button>
|
|
1746
1836
|
</IntegrationsEditorTip>
|
|
1747
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.variables.tooltip')" shortcut="
|
|
1837
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.variables.tooltip')" :shortcut="primaryShortcut('variables')">
|
|
1748
1838
|
<button
|
|
1749
1839
|
type="button"
|
|
1750
1840
|
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
@@ -1755,7 +1845,7 @@ const edgeTypes = {
|
|
|
1755
1845
|
<span v-if="variableCount" class="rounded-lg bg-muted px-1.5 text-xs tabular-nums text-muted-foreground">{{ variableCount }}</span>
|
|
1756
1846
|
</button>
|
|
1757
1847
|
</IntegrationsEditorTip>
|
|
1758
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.state.tooltip')" shortcut="
|
|
1848
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.state.tooltip')" :shortcut="primaryShortcut('state')">
|
|
1759
1849
|
<button
|
|
1760
1850
|
type="button"
|
|
1761
1851
|
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
@@ -1766,7 +1856,7 @@ const edgeTypes = {
|
|
|
1766
1856
|
<span v-if="stateCount" class="rounded-lg bg-muted px-1.5 text-xs tabular-nums text-muted-foreground">{{ stateCount }}</span>
|
|
1767
1857
|
</button>
|
|
1768
1858
|
</IntegrationsEditorTip>
|
|
1769
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.settings.tooltip')" shortcut="
|
|
1859
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.settings.tooltip')" :shortcut="primaryShortcut('settings')">
|
|
1770
1860
|
<button
|
|
1771
1861
|
type="button"
|
|
1772
1862
|
class="flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-sm font-medium text-foreground transition hover:bg-black/[0.04]"
|
|
@@ -1776,10 +1866,25 @@ const edgeTypes = {
|
|
|
1776
1866
|
{{ t("integration.editor.tool.settings.label") }}
|
|
1777
1867
|
</button>
|
|
1778
1868
|
</IntegrationsEditorTip>
|
|
1869
|
+
<!-- The overview, and the one control that has to be reachable without
|
|
1870
|
+
already knowing a key: it is where the other keys are learnt. Its
|
|
1871
|
+
tooltip carries `?` for the same reason — the pane teaches the key
|
|
1872
|
+
that teaches the rest. Icon-only, so it carries a name of its own
|
|
1873
|
+
(`specs/accessibility.md` AC-2). -->
|
|
1874
|
+
<IntegrationsEditorTip :label="t('integration.canvas.shortcuts.dialog.title')" :shortcut="primaryShortcut('overview')">
|
|
1875
|
+
<button
|
|
1876
|
+
type="button"
|
|
1877
|
+
:aria-label="t('integration.canvas.shortcuts.dialog.title')"
|
|
1878
|
+
class="flex size-8 items-center justify-center rounded-lg text-foreground transition hover:bg-black/[0.04]"
|
|
1879
|
+
@click="shortcutsOpen = true"
|
|
1880
|
+
>
|
|
1881
|
+
<Keyboard :size="14" />
|
|
1882
|
+
</button>
|
|
1883
|
+
</IntegrationsEditorTip>
|
|
1779
1884
|
|
|
1780
1885
|
<div class="mx-1 h-5 w-px bg-black/10" />
|
|
1781
1886
|
|
|
1782
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomOut')" shortcut="
|
|
1887
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomOut')" :shortcut="primaryShortcut('zoomOut')">
|
|
1783
1888
|
<button
|
|
1784
1889
|
type="button"
|
|
1785
1890
|
:aria-label="t('integration.editor.tool.zoomOut')"
|
|
@@ -1792,7 +1897,7 @@ const edgeTypes = {
|
|
|
1792
1897
|
<!-- Tooltip sits on a wrapper span so its as-child merge never
|
|
1793
1898
|
touches the dropdown trigger (merging both onto one button
|
|
1794
1899
|
swallowed the trigger's pointerdown and the menu never opened). -->
|
|
1795
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomLevel.tooltip')" shortcut="
|
|
1900
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomLevel.tooltip')" :shortcut="primaryShortcut('zoomReset')">
|
|
1796
1901
|
<span class="inline-flex">
|
|
1797
1902
|
<DropdownMenu v-model:open="zoomMenuOpen">
|
|
1798
1903
|
<DropdownMenuTrigger as-child>
|
|
@@ -1834,7 +1939,7 @@ const edgeTypes = {
|
|
|
1834
1939
|
</DropdownMenu>
|
|
1835
1940
|
</span>
|
|
1836
1941
|
</IntegrationsEditorTip>
|
|
1837
|
-
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomIn')" shortcut="
|
|
1942
|
+
<IntegrationsEditorTip :label="t('integration.editor.tool.zoomIn')" :shortcut="primaryShortcut('zoomIn')">
|
|
1838
1943
|
<button
|
|
1839
1944
|
type="button"
|
|
1840
1945
|
:aria-label="t('integration.editor.tool.zoomIn')"
|
|
@@ -1880,6 +1985,10 @@ const edgeTypes = {
|
|
|
1880
1985
|
@update:variables="updateVariables"
|
|
1881
1986
|
/>
|
|
1882
1987
|
|
|
1988
|
+
<!-- Every key this canvas answers, opened with `?`. Rendered here rather
|
|
1989
|
+
than at the page: the keys are the canvas's, and so is the list. -->
|
|
1990
|
+
<CanvasShortcutsDialog v-model:open="shortcutsOpen" />
|
|
1991
|
+
|
|
1883
1992
|
<!-- Node/trigger configuration — a near-fullscreen workbench lightbox
|
|
1884
1993
|
(Input pane / Parameters+Settings tabs / Save+Cancel footer). The
|
|
1885
1994
|
inspector edits a draft; closing without Save discards it. -->
|
|
@@ -42,17 +42,51 @@ type __VLS_Props = {
|
|
|
42
42
|
* id that is on the canvas is in the blob by construction.
|
|
43
43
|
*/
|
|
44
44
|
declare function revealNode(id: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Point at a node without opening it — for a reader who has to look at the
|
|
47
|
+
* card's *surroundings* rather than at its settings.
|
|
48
|
+
*
|
|
49
|
+
* The deliberate difference from {@link revealNode} is the missing selection,
|
|
50
|
+
* and with it the missing settings lightbox. That is the whole reason there are
|
|
51
|
+
* two functions: the validation banner sends someone to a field at fault, and
|
|
52
|
+
* the dialog is where that field is. The error-path advice sends them to a port
|
|
53
|
+
* with nothing on it, and the question they have to answer — where should this
|
|
54
|
+
* failure go? — is answered by the graph around the card, which a dialog over
|
|
55
|
+
* the canvas covers up.
|
|
56
|
+
*
|
|
57
|
+
* Marked with the same pulse a newly created card gets, because the job is the
|
|
58
|
+
* same one: say which of thirty cards is the one meant.
|
|
59
|
+
*/
|
|
60
|
+
declare function showNodeOnCanvas(id: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Hang a Stop-and-Error step off a node's error output and wire it up
|
|
63
|
+
* (specs/workflow-advice.md AC-3).
|
|
64
|
+
*
|
|
65
|
+
* The advice strip can tell an author their error output leads nowhere; on its
|
|
66
|
+
* own that is a reprimand without a remedy, because the repair — drop a node,
|
|
67
|
+
* pick the right one, connect it, write an expression quoting the failing step's
|
|
68
|
+
* message — is four steps of tedium they have to already know. Every template we
|
|
69
|
+
* ship does exactly this, twenty-five times over, so the shape is settled and
|
|
70
|
+
* worth one click.
|
|
71
|
+
*
|
|
72
|
+
* Leaves the result unsaved and unopened, like every other insertion here: the
|
|
73
|
+
* new step is highlighted and the author decides whether to keep it. Deleting it
|
|
74
|
+
* is the undo, because this editor has no undo stack to hook into.
|
|
75
|
+
*/
|
|
76
|
+
declare function attachErrorStop(sourceNodeId: string, port: string): void;
|
|
45
77
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {
|
|
46
78
|
revealNode: typeof revealNode;
|
|
79
|
+
showNodeOnCanvas: typeof showNodeOnCanvas;
|
|
80
|
+
attachErrorStop: typeof attachErrorStop;
|
|
47
81
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
48
|
-
change: (blob: WorkflowBlob) => any;
|
|
49
82
|
run: () => any;
|
|
50
83
|
toggleActive: () => any;
|
|
84
|
+
change: (blob: WorkflowBlob) => any;
|
|
51
85
|
openSettings: () => any;
|
|
52
86
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
53
|
-
onChange?: ((blob: WorkflowBlob) => any) | undefined;
|
|
54
87
|
onRun?: (() => any) | undefined;
|
|
55
88
|
onToggleActive?: (() => any) | undefined;
|
|
89
|
+
onChange?: ((blob: WorkflowBlob) => any) | undefined;
|
|
56
90
|
onOpenSettings?: (() => any) | undefined;
|
|
57
91
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
58
92
|
export default _default;
|
|
@@ -3,9 +3,13 @@ import '@vue-flow/core/dist/theme-default.css';
|
|
|
3
3
|
import type { Workflow } from '../../types/integrations.js';
|
|
4
4
|
type __VLS_Props = {
|
|
5
5
|
workflow: Workflow;
|
|
6
|
-
/**
|
|
6
|
+
/** The run to replay (deep-link from the Runs table). */
|
|
7
7
|
initialRunId?: string | null;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Accepted and ignored since PO-350 — the panel has no other mode
|
|
10
|
+
* to switch out of. Kept so a host passing it keeps working; drop it at the
|
|
11
|
+
* next major.
|
|
12
|
+
*/
|
|
9
13
|
single?: boolean;
|
|
10
14
|
};
|
|
11
15
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|