@revenexx/studio-integrations 0.1.3 → 0.2.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/dist/module.json +1 -1
- package/dist/runtime/components/Integrations/CredentialCreateDialog.d.vue.ts +13 -0
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +279 -0
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue.d.ts +13 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.d.vue.ts +20 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +342 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue.d.ts +20 -0
- package/dist/runtime/components/Integrations/CredentialLogo.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/CredentialLogo.vue +37 -0
- package/dist/runtime/components/Integrations/CredentialLogo.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +364 -0
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/CredentialTypePicker.d.vue.ts +15 -0
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue +71 -0
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue.d.ts +15 -0
- package/dist/runtime/components/Integrations/DeadLettersPanel.d.vue.ts +5 -0
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue +151 -0
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue.d.ts +5 -0
- package/dist/runtime/components/Integrations/EditorTip.d.vue.ts +17 -0
- package/dist/runtime/components/Integrations/EditorTip.vue +46 -0
- package/dist/runtime/components/Integrations/EditorTip.vue.d.ts +17 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue +64 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +19 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue +236 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +19 -0
- package/dist/runtime/components/Integrations/GroupFrameView.d.vue.ts +28 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue +222 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue.d.ts +28 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue +184 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.d.vue.ts +16 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue +102 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue.d.ts +16 -0
- package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +23 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue +587 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +23 -0
- package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue +80 -0
- package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +22 -3
- package/dist/runtime/components/Integrations/NodeInspector.vue +1074 -294
- package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +22 -3
- package/dist/runtime/components/Integrations/NodeLogo.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/NodeLogo.vue +38 -0
- package/dist/runtime/components/Integrations/NodeLogo.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/NodePalette.d.vue.ts +22 -1
- package/dist/runtime/components/Integrations/NodePalette.vue +411 -90
- package/dist/runtime/components/Integrations/NodePalette.vue.d.ts +22 -1
- package/dist/runtime/components/Integrations/QueryBuilder.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/QueryBuilder.vue +239 -0
- package/dist/runtime/components/Integrations/QueryBuilder.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/{RunDetailDialog.d.vue.ts → RunActionsMenu.d.vue.ts} +3 -4
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +86 -0
- package/dist/runtime/components/Integrations/{RunDetailDialog.vue.d.ts → RunActionsMenu.vue.d.ts} +3 -4
- package/dist/runtime/components/Integrations/RunDetailPanel.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +777 -0
- package/dist/runtime/components/Integrations/RunDetailPanel.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/RunPayloadInput.d.vue.ts +13 -0
- package/dist/runtime/components/Integrations/RunPayloadInput.vue +175 -0
- package/dist/runtime/components/Integrations/RunPayloadInput.vue.d.ts +13 -0
- package/dist/runtime/components/Integrations/RunResponseModal.d.vue.ts +27 -0
- package/dist/runtime/components/Integrations/RunResponseModal.vue +84 -0
- package/dist/runtime/components/Integrations/RunResponseModal.vue.d.ts +27 -0
- package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +21 -0
- package/dist/runtime/components/Integrations/RunsTable.vue +114 -0
- package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +21 -0
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.d.vue.ts +11 -0
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +91 -0
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue.d.ts +11 -0
- package/dist/runtime/components/Integrations/Sidebar.vue +1 -0
- package/dist/runtime/components/Integrations/StickyNoteView.d.vue.ts +28 -0
- package/dist/runtime/components/Integrations/StickyNoteView.vue +208 -0
- package/dist/runtime/components/Integrations/StickyNoteView.vue.d.ts +28 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.d.vue.ts +29 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +201 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue.d.ts +29 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +32 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +138 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +32 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +322 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.d.vue.ts +18 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +63 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue.d.ts +18 -0
- package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +12 -1
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +68 -6
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +12 -1
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +8 -1
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +1424 -144
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +8 -1
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +417 -0
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowIconPicker.d.vue.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue +89 -0
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue.d.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowIconView.d.vue.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowIconView.vue +35 -0
- package/dist/runtime/components/Integrations/WorkflowIconView.vue.d.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +5 -1
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +114 -84
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +5 -1
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +654 -0
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.d.vue.ts +36 -0
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue +136 -0
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue.d.ts +36 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue +63 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +35 -15
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.d.vue.ts +13 -0
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +265 -0
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue.d.ts +13 -0
- package/dist/runtime/components/Integrations/WorkflowsTable.d.vue.ts +4 -1
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +122 -39
- package/dist/runtime/components/Integrations/WorkflowsTable.vue.d.ts +4 -1
- package/dist/runtime/components/Integrations/workflowLayout.d.ts +5 -0
- package/dist/runtime/components/Integrations/workflowLayout.js +5 -3
- package/dist/runtime/composables/integrationsApi.d.ts +6 -2
- package/dist/runtime/composables/integrationsApi.js +5 -4
- package/dist/runtime/composables/useCanvasShortcuts.d.ts +37 -0
- package/dist/runtime/composables/useCanvasShortcuts.js +62 -0
- package/dist/runtime/composables/useIntegrationsDeadLetters.d.ts +22 -0
- package/dist/runtime/composables/useIntegrationsDeadLetters.js +50 -0
- package/dist/runtime/composables/useIntegrationsNodes.d.ts +4 -0
- package/dist/runtime/composables/useIntegrationsNodes.js +6 -3
- package/dist/runtime/composables/useIntegrationsRevisions.d.ts +40 -0
- package/dist/runtime/composables/useIntegrationsRevisions.js +51 -0
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +21 -1
- package/dist/runtime/composables/useIntegrationsRuns.js +92 -4
- package/dist/runtime/composables/useIntegrationsTemplates.d.ts +1 -0
- package/dist/runtime/composables/useIntegrationsTemplates.js +32 -4
- package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +1 -0
- package/dist/runtime/composables/useIntegrationsWorkflows.js +57 -1
- package/dist/runtime/composables/useMiniMapLayout.d.ts +34 -0
- package/dist/runtime/composables/useMiniMapLayout.js +119 -0
- package/dist/runtime/composables/useNodeConfigResolve.d.ts +43 -0
- package/dist/runtime/composables/useNodeConfigResolve.js +123 -0
- package/dist/runtime/composables/useNodeDrag.d.ts +22 -0
- package/dist/runtime/composables/useNodeDrag.js +10 -0
- package/dist/runtime/composables/usePaletteLayout.d.ts +41 -0
- package/dist/runtime/composables/usePaletteLayout.js +113 -0
- package/dist/runtime/data/expressionEditor.d.ts +22 -0
- package/dist/runtime/data/expressionEditor.js +40 -0
- package/dist/runtime/data/integrationNodeCatalog.js +8 -8
- package/dist/runtime/data/nodeInputData.d.ts +37 -0
- package/dist/runtime/data/nodeInputData.js +62 -0
- package/dist/runtime/data/nodeRunData.d.ts +56 -0
- package/dist/runtime/data/nodeRunData.js +91 -0
- package/dist/runtime/data/payloadForm.d.ts +44 -0
- package/dist/runtime/data/payloadForm.js +126 -0
- package/dist/runtime/data/workflowIconCatalog.d.ts +34 -0
- package/dist/runtime/data/workflowIconCatalog.js +116 -0
- package/dist/runtime/pages/integrations/audit.vue +25 -35
- package/dist/runtime/pages/integrations/credentials.vue +117 -122
- package/dist/runtime/pages/integrations/index.vue +133 -36
- package/dist/runtime/pages/integrations/runs.vue +125 -75
- package/dist/runtime/pages/integrations/schedules.vue +5 -16
- package/dist/runtime/pages/integrations/secrets.vue +1 -3
- package/dist/runtime/pages/integrations/workflows/[id].vue +599 -194
- package/dist/runtime/pages/integrations/workflows/index.vue +10 -8
- package/dist/runtime/types/integrations.d.ts +190 -4
- package/dist/runtime/utils/credentialState.d.ts +28 -0
- package/dist/runtime/utils/credentialState.js +29 -0
- package/dist/runtime/utils/localize.d.ts +3 -1
- package/dist/runtime/utils/localize.js +1 -2
- package/dist/runtime/utils/statusStyle.d.ts +6 -0
- package/dist/runtime/utils/statusStyle.js +15 -0
- package/package.json +12 -2
- package/dist/runtime/components/Integrations/RunDetailDialog.vue +0 -169
- package/dist/runtime/pages/integrations/workflows/new.d.vue.ts +0 -2
- package/dist/runtime/pages/integrations/workflows/new.vue +0 -153
- package/dist/runtime/pages/integrations/workflows/new.vue.d.ts +0 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, nextTick, ref } from "vue";
|
|
3
|
+
import { Handle, Position, useVueFlow } from "@vue-flow/core";
|
|
4
|
+
import { NodeToolbar } from "@vue-flow/node-toolbar";
|
|
5
|
+
import { ChevronsDownUp, ChevronsUpDown, Trash2, Ungroup } from "lucide-vue-next";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
id: { type: String, required: true },
|
|
8
|
+
data: { type: Object, required: true },
|
|
9
|
+
selected: { type: Boolean, required: false }
|
|
10
|
+
});
|
|
11
|
+
defineEmits(["updateNodeInternals"]);
|
|
12
|
+
const GROUP_COLORS = [
|
|
13
|
+
{ bg: "rgba(254,243,199,0.45)", border: "#fcd34d", chip: "#f59e0b" },
|
|
14
|
+
{ bg: "rgba(255,237,213,0.45)", border: "#fdba74", chip: "#f97316" },
|
|
15
|
+
{ bg: "rgba(255,228,230,0.45)", border: "#fda4af", chip: "#f43f5e" },
|
|
16
|
+
{ bg: "rgba(220,252,231,0.45)", border: "#86efac", chip: "#10b981" },
|
|
17
|
+
{ bg: "rgba(219,234,254,0.45)", border: "#93c5fd", chip: "#3b82f6" },
|
|
18
|
+
{ bg: "rgba(237,233,254,0.45)", border: "#c4b5fd", chip: "#8b5cf6" },
|
|
19
|
+
{ bg: "rgba(245,245,244,0.6)", border: "#d6d3d1", chip: "#78716c" }
|
|
20
|
+
];
|
|
21
|
+
const color = computed(() => GROUP_COLORS[props.data.group.color ?? 4] ?? GROUP_COLORS[4]);
|
|
22
|
+
function loc(v) {
|
|
23
|
+
if (!v) return "";
|
|
24
|
+
return typeof v === "string" ? v : v.en ?? Object.values(v)[0] ?? "";
|
|
25
|
+
}
|
|
26
|
+
const label = computed(() => loc(props.data.group.label) || "Group");
|
|
27
|
+
const collapsed = computed(() => props.data.group.collapsed === true);
|
|
28
|
+
const editable = computed(() => !!props.data.actions);
|
|
29
|
+
const editing = ref(false);
|
|
30
|
+
const draft = ref("");
|
|
31
|
+
const inputEl = ref(null);
|
|
32
|
+
function startRename() {
|
|
33
|
+
if (!editable.value) return;
|
|
34
|
+
draft.value = label.value;
|
|
35
|
+
editing.value = true;
|
|
36
|
+
void nextTick(() => inputEl.value?.focus());
|
|
37
|
+
}
|
|
38
|
+
function commitRename() {
|
|
39
|
+
if (!editing.value) return;
|
|
40
|
+
editing.value = false;
|
|
41
|
+
const next = draft.value.trim();
|
|
42
|
+
if (next && next !== label.value) props.data.actions?.rename(next);
|
|
43
|
+
}
|
|
44
|
+
const hovered = ref(false);
|
|
45
|
+
let hoverTimer = null;
|
|
46
|
+
function onHoverEnter() {
|
|
47
|
+
if (hoverTimer) clearTimeout(hoverTimer);
|
|
48
|
+
hovered.value = true;
|
|
49
|
+
}
|
|
50
|
+
function onHoverLeave() {
|
|
51
|
+
if (hoverTimer) clearTimeout(hoverTimer);
|
|
52
|
+
hoverTimer = setTimeout(() => {
|
|
53
|
+
hovered.value = false;
|
|
54
|
+
}, 250);
|
|
55
|
+
}
|
|
56
|
+
const toolbarVisible = computed(() => editable.value && !editing.value && (hovered.value || !!props.selected));
|
|
57
|
+
const memberCountText = computed(() => `${props.data.memberCount} node${props.data.memberCount === 1 ? "" : "s"}`);
|
|
58
|
+
const flow = useVueFlow();
|
|
59
|
+
const resizing = ref(false);
|
|
60
|
+
const liveW = ref(0);
|
|
61
|
+
const liveH = ref(0);
|
|
62
|
+
let resizeStart = { x: 0, y: 0, w: 0, h: 0 };
|
|
63
|
+
const frameW = computed(() => resizing.value ? liveW.value : props.data.rect.width);
|
|
64
|
+
const frameH = computed(() => resizing.value ? liveH.value : props.data.rect.height);
|
|
65
|
+
function onResizeStart(e) {
|
|
66
|
+
e.stopPropagation();
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
resizing.value = true;
|
|
69
|
+
liveW.value = props.data.rect.width;
|
|
70
|
+
liveH.value = props.data.rect.height;
|
|
71
|
+
resizeStart = { x: e.clientX, y: e.clientY, w: liveW.value, h: liveH.value };
|
|
72
|
+
e.target.setPointerCapture(e.pointerId);
|
|
73
|
+
}
|
|
74
|
+
function onResizeMove(e) {
|
|
75
|
+
if (!resizing.value) return;
|
|
76
|
+
const zoom = flow.viewport.value.zoom || 1;
|
|
77
|
+
liveW.value = Math.max(150, Math.round(resizeStart.w + (e.clientX - resizeStart.x) / zoom));
|
|
78
|
+
liveH.value = Math.max(90, Math.round(resizeStart.h + (e.clientY - resizeStart.y) / zoom));
|
|
79
|
+
}
|
|
80
|
+
function onResizeEnd() {
|
|
81
|
+
if (!resizing.value) return;
|
|
82
|
+
resizing.value = false;
|
|
83
|
+
props.data.actions?.resize({ width: liveW.value, height: liveH.value });
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<template>
|
|
88
|
+
<div class="relative">
|
|
89
|
+
<NodeToolbar :is-visible="toolbarVisible" :position="Position.Top" :offset="8">
|
|
90
|
+
<div
|
|
91
|
+
class="flex items-center gap-1 rounded-lg border border-black/[0.06] bg-white px-1.5 py-1 shadow-md"
|
|
92
|
+
@mouseenter="onHoverEnter"
|
|
93
|
+
@mouseleave="onHoverLeave"
|
|
94
|
+
>
|
|
95
|
+
<button
|
|
96
|
+
v-for="(c, i) in GROUP_COLORS"
|
|
97
|
+
:key="i"
|
|
98
|
+
type="button"
|
|
99
|
+
class="size-4.5 rounded-full border transition hover:scale-110"
|
|
100
|
+
:class="(data.group.color ?? 4) === i ? 'ring-2 ring-black/25 ring-offset-1' : ''"
|
|
101
|
+
:style="{ backgroundColor: c.chip, borderColor: c.border, width: '16px', height: '16px' }"
|
|
102
|
+
@click="data.actions?.setColor(i)"
|
|
103
|
+
/>
|
|
104
|
+
<div class="mx-0.5 h-4 w-px bg-black/10" />
|
|
105
|
+
<button
|
|
106
|
+
type="button"
|
|
107
|
+
class="flex size-6 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
|
108
|
+
:title="collapsed ? 'Expand group' : 'Collapse group'"
|
|
109
|
+
@click="data.actions?.toggleCollapse()"
|
|
110
|
+
>
|
|
111
|
+
<component :is="collapsed ? ChevronsUpDown : ChevronsDownUp" :size="13" />
|
|
112
|
+
</button>
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
class="flex size-6 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
|
116
|
+
title="Ungroup (keep the nodes)"
|
|
117
|
+
@click="data.actions?.ungroup()"
|
|
118
|
+
>
|
|
119
|
+
<Ungroup :size="13" />
|
|
120
|
+
</button>
|
|
121
|
+
<button
|
|
122
|
+
type="button"
|
|
123
|
+
class="flex size-6 items-center justify-center rounded-md text-muted-foreground transition hover:bg-rose-50 hover:text-rose-600"
|
|
124
|
+
title="Remove group frame"
|
|
125
|
+
@click="data.actions?.ungroup()"
|
|
126
|
+
>
|
|
127
|
+
<Trash2 :size="13" />
|
|
128
|
+
</button>
|
|
129
|
+
</div>
|
|
130
|
+
</NodeToolbar>
|
|
131
|
+
|
|
132
|
+
<!-- Collapsed: compact stand-in card with generic edge handles. -->
|
|
133
|
+
<template v-if="collapsed">
|
|
134
|
+
<Handle
|
|
135
|
+
id="__in__top"
|
|
136
|
+
type="target"
|
|
137
|
+
:position="Position.Top"
|
|
138
|
+
class="!size-3 !rounded-full !border-2 !border-white !bg-slate-500 !shadow-sm"
|
|
139
|
+
/>
|
|
140
|
+
<div
|
|
141
|
+
class="w-[220px] rounded-lg border-2 bg-white transition-all duration-150"
|
|
142
|
+
:style="{ borderColor: color.border }"
|
|
143
|
+
:class="selected ? 'shadow-[0_0_0_2px_rgba(59,130,246,0.2)]' : 'shadow-sm hover:shadow-md'"
|
|
144
|
+
@mouseenter="onHoverEnter"
|
|
145
|
+
@mouseleave="onHoverLeave"
|
|
146
|
+
@dblclick.stop="data.actions?.toggleCollapse()"
|
|
147
|
+
>
|
|
148
|
+
<div class="flex items-center gap-2.5 px-3 py-2.5">
|
|
149
|
+
<span class="flex size-8 shrink-0 items-center justify-center rounded-md text-white" :style="{ backgroundColor: color.chip }">
|
|
150
|
+
<ChevronsUpDown :size="15" />
|
|
151
|
+
</span>
|
|
152
|
+
<div class="min-w-0 flex-1">
|
|
153
|
+
<div class="truncate text-sm font-semibold leading-tight text-foreground">{{ label }}</div>
|
|
154
|
+
<div class="mt-0.5 text-sm text-muted-foreground">{{ memberCountText }}</div>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
<Handle
|
|
159
|
+
id="default__bottom"
|
|
160
|
+
type="source"
|
|
161
|
+
:position="Position.Bottom"
|
|
162
|
+
class="!size-3 !rounded-full !border-2 !border-white !bg-slate-500 !shadow-sm"
|
|
163
|
+
/>
|
|
164
|
+
</template>
|
|
165
|
+
|
|
166
|
+
<!-- Expanded: the frame behind the members. -->
|
|
167
|
+
<div
|
|
168
|
+
v-else
|
|
169
|
+
class="pointer-events-none relative rounded-xl border-2 border-dashed transition-colors"
|
|
170
|
+
:class="selected ? 'shadow-[0_0_0_2px_rgba(59,130,246,0.15)]' : ''"
|
|
171
|
+
:style="{
|
|
172
|
+
width: `${frameW}px`,
|
|
173
|
+
height: `${frameH}px`,
|
|
174
|
+
backgroundColor: color.bg,
|
|
175
|
+
borderColor: color.border
|
|
176
|
+
}"
|
|
177
|
+
>
|
|
178
|
+
<div
|
|
179
|
+
class="pointer-events-auto flex cursor-grab items-center gap-1.5 px-3 pt-1.5 active:cursor-grabbing"
|
|
180
|
+
@mouseenter="onHoverEnter"
|
|
181
|
+
@mouseleave="onHoverLeave"
|
|
182
|
+
>
|
|
183
|
+
<input
|
|
184
|
+
v-if="editing"
|
|
185
|
+
ref="inputEl"
|
|
186
|
+
v-model="draft"
|
|
187
|
+
class="nodrag w-40 rounded border border-black/[0.1] bg-white px-1 py-0.5 text-sm font-semibold focus:outline-none focus:ring-2 focus:ring-primary/40"
|
|
188
|
+
@blur="commitRename"
|
|
189
|
+
@keydown.enter.prevent="commitRename"
|
|
190
|
+
@keydown.stop
|
|
191
|
+
@mousedown.stop
|
|
192
|
+
>
|
|
193
|
+
<span
|
|
194
|
+
v-else
|
|
195
|
+
class="select-none text-sm font-semibold"
|
|
196
|
+
:style="{ color: color.chip }"
|
|
197
|
+
@dblclick.stop="startRename"
|
|
198
|
+
>
|
|
199
|
+
{{ label }}
|
|
200
|
+
</span>
|
|
201
|
+
<span class="select-none text-xs text-muted-foreground">· {{ memberCountText }}</span>
|
|
202
|
+
</div>
|
|
203
|
+
|
|
204
|
+
<!-- Bottom-right resize handle (editable frames only). -->
|
|
205
|
+
<div
|
|
206
|
+
v-if="editable"
|
|
207
|
+
class="nodrag pointer-events-auto absolute bottom-0 right-0 flex size-5 cursor-se-resize items-end justify-end p-1"
|
|
208
|
+
:style="{ color: color.chip }"
|
|
209
|
+
title="Resize group"
|
|
210
|
+
@pointerdown="onResizeStart"
|
|
211
|
+
@pointermove="onResizeMove"
|
|
212
|
+
@pointerup="onResizeEnd"
|
|
213
|
+
@pointercancel="onResizeEnd"
|
|
214
|
+
>
|
|
215
|
+
<svg viewBox="0 0 8 8" class="size-2.5" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round">
|
|
216
|
+
<path d="M7 1 1 7" />
|
|
217
|
+
<path d="M7 4.5 4.5 7" />
|
|
218
|
+
</svg>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
</template>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { WorkflowGroup } from '../../types/integrations.js';
|
|
2
|
+
interface GroupNodeData {
|
|
3
|
+
group: WorkflowGroup;
|
|
4
|
+
/** Derived frame size (expanded mode). */
|
|
5
|
+
rect: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
memberCount: number;
|
|
10
|
+
/** Absent in read-only previews — no toolbar, no editing. */
|
|
11
|
+
actions?: {
|
|
12
|
+
rename: (label: string) => void;
|
|
13
|
+
setColor: (i: number) => void;
|
|
14
|
+
toggleCollapse: () => void;
|
|
15
|
+
ungroup: () => void;
|
|
16
|
+
resize: (size: {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
}) => void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
type __VLS_Props = {
|
|
23
|
+
id: string;
|
|
24
|
+
data: GroupNodeData;
|
|
25
|
+
selected?: boolean;
|
|
26
|
+
};
|
|
27
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, any, string, import("vue").PublicProps, any, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConfigField } from '../../types/integrations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
slug: string;
|
|
4
|
+
version: string;
|
|
5
|
+
field: ConfigField;
|
|
6
|
+
config: Record<string, unknown>;
|
|
7
|
+
modelValue: unknown;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
"update:modelValue": (value: unknown) => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
"onUpdate:modelValue"?: ((value: unknown) => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, ref } from "vue";
|
|
3
|
+
import { ChevronDown } from "lucide-vue-next";
|
|
4
|
+
import { Input } from "@revenexx/studio";
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
slug: { type: String, required: true },
|
|
7
|
+
version: { type: String, required: true },
|
|
8
|
+
field: { type: Object, required: true },
|
|
9
|
+
config: { type: Object, required: true },
|
|
10
|
+
modelValue: { type: null, required: true }
|
|
11
|
+
});
|
|
12
|
+
const emit = defineEmits(["update:modelValue"]);
|
|
13
|
+
function labelText(v) {
|
|
14
|
+
if (!v) return "";
|
|
15
|
+
return typeof v === "string" ? v : v.en ?? Object.values(v)[0] ?? "";
|
|
16
|
+
}
|
|
17
|
+
const search = ref("");
|
|
18
|
+
const focused = ref(false);
|
|
19
|
+
const q = useNodeConfigResolve({
|
|
20
|
+
slug: () => props.slug,
|
|
21
|
+
version: () => props.version,
|
|
22
|
+
target: () => props.field.key,
|
|
23
|
+
config: () => props.config,
|
|
24
|
+
dependsOn: () => props.field.dependsOn,
|
|
25
|
+
search: () => focused.value ? search.value : ""
|
|
26
|
+
});
|
|
27
|
+
const options = computed(() => q.data.value?.options ?? []);
|
|
28
|
+
const isMulti = computed(() => props.field.type === "multiselect");
|
|
29
|
+
const disabledControlClass = "flex h-8 items-center rounded-md border border-black/[0.08] bg-white px-2 text-sm text-muted-foreground opacity-50";
|
|
30
|
+
const currentValue = computed(() => String(props.modelValue ?? ""));
|
|
31
|
+
const currentKnown = computed(
|
|
32
|
+
() => options.value.some((o) => String(o.value) === currentValue.value)
|
|
33
|
+
);
|
|
34
|
+
const currentLabel = computed(() => {
|
|
35
|
+
const hit = options.value.find((o) => String(o.value) === currentValue.value);
|
|
36
|
+
return hit ? labelText(hit.label) || String(hit.value) : currentValue.value;
|
|
37
|
+
});
|
|
38
|
+
const listOpen = computed(() => focused.value && !q.gated.value);
|
|
39
|
+
const visibleOptions = computed(() => {
|
|
40
|
+
const term = search.value.trim().toLowerCase();
|
|
41
|
+
if (!focused.value || !term) return options.value;
|
|
42
|
+
const hits = options.value.filter(
|
|
43
|
+
(o) => (labelText(o.label) || "").toLowerCase().includes(term) || String(o.value).toLowerCase().includes(term)
|
|
44
|
+
);
|
|
45
|
+
return hits.length ? hits : options.value;
|
|
46
|
+
});
|
|
47
|
+
function onComboFocus() {
|
|
48
|
+
search.value = "";
|
|
49
|
+
focused.value = true;
|
|
50
|
+
}
|
|
51
|
+
function onComboBlur() {
|
|
52
|
+
focused.value = false;
|
|
53
|
+
}
|
|
54
|
+
function pick(value) {
|
|
55
|
+
emit("update:modelValue", value);
|
|
56
|
+
search.value = "";
|
|
57
|
+
focused.value = false;
|
|
58
|
+
}
|
|
59
|
+
const selectedArray = computed(
|
|
60
|
+
() => Array.isArray(props.modelValue) ? props.modelValue.map(String) : []
|
|
61
|
+
);
|
|
62
|
+
const knownValues = computed(() => new Set(options.value.map((o) => String(o.value))));
|
|
63
|
+
const missingValues = computed(() => selectedArray.value.filter((v) => !knownValues.value.has(v)));
|
|
64
|
+
const multiFilter = ref("");
|
|
65
|
+
const visibleMultiOptions = computed(() => {
|
|
66
|
+
const f = multiFilter.value.trim().toLowerCase();
|
|
67
|
+
if (!f) return options.value;
|
|
68
|
+
return options.value.filter(
|
|
69
|
+
(o) => (labelText(o.label) || String(o.value)).toLowerCase().includes(f) || String(o.value).toLowerCase().includes(f)
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
function toggleMulti(optValue) {
|
|
73
|
+
const arr = selectedArray.value;
|
|
74
|
+
const has = arr.includes(optValue);
|
|
75
|
+
emit("update:modelValue", has ? arr.filter((v) => v !== optValue) : [...arr, optValue]);
|
|
76
|
+
}
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<div>
|
|
81
|
+
<!-- gated: required dependencies still unset -->
|
|
82
|
+
<template v-if="q.gated.value">
|
|
83
|
+
<div :class="disabledControlClass">—</div>
|
|
84
|
+
<p class="mt-1 text-sm text-amber-600">Set {{ q.unsatisfied.value.join(", ") }} first</p>
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<!-- first load: no data yet -->
|
|
88
|
+
<template v-else-if="q.isFetching.value && options.length === 0">
|
|
89
|
+
<div :class="disabledControlClass">resolving options…</div>
|
|
90
|
+
</template>
|
|
91
|
+
|
|
92
|
+
<!-- error: build/runtime/etc -->
|
|
93
|
+
<template v-else-if="q.error.value">
|
|
94
|
+
<div :class="disabledControlClass">—</div>
|
|
95
|
+
<div class="mt-1 flex items-center gap-2 text-sm text-amber-600">
|
|
96
|
+
<span>{{ q.error.value.kind === "building" ? "Node bundle still building." : q.error.value.message }}</span>
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
class="rounded border border-black/[0.08] px-1.5 py-0.5 text-mono text-muted-foreground transition hover:text-foreground"
|
|
100
|
+
@click="q.refetch()"
|
|
101
|
+
>
|
|
102
|
+
RETRY
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
|
|
107
|
+
<!-- multiselect — pill toggles with a client-side filter for long lists -->
|
|
108
|
+
<template v-else-if="isMulti">
|
|
109
|
+
<Input
|
|
110
|
+
v-if="options.length > 10"
|
|
111
|
+
v-model="multiFilter"
|
|
112
|
+
placeholder="Filter options"
|
|
113
|
+
class="mb-1.5 h-7 bg-white text-sm"
|
|
114
|
+
/>
|
|
115
|
+
<div class="flex flex-wrap gap-1">
|
|
116
|
+
<span v-if="visibleMultiOptions.length === 0" class="text-sm text-muted-foreground">
|
|
117
|
+
{{ options.length === 0 ? "no options available" : "no options match the filter" }}
|
|
118
|
+
</span>
|
|
119
|
+
<button
|
|
120
|
+
v-for="opt in visibleMultiOptions"
|
|
121
|
+
:key="String(opt.value)"
|
|
122
|
+
type="button"
|
|
123
|
+
:disabled="q.isFetching.value"
|
|
124
|
+
class="rounded-md border border-black/[0.08] px-1.5 py-0.5 text-sm transition disabled:cursor-wait disabled:opacity-60"
|
|
125
|
+
:class="selectedArray.includes(String(opt.value)) ? 'bg-emerald-500/15 text-emerald-700 border-emerald-500/30' : 'bg-white text-muted-foreground hover:text-foreground'"
|
|
126
|
+
@click="toggleMulti(String(opt.value))"
|
|
127
|
+
>
|
|
128
|
+
{{ labelText(opt.label) || String(opt.value) }}
|
|
129
|
+
</button>
|
|
130
|
+
<!-- stored values no longer offered — shown read-only so they stay visible -->
|
|
131
|
+
<span
|
|
132
|
+
v-for="m in missingValues"
|
|
133
|
+
:key="m"
|
|
134
|
+
class="rounded-md border border-black/[0.08] bg-white px-1.5 py-0.5 text-sm text-muted-foreground opacity-60"
|
|
135
|
+
>
|
|
136
|
+
{{ m }} (not in list)
|
|
137
|
+
</span>
|
|
138
|
+
</div>
|
|
139
|
+
<p v-if="q.isFetching.value && q.hasData.value" class="mt-1 text-sm text-muted-foreground">reloading…</p>
|
|
140
|
+
</template>
|
|
141
|
+
|
|
142
|
+
<!-- single select: searchable combobox; typing re-resolves with the term -->
|
|
143
|
+
<template v-else>
|
|
144
|
+
<div class="relative">
|
|
145
|
+
<Input
|
|
146
|
+
:model-value="focused ? search : currentLabel"
|
|
147
|
+
:placeholder="labelText(field.placeholder) || 'Pick one'"
|
|
148
|
+
class="h-8 bg-white pr-7 text-sm"
|
|
149
|
+
@update:model-value="(v) => {
|
|
150
|
+
search = String(v);
|
|
151
|
+
}"
|
|
152
|
+
@focus="onComboFocus"
|
|
153
|
+
@blur="onComboBlur"
|
|
154
|
+
/>
|
|
155
|
+
<ChevronDown :size="14" class="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground" />
|
|
156
|
+
<div
|
|
157
|
+
v-if="listOpen"
|
|
158
|
+
class="absolute left-0 right-0 top-full z-30 mt-1 max-h-56 overflow-y-auto rounded-md border border-black/[0.08] bg-white py-1 shadow-md"
|
|
159
|
+
>
|
|
160
|
+
<div v-if="q.isFetching.value" class="px-2.5 py-1.5 text-sm text-muted-foreground">
|
|
161
|
+
{{ search ? "searching\u2026" : "resolving options\u2026" }}
|
|
162
|
+
</div>
|
|
163
|
+
<button
|
|
164
|
+
v-for="opt in visibleOptions"
|
|
165
|
+
:key="String(opt.value)"
|
|
166
|
+
type="button"
|
|
167
|
+
class="flex w-full items-center px-2.5 py-1.5 text-left text-sm hover:bg-muted/50"
|
|
168
|
+
:class="String(opt.value) === currentValue ? 'bg-emerald-500/10 text-emerald-800' : ''"
|
|
169
|
+
@mousedown.prevent="pick(String(opt.value))"
|
|
170
|
+
>
|
|
171
|
+
<span class="min-w-0 truncate">{{ labelText(opt.label) || String(opt.value) }}</span>
|
|
172
|
+
</button>
|
|
173
|
+
<div v-if="!q.isFetching.value && visibleOptions.length === 0" class="px-2.5 py-1.5 text-sm text-muted-foreground">
|
|
174
|
+
{{ search ? 'nothing matches "' + search + '"' : "no options available" }}
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
<p v-if="currentValue !== '' && !currentKnown" class="mt-1 text-sm text-amber-600">
|
|
179
|
+
current value not in resolved options
|
|
180
|
+
</p>
|
|
181
|
+
<p v-if="q.isFetching.value && q.hasData.value && !focused" class="mt-1 text-sm text-muted-foreground">reloading…</p>
|
|
182
|
+
</template>
|
|
183
|
+
</div>
|
|
184
|
+
</template>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConfigField } from '../../types/integrations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
slug: string;
|
|
4
|
+
version: string;
|
|
5
|
+
field: ConfigField;
|
|
6
|
+
config: Record<string, unknown>;
|
|
7
|
+
modelValue: unknown;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
"update:modelValue": (value: unknown) => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
"onUpdate:modelValue"?: ((value: unknown) => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ConfigField } from '../../types/integrations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
slug: string;
|
|
4
|
+
version: string;
|
|
5
|
+
field: ConfigField;
|
|
6
|
+
config: Record<string, unknown>;
|
|
7
|
+
staticKeys: string[];
|
|
8
|
+
secretKeys: string[];
|
|
9
|
+
depth?: number;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
|
+
set: (key: string, value: unknown) => any;
|
|
13
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onSet?: ((key: string, value: unknown) => any) | undefined;
|
|
15
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { Button } from "@revenexx/studio";
|
|
4
|
+
import { IntegrationsApiError } from "../../composables/integrationsApi";
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
slug: { type: String, required: true },
|
|
7
|
+
version: { type: String, required: true },
|
|
8
|
+
field: { type: Object, required: true },
|
|
9
|
+
config: { type: Object, required: true },
|
|
10
|
+
staticKeys: { type: Array, required: true },
|
|
11
|
+
secretKeys: { type: Array, required: true },
|
|
12
|
+
depth: { type: Number, required: false }
|
|
13
|
+
});
|
|
14
|
+
const emit = defineEmits(["set"]);
|
|
15
|
+
void IntegrationsApiError;
|
|
16
|
+
const MAX_DEPTH = 5;
|
|
17
|
+
const q = useNodeConfigResolve({
|
|
18
|
+
slug: () => props.slug,
|
|
19
|
+
version: () => props.version,
|
|
20
|
+
target: () => "*",
|
|
21
|
+
config: () => props.config,
|
|
22
|
+
dependsOn: () => props.field.dependsOn
|
|
23
|
+
});
|
|
24
|
+
const resolvedFields = computed(() => q.data.value?.fields ?? []);
|
|
25
|
+
function labelText(v) {
|
|
26
|
+
if (!v) return "";
|
|
27
|
+
return typeof v === "string" ? v : v.en ?? Object.values(v)[0] ?? "";
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<div>
|
|
33
|
+
<!-- gated: required dependencies still unset -->
|
|
34
|
+
<p v-if="q.gated.value" class="text-sm text-amber-600">
|
|
35
|
+
Set {{ q.unsatisfied.value.join(", ") }} first
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
<!-- first load: no fields yet -->
|
|
39
|
+
<p v-else-if="q.isFetching.value && !resolvedFields.length" class="text-sm text-muted-foreground">
|
|
40
|
+
Resolving fields…
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<!-- error: build/runtime/etc -->
|
|
44
|
+
<div v-else-if="q.error.value" class="flex items-center gap-2 text-sm text-amber-600">
|
|
45
|
+
<span>{{ q.error.value.kind === "building" ? "Node bundle still building." : q.error.value.message }}</span>
|
|
46
|
+
<Button
|
|
47
|
+
type="button"
|
|
48
|
+
variant="outline"
|
|
49
|
+
size="sm"
|
|
50
|
+
class="h-6 px-1.5 text-mono text-muted-foreground"
|
|
51
|
+
@click="q.refetch()"
|
|
52
|
+
>
|
|
53
|
+
RETRY
|
|
54
|
+
</Button>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- empty: resolved but no fields -->
|
|
58
|
+
<p v-else-if="!resolvedFields.length" class="text-sm text-muted-foreground">
|
|
59
|
+
No fields resolved.
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
<!-- fieldset: the resolved child fields, rendered into the flat node config -->
|
|
63
|
+
<fieldset
|
|
64
|
+
v-else
|
|
65
|
+
:disabled="q.isFetching.value"
|
|
66
|
+
:class="{ 'opacity-60': q.isFetching.value }"
|
|
67
|
+
class="space-y-3 rounded-md border border-black/[0.08] bg-muted/10 p-3 m-0"
|
|
68
|
+
>
|
|
69
|
+
<legend class="px-1 text-mono text-muted-foreground">
|
|
70
|
+
{{ labelText(field.label) }}
|
|
71
|
+
</legend>
|
|
72
|
+
<template v-for="f in resolvedFields" :key="f.key">
|
|
73
|
+
<!-- collision guard: a resolved key that shadows a static config field is skipped -->
|
|
74
|
+
<p v-if="staticKeys.includes(f.key)" class="text-sm text-amber-600">
|
|
75
|
+
resolved field '{{ f.key }}' collides with a static config field — skipped
|
|
76
|
+
</p>
|
|
77
|
+
|
|
78
|
+
<!-- depth cap: don't expand nested dynamic-schema past MAX_DEPTH -->
|
|
79
|
+
<p v-else-if="f.type === 'dynamic-schema' && (depth ?? 0) >= MAX_DEPTH" class="text-sm text-muted-foreground">
|
|
80
|
+
nested dynamic-schema is not expanded further
|
|
81
|
+
</p>
|
|
82
|
+
|
|
83
|
+
<!-- a resolved field, rendered exactly like a static node config field -->
|
|
84
|
+
<IntegrationsNodeConfigField
|
|
85
|
+
v-else
|
|
86
|
+
:field="f"
|
|
87
|
+
:config="config"
|
|
88
|
+
:slug="slug"
|
|
89
|
+
:version="version"
|
|
90
|
+
:secret-keys="secretKeys"
|
|
91
|
+
:static-keys="staticKeys"
|
|
92
|
+
:depth="(depth ?? 0) + 1"
|
|
93
|
+
@set="(k, v) => emit('set', k, v)"
|
|
94
|
+
/>
|
|
95
|
+
</template>
|
|
96
|
+
|
|
97
|
+
<p v-if="q.isFetching.value && q.hasData.value" class="text-sm text-muted-foreground">
|
|
98
|
+
reloading fields…
|
|
99
|
+
</p>
|
|
100
|
+
</fieldset>
|
|
101
|
+
</div>
|
|
102
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ConfigField } from '../../types/integrations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
slug: string;
|
|
4
|
+
version: string;
|
|
5
|
+
field: ConfigField;
|
|
6
|
+
config: Record<string, unknown>;
|
|
7
|
+
staticKeys: string[];
|
|
8
|
+
secretKeys: string[];
|
|
9
|
+
depth?: number;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
|
+
set: (key: string, value: unknown) => any;
|
|
13
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onSet?: ((key: string, value: unknown) => any) | undefined;
|
|
15
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ConfigField, WorkflowVariable } from '../../types/integrations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
field: ConfigField;
|
|
4
|
+
config: Record<string, unknown>;
|
|
5
|
+
slug: string;
|
|
6
|
+
version: string;
|
|
7
|
+
secretKeys: string[];
|
|
8
|
+
staticKeys?: string[];
|
|
9
|
+
depth?: number;
|
|
10
|
+
variables?: Record<string, WorkflowVariable>;
|
|
11
|
+
upstreamOutputs?: Array<{
|
|
12
|
+
nodeId: string;
|
|
13
|
+
nodeName?: string;
|
|
14
|
+
output: string;
|
|
15
|
+
fields?: string[];
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
19
|
+
set: (key: string, value: unknown) => any;
|
|
20
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
21
|
+
onSet?: ((key: string, value: unknown) => any) | undefined;
|
|
22
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
23
|
+
export default _default;
|