@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.
Files changed (180) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/Integrations/CredentialCreateDialog.d.vue.ts +13 -0
  3. package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +279 -0
  4. package/dist/runtime/components/Integrations/CredentialCreateDialog.vue.d.ts +13 -0
  5. package/dist/runtime/components/Integrations/CredentialDetailDialog.d.vue.ts +20 -0
  6. package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +342 -0
  7. package/dist/runtime/components/Integrations/CredentialDetailDialog.vue.d.ts +20 -0
  8. package/dist/runtime/components/Integrations/CredentialLogo.d.vue.ts +14 -0
  9. package/dist/runtime/components/Integrations/CredentialLogo.vue +37 -0
  10. package/dist/runtime/components/Integrations/CredentialLogo.vue.d.ts +14 -0
  11. package/dist/runtime/components/Integrations/CredentialRevenexxSource.d.vue.ts +12 -0
  12. package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +364 -0
  13. package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue.d.ts +12 -0
  14. package/dist/runtime/components/Integrations/CredentialTypePicker.d.vue.ts +15 -0
  15. package/dist/runtime/components/Integrations/CredentialTypePicker.vue +71 -0
  16. package/dist/runtime/components/Integrations/CredentialTypePicker.vue.d.ts +15 -0
  17. package/dist/runtime/components/Integrations/DeadLettersPanel.d.vue.ts +5 -0
  18. package/dist/runtime/components/Integrations/DeadLettersPanel.vue +151 -0
  19. package/dist/runtime/components/Integrations/DeadLettersPanel.vue.d.ts +5 -0
  20. package/dist/runtime/components/Integrations/EditorTip.d.vue.ts +17 -0
  21. package/dist/runtime/components/Integrations/EditorTip.vue +46 -0
  22. package/dist/runtime/components/Integrations/EditorTip.vue.d.ts +17 -0
  23. package/dist/runtime/components/Integrations/EventTypeCombobox.d.vue.ts +9 -0
  24. package/dist/runtime/components/Integrations/EventTypeCombobox.vue +64 -0
  25. package/dist/runtime/components/Integrations/EventTypeCombobox.vue.d.ts +9 -0
  26. package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +19 -0
  27. package/dist/runtime/components/Integrations/ExpressionInput.vue +236 -0
  28. package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +19 -0
  29. package/dist/runtime/components/Integrations/GroupFrameView.d.vue.ts +28 -0
  30. package/dist/runtime/components/Integrations/GroupFrameView.vue +222 -0
  31. package/dist/runtime/components/Integrations/GroupFrameView.vue.d.ts +28 -0
  32. package/dist/runtime/components/Integrations/NodeConfigDynamicField.d.vue.ts +14 -0
  33. package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue +184 -0
  34. package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue.d.ts +14 -0
  35. package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.d.vue.ts +16 -0
  36. package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue +102 -0
  37. package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue.d.ts +16 -0
  38. package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +23 -0
  39. package/dist/runtime/components/Integrations/NodeConfigField.vue +587 -0
  40. package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +23 -0
  41. package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.d.vue.ts +14 -0
  42. package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue +80 -0
  43. package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue.d.ts +14 -0
  44. package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +22 -3
  45. package/dist/runtime/components/Integrations/NodeInspector.vue +1074 -294
  46. package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +22 -3
  47. package/dist/runtime/components/Integrations/NodeLogo.d.vue.ts +9 -0
  48. package/dist/runtime/components/Integrations/NodeLogo.vue +38 -0
  49. package/dist/runtime/components/Integrations/NodeLogo.vue.d.ts +9 -0
  50. package/dist/runtime/components/Integrations/NodePalette.d.vue.ts +22 -1
  51. package/dist/runtime/components/Integrations/NodePalette.vue +411 -90
  52. package/dist/runtime/components/Integrations/NodePalette.vue.d.ts +22 -1
  53. package/dist/runtime/components/Integrations/QueryBuilder.d.vue.ts +9 -0
  54. package/dist/runtime/components/Integrations/QueryBuilder.vue +239 -0
  55. package/dist/runtime/components/Integrations/QueryBuilder.vue.d.ts +9 -0
  56. package/dist/runtime/components/Integrations/{RunDetailDialog.d.vue.ts → RunActionsMenu.d.vue.ts} +3 -4
  57. package/dist/runtime/components/Integrations/RunActionsMenu.vue +86 -0
  58. package/dist/runtime/components/Integrations/{RunDetailDialog.vue.d.ts → RunActionsMenu.vue.d.ts} +3 -4
  59. package/dist/runtime/components/Integrations/RunDetailPanel.d.vue.ts +14 -0
  60. package/dist/runtime/components/Integrations/RunDetailPanel.vue +777 -0
  61. package/dist/runtime/components/Integrations/RunDetailPanel.vue.d.ts +14 -0
  62. package/dist/runtime/components/Integrations/RunPayloadInput.d.vue.ts +13 -0
  63. package/dist/runtime/components/Integrations/RunPayloadInput.vue +175 -0
  64. package/dist/runtime/components/Integrations/RunPayloadInput.vue.d.ts +13 -0
  65. package/dist/runtime/components/Integrations/RunResponseModal.d.vue.ts +27 -0
  66. package/dist/runtime/components/Integrations/RunResponseModal.vue +84 -0
  67. package/dist/runtime/components/Integrations/RunResponseModal.vue.d.ts +27 -0
  68. package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +21 -0
  69. package/dist/runtime/components/Integrations/RunsTable.vue +114 -0
  70. package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +21 -0
  71. package/dist/runtime/components/Integrations/SftpAccountImportDialog.d.vue.ts +11 -0
  72. package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +91 -0
  73. package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue.d.ts +11 -0
  74. package/dist/runtime/components/Integrations/Sidebar.vue +1 -0
  75. package/dist/runtime/components/Integrations/StickyNoteView.d.vue.ts +28 -0
  76. package/dist/runtime/components/Integrations/StickyNoteView.vue +208 -0
  77. package/dist/runtime/components/Integrations/StickyNoteView.vue.d.ts +28 -0
  78. package/dist/runtime/components/Integrations/TemplateFlowPreview.d.vue.ts +29 -0
  79. package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +201 -0
  80. package/dist/runtime/components/Integrations/TemplateFlowPreview.vue.d.ts +29 -0
  81. package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +32 -0
  82. package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +138 -0
  83. package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +32 -0
  84. package/dist/runtime/components/Integrations/WorkflowCreateDialog.d.vue.ts +9 -0
  85. package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +322 -0
  86. package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue.d.ts +9 -0
  87. package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.d.vue.ts +18 -0
  88. package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +63 -0
  89. package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue.d.ts +18 -0
  90. package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +12 -1
  91. package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +68 -6
  92. package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +12 -1
  93. package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +8 -1
  94. package/dist/runtime/components/Integrations/WorkflowEditor.vue +1424 -144
  95. package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +8 -1
  96. package/dist/runtime/components/Integrations/WorkflowHistoryPanel.d.vue.ts +12 -0
  97. package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +417 -0
  98. package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue.d.ts +12 -0
  99. package/dist/runtime/components/Integrations/WorkflowIconPicker.d.vue.ts +10 -0
  100. package/dist/runtime/components/Integrations/WorkflowIconPicker.vue +89 -0
  101. package/dist/runtime/components/Integrations/WorkflowIconPicker.vue.d.ts +10 -0
  102. package/dist/runtime/components/Integrations/WorkflowIconView.d.vue.ts +10 -0
  103. package/dist/runtime/components/Integrations/WorkflowIconView.vue +35 -0
  104. package/dist/runtime/components/Integrations/WorkflowIconView.vue.d.ts +10 -0
  105. package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +5 -1
  106. package/dist/runtime/components/Integrations/WorkflowNodeView.vue +114 -84
  107. package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +5 -1
  108. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.d.vue.ts +12 -0
  109. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +654 -0
  110. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue.d.ts +12 -0
  111. package/dist/runtime/components/Integrations/WorkflowSettingsDialog.d.vue.ts +36 -0
  112. package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue +136 -0
  113. package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue.d.ts +36 -0
  114. package/dist/runtime/components/Integrations/WorkflowTagsInput.d.vue.ts +14 -0
  115. package/dist/runtime/components/Integrations/WorkflowTagsInput.vue +63 -0
  116. package/dist/runtime/components/Integrations/WorkflowTagsInput.vue.d.ts +14 -0
  117. package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +35 -15
  118. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.d.vue.ts +13 -0
  119. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +265 -0
  120. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue.d.ts +13 -0
  121. package/dist/runtime/components/Integrations/WorkflowsTable.d.vue.ts +4 -1
  122. package/dist/runtime/components/Integrations/WorkflowsTable.vue +122 -39
  123. package/dist/runtime/components/Integrations/WorkflowsTable.vue.d.ts +4 -1
  124. package/dist/runtime/components/Integrations/workflowLayout.d.ts +5 -0
  125. package/dist/runtime/components/Integrations/workflowLayout.js +5 -3
  126. package/dist/runtime/composables/integrationsApi.d.ts +6 -2
  127. package/dist/runtime/composables/integrationsApi.js +5 -4
  128. package/dist/runtime/composables/useCanvasShortcuts.d.ts +37 -0
  129. package/dist/runtime/composables/useCanvasShortcuts.js +62 -0
  130. package/dist/runtime/composables/useIntegrationsDeadLetters.d.ts +22 -0
  131. package/dist/runtime/composables/useIntegrationsDeadLetters.js +50 -0
  132. package/dist/runtime/composables/useIntegrationsNodes.d.ts +4 -0
  133. package/dist/runtime/composables/useIntegrationsNodes.js +6 -3
  134. package/dist/runtime/composables/useIntegrationsRevisions.d.ts +40 -0
  135. package/dist/runtime/composables/useIntegrationsRevisions.js +51 -0
  136. package/dist/runtime/composables/useIntegrationsRuns.d.ts +21 -1
  137. package/dist/runtime/composables/useIntegrationsRuns.js +92 -4
  138. package/dist/runtime/composables/useIntegrationsTemplates.d.ts +1 -0
  139. package/dist/runtime/composables/useIntegrationsTemplates.js +32 -4
  140. package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +1 -0
  141. package/dist/runtime/composables/useIntegrationsWorkflows.js +57 -1
  142. package/dist/runtime/composables/useMiniMapLayout.d.ts +34 -0
  143. package/dist/runtime/composables/useMiniMapLayout.js +119 -0
  144. package/dist/runtime/composables/useNodeConfigResolve.d.ts +43 -0
  145. package/dist/runtime/composables/useNodeConfigResolve.js +123 -0
  146. package/dist/runtime/composables/useNodeDrag.d.ts +22 -0
  147. package/dist/runtime/composables/useNodeDrag.js +10 -0
  148. package/dist/runtime/composables/usePaletteLayout.d.ts +41 -0
  149. package/dist/runtime/composables/usePaletteLayout.js +113 -0
  150. package/dist/runtime/data/expressionEditor.d.ts +22 -0
  151. package/dist/runtime/data/expressionEditor.js +40 -0
  152. package/dist/runtime/data/integrationNodeCatalog.js +8 -8
  153. package/dist/runtime/data/nodeInputData.d.ts +37 -0
  154. package/dist/runtime/data/nodeInputData.js +62 -0
  155. package/dist/runtime/data/nodeRunData.d.ts +56 -0
  156. package/dist/runtime/data/nodeRunData.js +91 -0
  157. package/dist/runtime/data/payloadForm.d.ts +44 -0
  158. package/dist/runtime/data/payloadForm.js +126 -0
  159. package/dist/runtime/data/workflowIconCatalog.d.ts +34 -0
  160. package/dist/runtime/data/workflowIconCatalog.js +116 -0
  161. package/dist/runtime/pages/integrations/audit.vue +25 -35
  162. package/dist/runtime/pages/integrations/credentials.vue +117 -122
  163. package/dist/runtime/pages/integrations/index.vue +133 -36
  164. package/dist/runtime/pages/integrations/runs.vue +125 -75
  165. package/dist/runtime/pages/integrations/schedules.vue +5 -16
  166. package/dist/runtime/pages/integrations/secrets.vue +1 -3
  167. package/dist/runtime/pages/integrations/workflows/[id].vue +599 -194
  168. package/dist/runtime/pages/integrations/workflows/index.vue +10 -8
  169. package/dist/runtime/types/integrations.d.ts +190 -4
  170. package/dist/runtime/utils/credentialState.d.ts +28 -0
  171. package/dist/runtime/utils/credentialState.js +29 -0
  172. package/dist/runtime/utils/localize.d.ts +3 -1
  173. package/dist/runtime/utils/localize.js +1 -2
  174. package/dist/runtime/utils/statusStyle.d.ts +6 -0
  175. package/dist/runtime/utils/statusStyle.js +15 -0
  176. package/package.json +12 -2
  177. package/dist/runtime/components/Integrations/RunDetailDialog.vue +0 -169
  178. package/dist/runtime/pages/integrations/workflows/new.d.vue.ts +0 -2
  179. package/dist/runtime/pages/integrations/workflows/new.vue +0 -153
  180. package/dist/runtime/pages/integrations/workflows/new.vue.d.ts +0 -2
@@ -0,0 +1,14 @@
1
+ import type { WorkflowRun } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ run: WorkflowRun;
4
+ /** Which surface renders: the overview or the steps+history timeline. */
5
+ view?: 'details' | 'timeline';
6
+ };
7
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ changed: () => any;
9
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ onChanged?: (() => any) | undefined;
11
+ }>, {
12
+ view: "details" | "timeline";
13
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import type { WorkflowBlob } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ blob: Pick<WorkflowBlob, 'nodes'>;
4
+ };
5
+ type __VLS_PublicProps = __VLS_Props & {
6
+ modelValue?: string;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (value: string) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,175 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ import { Paperclip, TrashBinMinimalistic as Trash2 } from "#solar-icons";
4
+ import { Input, Switch, Textarea } from "@revenexx/studio";
5
+ import { buildPayload, payloadFieldsFromBlob, splitPayload } from "../../data/payloadForm";
6
+ const props = defineProps({
7
+ blob: { type: Object, required: true }
8
+ });
9
+ const model = defineModel({ type: String, ...{ default: "{}" } });
10
+ const fields = computed(() => payloadFieldsFromBlob(props.blob));
11
+ const textValues = ref({});
12
+ const files = ref({});
13
+ const extras = ref({});
14
+ const parseNote = ref(null);
15
+ const expert = ref(fields.value.length === 0);
16
+ function parseModel() {
17
+ try {
18
+ const parsed = JSON.parse(model.value || "{}");
19
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+ function hydrateForm() {
25
+ const payload = parseModel();
26
+ if (payload === null) return false;
27
+ const split = splitPayload(fields.value, payload);
28
+ textValues.value = split.textValues;
29
+ files.value = split.files;
30
+ extras.value = split.extras;
31
+ return true;
32
+ }
33
+ function serialize() {
34
+ model.value = JSON.stringify(buildPayload(fields.value, textValues.value, files.value, extras.value), null, 2);
35
+ }
36
+ hydrateForm();
37
+ watch([textValues, files], () => {
38
+ if (!expert.value) serialize();
39
+ }, { deep: true });
40
+ function toggleExpert(on) {
41
+ if (on) {
42
+ serialize();
43
+ expert.value = true;
44
+ parseNote.value = null;
45
+ return;
46
+ }
47
+ if (!hydrateForm()) {
48
+ parseNote.value = "The JSON does not parse \u2014 fix it before switching back to the form.";
49
+ return;
50
+ }
51
+ parseNote.value = null;
52
+ expert.value = false;
53
+ }
54
+ const WARN_BYTES = 25 * 1024 * 1024;
55
+ const dragOver = ref(null);
56
+ function attach(path, file) {
57
+ const reader = new FileReader();
58
+ reader.onload = () => {
59
+ const url = String(reader.result ?? "");
60
+ const data = url.slice(url.indexOf(",") + 1);
61
+ files.value = {
62
+ ...files.value,
63
+ [path]: {
64
+ data,
65
+ filename: file.name,
66
+ contentType: file.type || "application/octet-stream",
67
+ size: file.size
68
+ }
69
+ };
70
+ };
71
+ reader.readAsDataURL(file);
72
+ }
73
+ function onPick(path, ev) {
74
+ const file = ev.target.files?.[0];
75
+ if (file) attach(path, file);
76
+ ev.target.value = "";
77
+ }
78
+ function onDrop(path, ev) {
79
+ dragOver.value = null;
80
+ const file = ev.dataTransfer?.files?.[0];
81
+ if (file) attach(path, file);
82
+ }
83
+ function detach(path) {
84
+ files.value = { ...files.value, [path]: null };
85
+ }
86
+ function prettyBytes(n) {
87
+ if (n < 1024) return `${n} B`;
88
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
89
+ return `${(n / 1024 / 1024).toFixed(1)} MB`;
90
+ }
91
+ </script>
92
+
93
+ <template>
94
+ <div class="space-y-2">
95
+ <div v-if="fields.length" class="flex items-center justify-between">
96
+ <span class="text-xs font-medium text-muted-foreground">
97
+ {{ expert ? "Trigger payload (JSON)" : "Trigger payload" }}
98
+ </span>
99
+ <label class="flex items-center gap-1.5 text-xs text-muted-foreground">
100
+ <Switch :model-value="expert" @update:model-value="toggleExpert" />
101
+ Expert (JSON)
102
+ </label>
103
+ </div>
104
+ <label v-else class="text-xs font-medium text-muted-foreground">Trigger payload (JSON)</label>
105
+
106
+ <!-- ── Form mode: fields derived from the blob's payload references ──── -->
107
+ <div v-if="!expert && fields.length" class="space-y-3">
108
+ <div v-for="field in fields" :key="`${field.kind}:${field.path}`" class="space-y-1">
109
+ <label class="text-xs font-medium">{{ field.label }}</label>
110
+
111
+ <template v-if="field.kind === 'file'">
112
+ <div
113
+ v-if="!files[field.path]"
114
+ class="relative flex items-center justify-center gap-2 rounded-md border border-dashed px-3 py-5 text-sm text-muted-foreground transition"
115
+ :class="dragOver === field.path ? 'border-emerald-500/60 bg-emerald-500/5 text-emerald-700' : 'border-black/[0.12] hover:border-black/25'"
116
+ @dragover.prevent="dragOver = field.path"
117
+ @dragleave="dragOver = null"
118
+ @drop.prevent="onDrop(field.path, $event)"
119
+ >
120
+ <Paperclip :size="14" />
121
+ Drop a file here or click to choose
122
+ <input
123
+ type="file"
124
+ class="absolute inset-0 cursor-pointer opacity-0"
125
+ @change="onPick(field.path, $event)"
126
+ >
127
+ </div>
128
+ <div v-else class="flex items-center gap-2 rounded-md border border-black/[0.08] bg-muted/30 px-2.5 py-1.5 text-sm">
129
+ <Paperclip :size="13" class="shrink-0 text-muted-foreground" />
130
+ <span class="min-w-0 flex-1 truncate">{{ files[field.path].filename }}</span>
131
+ <span class="shrink-0 text-xs text-muted-foreground">{{ prettyBytes(files[field.path].size) }}</span>
132
+ <button
133
+ type="button"
134
+ class="flex size-6 shrink-0 items-center justify-center rounded text-muted-foreground transition hover:bg-muted/60 hover:text-rose-600"
135
+ title="Remove file"
136
+ @click="detach(field.path)"
137
+ >
138
+ <Trash2 :size="13" />
139
+ </button>
140
+ </div>
141
+ <p v-if="files[field.path] && files[field.path].size > WARN_BYTES" class="text-xs text-amber-700">
142
+ Large file — payloads beyond ~25 MB can exceed the workflow bus limits. Prefer the SFTP or IO routes for big files.
143
+ </p>
144
+ </template>
145
+
146
+ <template v-else>
147
+ <Input
148
+ :model-value="textValues[field.path] ?? ''"
149
+ class="h-8 text-sm"
150
+ :placeholder="`\${{ trigger.payload.${field.path} }}`"
151
+ @update:model-value="(v) => {
152
+ textValues = { ...textValues, [field.path]: String(v) };
153
+ }"
154
+ />
155
+ </template>
156
+ </div>
157
+ <p v-if="Object.keys(extras).length" class="text-xs text-muted-foreground">
158
+ Additional payload keys from the expert view are kept: {{ Object.keys(extras).join(", ") }}
159
+ </p>
160
+ </div>
161
+
162
+ <!-- ── Expert mode: the raw JSON ─────────────────────────────────────── -->
163
+ <template v-else>
164
+ <Textarea
165
+ v-model="model"
166
+ :rows="8"
167
+ spellcheck="false"
168
+ class="font-mono text-xs"
169
+ placeholder="{}"
170
+ />
171
+ </template>
172
+
173
+ <p v-if="parseNote" class="text-xs text-rose-600">{{ parseNote }}</p>
174
+ </div>
175
+ </template>
@@ -0,0 +1,13 @@
1
+ import type { WorkflowBlob } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ blob: Pick<WorkflowBlob, 'nodes'>;
4
+ };
5
+ type __VLS_PublicProps = __VLS_Props & {
6
+ modelValue?: string;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (value: string) => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Result surface for a manual run, sync and async alike. The parent opens it
3
+ * in a loading state, awaits the trigger, then feeds through the outcome:
4
+ *
5
+ * - sync: the run's response body (JSON) or a mapped error (timeout /
6
+ * failed run). A failed 422 ships the run object, so `runId` lets
7
+ * the operator jump straight into the run detail.
8
+ * - async: a started confirmation with the fresh run's number — the visible
9
+ * counterpart to the fire-and-forget POST.
10
+ */
11
+ type __VLS_Props = {
12
+ open: boolean;
13
+ loading?: boolean;
14
+ mode?: 'sync' | 'async';
15
+ response?: unknown;
16
+ error?: string | null;
17
+ /** The run behind this result (sync failure / async start) for deep-linking. */
18
+ runId?: string | null;
19
+ };
20
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
21
+ "update:open": (args_0: boolean) => any;
22
+ "view-run": (id: string) => any;
23
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
24
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
25
+ "onView-run"?: ((id: string) => any) | undefined;
26
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ export default _default;
@@ -0,0 +1,84 @@
1
+ <script setup>
2
+ import { CheckCircle as CheckCircle2, RefreshCircle as Loader2 } from "#solar-icons";
3
+ import {
4
+ Button,
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogHeader,
9
+ DialogTitle
10
+ } from "@revenexx/studio";
11
+ defineProps({
12
+ open: { type: Boolean, required: true },
13
+ loading: { type: Boolean, required: false },
14
+ mode: { type: String, required: false },
15
+ response: { type: null, required: false },
16
+ error: { type: [String, null], required: false },
17
+ runId: { type: [String, null], required: false }
18
+ });
19
+ const emit = defineEmits(["update:open", "view-run"]);
20
+ </script>
21
+
22
+ <template>
23
+ <Dialog :open="open" @update:open="(v) => emit('update:open', v)">
24
+ <!-- Wide result surface — but hard-capped: min-w-0 down the tree keeps the
25
+ JSON <pre> scrolling INSIDE instead of blowing the dialog open. -->
26
+ <DialogContent class="max-w-[94vw] overflow-hidden sm:max-w-4xl">
27
+ <DialogHeader>
28
+ <DialogTitle>{{ mode === "async" ? "Run started" : "Run response" }}</DialogTitle>
29
+ <DialogDescription class="font-mono text-sm">
30
+ {{ mode === "async" ? "Queued for background execution" : "Synchronous run result" }}
31
+ </DialogDescription>
32
+ </DialogHeader>
33
+
34
+ <div class="min-w-0 max-w-full text-sm">
35
+ <div v-if="loading" class="flex items-center gap-2 py-6 text-muted-foreground">
36
+ <Loader2 :size="16" class="animate-spin" />
37
+ {{ mode === "async" ? "Starting\u2026" : "Running\u2026" }}
38
+ </div>
39
+
40
+ <template v-else-if="error">
41
+ <div class="rounded-md border border-rose-500/20 bg-rose-500/5 px-3 py-2 text-rose-700">
42
+ {{ error }}
43
+ </div>
44
+ <div v-if="runId" class="mt-3 flex justify-end">
45
+ <Button class="h-8 text-sm" @click="emit('view-run', runId)">
46
+ View run #{{ runId }}
47
+ </Button>
48
+ </div>
49
+ </template>
50
+
51
+ <template v-else-if="mode === 'async'">
52
+ <div class="flex items-center gap-2 rounded-md border border-emerald-500/20 bg-emerald-500/5 px-3 py-2 text-emerald-700">
53
+ <CheckCircle2 :size="15" class="shrink-0" />
54
+ <span v-if="runId">Run #{{ runId }} started and is executing in the background.</span>
55
+ <span v-else>Run started and is executing in the background.</span>
56
+ </div>
57
+ <div class="mt-3 flex justify-end gap-2">
58
+ <Button variant="outline" class="h-8 text-sm" @click="emit('update:open', false)">
59
+ Close
60
+ </Button>
61
+ <Button v-if="runId" class="h-8 text-sm" @click="emit('view-run', runId)">
62
+ View run
63
+ </Button>
64
+ </div>
65
+ </template>
66
+
67
+ <template v-else-if="response !== void 0 && response !== null">
68
+ <pre
69
+ class="max-h-[66vh] w-full min-w-0 max-w-full overflow-auto rounded-md border border-black/[0.06] bg-slate-50 p-3 text-xs"
70
+ >{{ JSON.stringify(response, null, 2) }}</pre>
71
+ <div v-if="runId" class="mt-3 flex justify-end">
72
+ <Button variant="outline" class="h-8 text-sm" @click="emit('view-run', runId)">
73
+ View run
74
+ </Button>
75
+ </div>
76
+ </template>
77
+
78
+ <p v-else class="py-6 text-muted-foreground">
79
+ No response.
80
+ </p>
81
+ </div>
82
+ </DialogContent>
83
+ </Dialog>
84
+ </template>
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Result surface for a manual run, sync and async alike. The parent opens it
3
+ * in a loading state, awaits the trigger, then feeds through the outcome:
4
+ *
5
+ * - sync: the run's response body (JSON) or a mapped error (timeout /
6
+ * failed run). A failed 422 ships the run object, so `runId` lets
7
+ * the operator jump straight into the run detail.
8
+ * - async: a started confirmation with the fresh run's number — the visible
9
+ * counterpart to the fire-and-forget POST.
10
+ */
11
+ type __VLS_Props = {
12
+ open: boolean;
13
+ loading?: boolean;
14
+ mode?: 'sync' | 'async';
15
+ response?: unknown;
16
+ error?: string | null;
17
+ /** The run behind this result (sync failure / async start) for deep-linking. */
18
+ runId?: string | null;
19
+ };
20
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
21
+ "update:open": (args_0: boolean) => any;
22
+ "view-run": (id: string) => any;
23
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
24
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
25
+ "onView-run"?: ((id: string) => any) | undefined;
26
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import type { WorkflowRun } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ runs: WorkflowRun[];
4
+ loading?: boolean;
5
+ emptyText?: string;
6
+ /** false when the owning list pages server-side (workflow Runs tab). */
7
+ pagination?: boolean;
8
+ /** false inside a workflow — the context makes the column redundant. */
9
+ showWorkflow?: boolean;
10
+ };
11
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ changed: () => any;
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
+ onChanged?: (() => any) | undefined;
15
+ }>, {
16
+ loading: boolean;
17
+ emptyText: string;
18
+ pagination: boolean;
19
+ showWorkflow: boolean;
20
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,114 @@
1
+ <script setup>
2
+ import { computed, onMounted, onUnmounted, ref } from "vue";
3
+ import { Badge } from "@revenexx/studio";
4
+ import { statusClass } from "../../utils/statusStyle";
5
+ const props = defineProps({
6
+ runs: { type: Array, required: true },
7
+ loading: { type: Boolean, required: false, default: false },
8
+ emptyText: { type: String, required: false, default: "No runs yet \u2014 kick off a workflow to populate this view." },
9
+ pagination: { type: Boolean, required: false, default: true },
10
+ showWorkflow: { type: Boolean, required: false, default: true }
11
+ });
12
+ const emit = defineEmits(["changed"]);
13
+ const router = useRouter();
14
+ const now = ref(Date.now());
15
+ let tick = null;
16
+ onMounted(() => {
17
+ tick = setInterval(() => {
18
+ now.value = Date.now();
19
+ }, 3e3);
20
+ });
21
+ onUnmounted(() => {
22
+ if (tick) {
23
+ clearInterval(tick);
24
+ tick = null;
25
+ }
26
+ });
27
+ function openRun(r) {
28
+ void router.push({ path: `/integrations/workflows/${r.workflowId}`, query: { run: r.id } });
29
+ }
30
+ function formatRelative(iso) {
31
+ if (!iso) return "\u2014";
32
+ const ms = Date.now() - new Date(iso).getTime();
33
+ if (Number.isNaN(ms)) return "\u2014";
34
+ if (ms < 6e4) return `${Math.max(1, Math.floor(ms / 1e3))}s ago`;
35
+ if (ms < 36e5) return `${Math.floor(ms / 6e4)}m ago`;
36
+ if (ms < 864e5) return `${Math.floor(ms / 36e5)}h ago`;
37
+ return `${Math.floor(ms / 864e5)}d ago`;
38
+ }
39
+ function formatDuration(ms) {
40
+ if (ms == null) return "\u2014";
41
+ if (ms < 1e3) return `${ms}ms`;
42
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(2)}s`;
43
+ return `${(ms / 6e4).toFixed(1)}m`;
44
+ }
45
+ function liveDuration(run) {
46
+ if (!run.startedAt) return null;
47
+ const start = Date.parse(run.startedAt);
48
+ if (Number.isNaN(start)) return null;
49
+ const end = run.finishedAt ? Date.parse(run.finishedAt) : now.value;
50
+ return end - start;
51
+ }
52
+ const columns = computed(() => [
53
+ { key: "status", label: "Status", width: "100px", sortable: true, sortGetter: (r) => r.status },
54
+ ...props.showWorkflow ? [{ key: "workflow", label: "Workflow", sortable: true, sortGetter: (r) => r.workflowName.toLowerCase(), searchGetter: (r) => r.workflowName }] : [],
55
+ // Fixed floor wide enough for a full UUID, flexible above it — header and
56
+ // body rows are separate grids, so a content-sized track (max-content)
57
+ // would misalign them. The flex share also lets the table fill the width.
58
+ { key: "id", label: "ID", width: "minmax(280px,1fr)", searchGetter: (r) => `${r.temporalRunId ?? ""} ${r.id}` },
59
+ { key: "trigger", label: "Trigger", width: "120px", sortable: true, sortGetter: (r) => r.triggerType },
60
+ { key: "started", label: "Started", width: "120px", sortable: true, sortGetter: (r) => r.startedAt },
61
+ { key: "duration", label: "Duration", width: "100px", sortable: true, sortGetter: (r) => r.durationMs ?? -1 },
62
+ { key: "actions", label: "", width: "52px" }
63
+ ]);
64
+ </script>
65
+
66
+ <template>
67
+ <DataTable
68
+ :data="runs"
69
+ :columns="columns"
70
+ :row-key="(r) => r.id"
71
+ :default-sort="{ column: 'started', direction: 'desc' }"
72
+ :search="{ placeholder: 'Search runs\u2026' }"
73
+ :filter="true"
74
+ :loading="loading"
75
+ :pagination="pagination"
76
+ :empty-text="emptyText"
77
+ @row-click="(r) => openRun(r)"
78
+ >
79
+ <template #cell-status="{ row: run }">
80
+ <Badge variant="outline" :class="['border text-xs font-medium uppercase', statusClass(run.status)]">
81
+ {{ run.status }}
82
+ </Badge>
83
+ </template>
84
+
85
+ <template #cell-workflow="{ row: run }">
86
+ <div class="font-medium text-sm truncate">{{ run.workflowName }}</div>
87
+ </template>
88
+
89
+ <template #cell-id="{ row: run }">
90
+ <span v-if="run.temporalRunId" class="font-mono text-xs whitespace-nowrap">{{ run.temporalRunId }}</span>
91
+ <span v-else class="text-xs text-muted-foreground">—</span>
92
+ </template>
93
+
94
+ <template #cell-trigger="{ row: run }">
95
+ <span class="inline-flex items-center whitespace-nowrap rounded-md border border-black/[0.06] bg-muted/50 px-1.5 py-0.5 text-xs font-medium uppercase text-muted-foreground">
96
+ {{ run.triggerType }}
97
+ </span>
98
+ </template>
99
+
100
+ <template #cell-started="{ row: run }">
101
+ <span class="text-sm text-muted-foreground tabular-nums">{{ formatRelative(run.startedAt) }}</span>
102
+ </template>
103
+
104
+ <template #cell-duration="{ row: run }">
105
+ <span class="text-sm tabular-nums">{{ formatDuration(liveDuration(run)) }}</span>
106
+ </template>
107
+
108
+ <template #cell-actions="{ row: run }">
109
+ <div class="flex justify-end">
110
+ <IntegrationsRunActionsMenu :run="run" @changed="emit('changed')" />
111
+ </div>
112
+ </template>
113
+ </DataTable>
114
+ </template>
@@ -0,0 +1,21 @@
1
+ import type { WorkflowRun } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ runs: WorkflowRun[];
4
+ loading?: boolean;
5
+ emptyText?: string;
6
+ /** false when the owning list pages server-side (workflow Runs tab). */
7
+ pagination?: boolean;
8
+ /** false inside a workflow — the context makes the column redundant. */
9
+ showWorkflow?: boolean;
10
+ };
11
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ changed: () => any;
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
+ onChanged?: (() => any) | undefined;
15
+ }>, {
16
+ loading: boolean;
17
+ emptyText: string;
18
+ pagination: boolean;
19
+ showWorkflow: boolean;
20
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,11 @@
1
+ type __VLS_PublicProps = {
2
+ 'open'?: boolean;
3
+ };
4
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:open": (value: boolean) => any;
6
+ created: (id: string) => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
8
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
9
+ onCreated?: ((id: string) => any) | undefined;
10
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ export default _default;
@@ -0,0 +1,91 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ import { RefreshCircle as Loader2 } from "#solar-icons";
4
+ import { Badge, Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@revenexx/studio";
5
+ import { useIntegrationsCredentials } from "../../composables/useIntegrationsCredentials";
6
+ const open = defineModel("open", { type: Boolean, ...{ default: false } });
7
+ const emit = defineEmits(["created"]);
8
+ const sftp = useConsoleSftp();
9
+ const { create } = useIntegrationsCredentials();
10
+ const busyId = ref(null);
11
+ const error = ref(null);
12
+ watch(open, (o) => {
13
+ if (o) {
14
+ error.value = null;
15
+ void sftp.load();
16
+ }
17
+ });
18
+ const activeAccounts = computed(() => sftp.accounts.value.filter((a) => a.status === "active" && a.login_username));
19
+ async function importAccount(account) {
20
+ const tenant = sftp.activeTenantSlug.value;
21
+ if (!tenant || !account.login_username) return;
22
+ busyId.value = account.id;
23
+ error.value = null;
24
+ try {
25
+ const creds = await sftp.revealPassword(tenant, account.id);
26
+ if (!creds?.password) {
27
+ error.value = "Could not read the account password.";
28
+ return;
29
+ }
30
+ const created = await create({
31
+ credential_type_slug: "revenexx:sftp",
32
+ name: `Platform SFTP \xB7 ${account.login_username}`,
33
+ config: {
34
+ host: creds.server ?? account.server ?? "",
35
+ port: 22,
36
+ username: creds.username ?? account.login_username,
37
+ password: creds.password
38
+ }
39
+ });
40
+ emit("created", created.id);
41
+ open.value = false;
42
+ } catch (err) {
43
+ error.value = err instanceof Error ? err.message : "Import failed.";
44
+ } finally {
45
+ busyId.value = null;
46
+ }
47
+ }
48
+ </script>
49
+
50
+ <template>
51
+ <Dialog v-model:open="open">
52
+ <DialogContent class="sm:max-w-md">
53
+ <DialogHeader>
54
+ <DialogTitle>Import platform SFTP account</DialogTitle>
55
+ <DialogDescription class="text-sm">
56
+ Creates an SFTP credential from a managed platform account — host, username and password are copied once. Later password changes must be re-imported.
57
+ </DialogDescription>
58
+ </DialogHeader>
59
+
60
+ <div v-if="sftp.loading.value && !activeAccounts.length" class="space-y-2">
61
+ <div v-for="n in 3" :key="`sk-${n}`" class="h-9 rounded-md bg-black/[0.07] animate-pulse" />
62
+ </div>
63
+ <p v-else-if="!activeAccounts.length" class="py-4 text-center text-sm text-muted-foreground">
64
+ No active platform SFTP accounts. Create one under Integration Studio → SFTP first.
65
+ </p>
66
+ <div v-else class="max-h-72 space-y-1 overflow-y-auto">
67
+ <button
68
+ v-for="account in activeAccounts"
69
+ :key="account.id"
70
+ type="button"
71
+ class="flex w-full items-center gap-2 rounded-md border border-black/[0.06] bg-white px-2.5 py-2 text-left transition hover:border-black/20"
72
+ :disabled="busyId !== null"
73
+ @click="importAccount(account)"
74
+ >
75
+ <span class="min-w-0 flex-1">
76
+ <span class="block truncate font-mono text-sm">{{ account.login_username }}</span>
77
+ <span class="block truncate text-xs text-muted-foreground">{{ account.home_directory ?? account.server ?? "" }}</span>
78
+ </span>
79
+ <Badge variant="outline" class="text-xs font-medium uppercase shrink-0">Active</Badge>
80
+ <Loader2 v-if="busyId === account.id" :size="14" class="shrink-0 animate-spin text-muted-foreground" />
81
+ </button>
82
+ </div>
83
+
84
+ <p v-if="error" class="text-sm text-rose-600">{{ error }}</p>
85
+
86
+ <div class="flex justify-end">
87
+ <Button variant="outline" size="sm" class="h-8 text-sm" @click="open = false">Close</Button>
88
+ </div>
89
+ </DialogContent>
90
+ </Dialog>
91
+ </template>
@@ -0,0 +1,11 @@
1
+ type __VLS_PublicProps = {
2
+ 'open'?: boolean;
3
+ };
4
+ declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:open": (value: boolean) => any;
6
+ created: (id: string) => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
8
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
9
+ onCreated?: ((id: string) => any) | undefined;
10
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ export default _default;
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { Pulse as Activity, ClockCircle as Clock, Home, Key as KeyRound, ShieldCheck, ShieldKeyhole as Credentials, Programming as Workflow } from "#solar-icons";
3
+ import SidebarNav from "@revenexx/studio-shared/components/Shared/SidebarNav.vue";
3
4
  const { workflows } = useIntegrationsWorkflows();
4
5
  const { runningCount } = useIntegrationsRuns();
5
6
  const { activeCount: schedulesActive } = useIntegrationsSchedules();