@revenexx/studio-integrations 0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/module.d.mts +2 -2
- 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/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 -7
- package/dist/runtime/composables/integrationsApi.js +6 -12
- package/dist/runtime/composables/useCanvasShortcuts.d.ts +37 -0
- package/dist/runtime/composables/useCanvasShortcuts.js +62 -0
- package/dist/runtime/composables/useCredentialTypes.js +2 -1
- package/dist/runtime/composables/useIntegrationsAudit.js +2 -1
- package/dist/runtime/composables/useIntegrationsCredentials.js +2 -1
- 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 +8 -4
- package/dist/runtime/composables/useIntegrationsRevisions.d.ts +40 -0
- package/dist/runtime/composables/useIntegrationsRevisions.js +52 -0
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +21 -1
- package/dist/runtime/composables/useIntegrationsRuns.js +94 -5
- package/dist/runtime/composables/useIntegrationsSecrets.js +2 -1
- package/dist/runtime/composables/useIntegrationsTemplates.d.ts +1 -0
- package/dist/runtime/composables/useIntegrationsTemplates.js +34 -5
- package/dist/runtime/composables/useIntegrationsTriggers.js +2 -1
- package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +1 -0
- package/dist/runtime/composables/useIntegrationsWorkflows.js +59 -2
- 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 +124 -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/apiError.d.ts +17 -0
- package/dist/runtime/utils/apiError.js +8 -0
- 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 +20 -3
- 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
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
|
|
3
|
-
constructor(status, body, message) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.status = status;
|
|
6
|
-
this.body = body;
|
|
7
|
-
this.name = "IntegrationsApiError";
|
|
8
|
-
}
|
|
9
|
-
}
|
|
2
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
10
3
|
export function useIntegrationsApi() {
|
|
11
4
|
const config = useRuntimeConfig();
|
|
12
5
|
const { getToken } = usePlatformAuth();
|
|
@@ -29,13 +22,14 @@ export function useIntegrationsApi() {
|
|
|
29
22
|
function url(path) {
|
|
30
23
|
return `${baseUrl.value.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
31
24
|
}
|
|
32
|
-
async function request(method, path, body) {
|
|
25
|
+
async function request(method, path, body, opts) {
|
|
33
26
|
const headers = await buildHeaders(body !== void 0 ? { "Content-Type": "application/json" } : {});
|
|
34
27
|
try {
|
|
35
28
|
return await $fetch(url(path), {
|
|
36
29
|
method,
|
|
37
30
|
headers,
|
|
38
|
-
body: body !== void 0 ? body : void 0
|
|
31
|
+
body: body !== void 0 ? body : void 0,
|
|
32
|
+
signal: opts?.signal
|
|
39
33
|
});
|
|
40
34
|
} catch (err) {
|
|
41
35
|
const fe = err;
|
|
@@ -46,8 +40,8 @@ export function useIntegrationsApi() {
|
|
|
46
40
|
}
|
|
47
41
|
return {
|
|
48
42
|
baseUrl,
|
|
49
|
-
get: (path) => request("GET", path),
|
|
50
|
-
post: (path, body) => request("POST", path, body ?? {}),
|
|
43
|
+
get: (path, opts) => request("GET", path, void 0, opts),
|
|
44
|
+
post: (path, body, opts) => request("POST", path, body ?? {}, opts),
|
|
51
45
|
put: (path, body) => request("PUT", path, body ?? {}),
|
|
52
46
|
patch: (path, body) => request("PATCH", path, body ?? {}),
|
|
53
47
|
del: (path) => request("DELETE", path)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCanvasShortcuts — document-level keyboard shortcuts for the workflow
|
|
3
|
+
* canvas, with editing-context scoping.
|
|
4
|
+
*
|
|
5
|
+
* Modeled on n8n's useKeybindings (editor-ui/src/app/composables/useKeybindings.ts)
|
|
6
|
+
* but dependency-free (no @vueuse) and with the platform-neutral `mod` token.
|
|
7
|
+
*
|
|
8
|
+
* Map keys:
|
|
9
|
+
* - tokens joined by '+': modifiers `mod` (⌘ on mac, Ctrl elsewhere), `shift`,
|
|
10
|
+
* `alt`, plus one key: a single character ('a', '1', '+'), or a named key
|
|
11
|
+
* ('enter', 'escape', 'tab', 'space', 'f2', 'delete', 'backspace',
|
|
12
|
+
* 'arrowup', ...). Case-insensitive.
|
|
13
|
+
* - alternatives via '|': 'f2|space' fires on either.
|
|
14
|
+
*
|
|
15
|
+
* Handlers are a function or `{ disabled: () => boolean, run: fn }` — a disabled
|
|
16
|
+
* handler lets the event fall through untouched (no preventDefault), so e.g.
|
|
17
|
+
* Enter still types a newline when nothing is selected.
|
|
18
|
+
*
|
|
19
|
+
* Scoping — a keydown is IGNORED entirely when:
|
|
20
|
+
* 1. `options.disabled` is truthy (the editor passes "config lightbox open").
|
|
21
|
+
* 2. The event target (or activeElement fallback) is INPUT / TEXTAREA / SELECT,
|
|
22
|
+
* is contenteditable, or sits inside a [contenteditable] ancestor.
|
|
23
|
+
* 3. The target or an ancestor carries `data-canvas-shortcuts-ignore`.
|
|
24
|
+
* 4. `event.defaultPrevented` — someone upstream already claimed the key.
|
|
25
|
+
*
|
|
26
|
+
* On a match: preventDefault() + stopPropagation(), then run. Non-matching
|
|
27
|
+
* combos are never touched, so browser shortcuts keep working.
|
|
28
|
+
*/
|
|
29
|
+
import type { MaybeRefOrGetter } from 'vue';
|
|
30
|
+
export type ShortcutHandler = ((event: KeyboardEvent) => void) | {
|
|
31
|
+
disabled: () => boolean;
|
|
32
|
+
run: (event: KeyboardEvent) => void;
|
|
33
|
+
};
|
|
34
|
+
export type ShortcutMap = Record<string, ShortcutHandler>;
|
|
35
|
+
export declare function useCanvasShortcuts(keymap: MaybeRefOrGetter<ShortcutMap>, options?: {
|
|
36
|
+
disabled?: MaybeRefOrGetter<boolean>;
|
|
37
|
+
}): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { computed, onBeforeUnmount, onMounted, toValue } from "vue";
|
|
2
|
+
const IS_MAC = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "");
|
|
3
|
+
function canonical(parts) {
|
|
4
|
+
return parts.map((p) => p.toLowerCase()).sort((a, b) => a.localeCompare(b)).join("+");
|
|
5
|
+
}
|
|
6
|
+
function normalizeShortcut(shortcut) {
|
|
7
|
+
if (shortcut.length === 1) return shortcut.toLowerCase();
|
|
8
|
+
return canonical(shortcut.split("+"));
|
|
9
|
+
}
|
|
10
|
+
function codeToKey(code) {
|
|
11
|
+
if (code.startsWith("Key")) return code.slice(3).toLowerCase();
|
|
12
|
+
if (code.startsWith("Digit")) return code.slice(5);
|
|
13
|
+
return code.toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
function eventShortcuts(event) {
|
|
16
|
+
const mods = [];
|
|
17
|
+
if (event.shiftKey) mods.push("shift");
|
|
18
|
+
if (event.altKey) mods.push("alt");
|
|
19
|
+
if (IS_MAC ? event.metaKey : event.ctrlKey) mods.push("mod");
|
|
20
|
+
const key = event.key === " " ? "space" : event.key.toLowerCase();
|
|
21
|
+
const code = codeToKey(event.code ?? "");
|
|
22
|
+
return {
|
|
23
|
+
byKey: canonical([...mods, key]),
|
|
24
|
+
byCode: canonical([...mods, code])
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function isEditingContext(event) {
|
|
28
|
+
const el = event.target instanceof Element ? event.target : document.activeElement;
|
|
29
|
+
if (!el) return false;
|
|
30
|
+
const tag = el.tagName;
|
|
31
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
|
32
|
+
if (el.isContentEditable) return true;
|
|
33
|
+
if (el.closest('[contenteditable=""],[contenteditable="true"]')) return true;
|
|
34
|
+
if (el.closest("[data-canvas-shortcuts-ignore]")) return true;
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
export function useCanvasShortcuts(keymap, options) {
|
|
38
|
+
const normalized = computed(() => {
|
|
39
|
+
const out = {};
|
|
40
|
+
for (const [combo, handler] of Object.entries(toValue(keymap))) {
|
|
41
|
+
for (const alt of combo.split("|")) {
|
|
42
|
+
out[normalizeShortcut(alt.trim())] = handler;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
});
|
|
47
|
+
function onKeyDown(event) {
|
|
48
|
+
if (toValue(options?.disabled)) return;
|
|
49
|
+
if (event.defaultPrevented) return;
|
|
50
|
+
if (isEditingContext(event)) return;
|
|
51
|
+
const { byKey, byCode } = eventShortcuts(event);
|
|
52
|
+
const handler = normalized.value[byKey] ?? normalized.value[byCode];
|
|
53
|
+
if (!handler) return;
|
|
54
|
+
const run = typeof handler === "function" ? handler : handler.disabled() ? void 0 : handler.run;
|
|
55
|
+
if (!run) return;
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
event.stopPropagation();
|
|
58
|
+
run(event);
|
|
59
|
+
}
|
|
60
|
+
onMounted(() => document.addEventListener("keydown", onKeyDown));
|
|
61
|
+
onBeforeUnmount(() => document.removeEventListener("keydown", onKeyDown));
|
|
62
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
2
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
2
3
|
export function useCredentialTypes() {
|
|
3
4
|
const types = useState("integrations.credentialTypes", () => []);
|
|
4
5
|
const loading = useState("integrations.credentialTypes.loading", () => false);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
2
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
2
3
|
export function useIntegrationsAudit() {
|
|
3
4
|
const api = useIntegrationsApi();
|
|
4
5
|
const entries = useState("int.audit.entries", () => []);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
3
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
3
4
|
export function useIntegrationsCredentials() {
|
|
4
5
|
const credentials = useState("integrations.credentials", () => []);
|
|
5
6
|
const loading = useState("integrations.credentials.loading", () => false);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DeadLetterRow } from '../types/integrations.js';
|
|
2
|
+
/** A dead letter enriched with its workflow's name (global "Missed runs" view). */
|
|
3
|
+
export interface GlobalDeadLetterRow extends DeadLetterRow {
|
|
4
|
+
workflowName: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function useIntegrationsDeadLetters(): {
|
|
7
|
+
list: (workflowId: number | string, opts?: {
|
|
8
|
+
page?: number;
|
|
9
|
+
perPage?: number;
|
|
10
|
+
}) => Promise<{
|
|
11
|
+
items: DeadLetterRow[];
|
|
12
|
+
total: number;
|
|
13
|
+
page: number;
|
|
14
|
+
lastPage: number;
|
|
15
|
+
}>;
|
|
16
|
+
replay: (id: number | string) => Promise<unknown>;
|
|
17
|
+
discard: (id: number | string) => Promise<unknown>;
|
|
18
|
+
loadGlobal: (force?: boolean) => Promise<GlobalDeadLetterRow[]>;
|
|
19
|
+
globalItems: any;
|
|
20
|
+
globalLoading: any;
|
|
21
|
+
pendingCount: import("vue").ComputedRef<any>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { computed } from "vue";
|
|
2
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
3
|
+
export function useIntegrationsDeadLetters() {
|
|
4
|
+
const api = useIntegrationsApi();
|
|
5
|
+
async function list(workflowId, opts = {}) {
|
|
6
|
+
const page = opts.page ?? 1;
|
|
7
|
+
const perPage = opts.perPage ?? 25;
|
|
8
|
+
const res = await api.get(
|
|
9
|
+
`/workflows/${workflowId}/dead-letters?page=${page}&per_page=${perPage}`
|
|
10
|
+
);
|
|
11
|
+
return {
|
|
12
|
+
items: res?.data ?? [],
|
|
13
|
+
total: res?.meta?.total ?? (res?.data?.length ?? 0),
|
|
14
|
+
page: res?.meta?.current_page ?? page,
|
|
15
|
+
lastPage: res?.meta?.last_page ?? 1
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const replay = (id) => api.post(`/dead-letters/${id}/replay`, {});
|
|
19
|
+
const discard = (id) => api.post(`/dead-letters/${id}/discard`, {});
|
|
20
|
+
const { workflows, load: loadWorkflows } = useIntegrationsWorkflows();
|
|
21
|
+
const globalItems = useState("integrations.deadletters.global", () => []);
|
|
22
|
+
const globalLoading = useState("integrations.deadletters.global.loading", () => false);
|
|
23
|
+
const globalLoaded = useState("integrations.deadletters.global.loaded", () => false);
|
|
24
|
+
const pendingCount = computed(() => globalItems.value.filter((i) => i.status === "pending").length);
|
|
25
|
+
async function loadGlobal(force = false) {
|
|
26
|
+
if (globalLoading.value) return globalItems.value;
|
|
27
|
+
if (globalLoaded.value && !force) return globalItems.value;
|
|
28
|
+
globalLoading.value = true;
|
|
29
|
+
try {
|
|
30
|
+
await loadWorkflows();
|
|
31
|
+
const MAX_PAGES = 20;
|
|
32
|
+
const per = await Promise.allSettled(workflows.value.map(async (wf) => {
|
|
33
|
+
const out = [];
|
|
34
|
+
let page = 1;
|
|
35
|
+
while (page <= MAX_PAGES) {
|
|
36
|
+
const res = await list(wf.id, { page, perPage: 100 });
|
|
37
|
+
out.push(...res.items.map((i) => ({ ...i, workflowName: wf.name })));
|
|
38
|
+
if (page >= res.lastPage) break;
|
|
39
|
+
page++;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}));
|
|
43
|
+
globalItems.value = per.flatMap((p) => p.status === "fulfilled" ? p.value : []).sort((a, b) => new Date(b.created_at ?? 0).getTime() - new Date(a.created_at ?? 0).getTime());
|
|
44
|
+
globalLoaded.value = true;
|
|
45
|
+
} finally {
|
|
46
|
+
globalLoading.value = false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { list, replay, discard, loadGlobal, globalItems, globalLoading, pendingCount };
|
|
50
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { findManifest } from '../data/integrationNodeCatalog.js';
|
|
2
|
+
import { resolveLocalized } from '../utils/localize.js';
|
|
1
3
|
export declare function useIntegrationsNodes(): {
|
|
2
4
|
loading: any;
|
|
3
5
|
error: any;
|
|
4
6
|
loaded: any;
|
|
5
7
|
load: (force?: boolean) => Promise<void>;
|
|
8
|
+
findManifest: typeof findManifest;
|
|
9
|
+
resolveLocalized: typeof resolveLocalized;
|
|
6
10
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { applyNodeCatalog } from "../data/integrationNodeCatalog.js";
|
|
2
|
-
import {
|
|
1
|
+
import { applyNodeCatalog, findManifest } from "../data/integrationNodeCatalog.js";
|
|
2
|
+
import { resolveLocalized } from "../utils/localize.js";
|
|
3
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
4
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
3
5
|
export function useIntegrationsNodes() {
|
|
4
6
|
const loading = useState("integrations.nodes.loading", () => false);
|
|
5
7
|
const error = useState("integrations.nodes.error", () => null);
|
|
@@ -17,7 +19,9 @@ export function useIntegrationsNodes() {
|
|
|
17
19
|
...n.manifest,
|
|
18
20
|
slug: n.manifest.slug ?? n.slug,
|
|
19
21
|
version: n.manifest.version ?? n.version,
|
|
20
|
-
name: n.manifest.name ?? n.name
|
|
22
|
+
name: n.manifest.name ?? n.name,
|
|
23
|
+
// Keep the source package — the palette groups app nodes by it.
|
|
24
|
+
__package: n.package ? { name: n.package.name, label: n.package.label ?? null } : void 0
|
|
21
25
|
}));
|
|
22
26
|
applyNodeCatalog(manifests);
|
|
23
27
|
loaded.value = true;
|
|
@@ -28,5 +32,5 @@ export function useIntegrationsNodes() {
|
|
|
28
32
|
loading.value = false;
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
|
-
return { loading, error, loaded, load };
|
|
35
|
+
return { loading, error, loaded, load, findManifest, resolveLocalized };
|
|
32
36
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { WorkflowBlob } from '../types/integrations.js';
|
|
2
|
+
/**
|
|
3
|
+
* Workflow revision history (PO — `workflow_histories`): every blob-changing
|
|
4
|
+
* save snapshots the previous revision. These endpoints expose that history
|
|
5
|
+
* and restore an archived revision as a brand-new one.
|
|
6
|
+
*
|
|
7
|
+
* GET /workflows/{id}/revisions → metadata list (paginated, newest first)
|
|
8
|
+
* GET /workflows/{id}/revisions/{rev} → full snapshot incl. blob + triggers
|
|
9
|
+
* POST /workflows/{id}/revisions/{rev}/restore
|
|
10
|
+
*/
|
|
11
|
+
export interface WorkflowRevisionMeta {
|
|
12
|
+
id: number;
|
|
13
|
+
revision: number;
|
|
14
|
+
name: string;
|
|
15
|
+
description: string | null;
|
|
16
|
+
active: boolean;
|
|
17
|
+
blob_definition_version: string;
|
|
18
|
+
created_at: string | null;
|
|
19
|
+
updated_at: string | null;
|
|
20
|
+
archived_at: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface WorkflowRevisionDetail extends WorkflowRevisionMeta {
|
|
23
|
+
/** Cockpit-shaped blob: triggers merged in, like useIntegrationsWorkflows.toCockpit. */
|
|
24
|
+
blob: WorkflowBlob;
|
|
25
|
+
}
|
|
26
|
+
export declare function useIntegrationsRevisions(): {
|
|
27
|
+
loading: import("vue").Ref<boolean, boolean>;
|
|
28
|
+
error: import("vue").Ref<string | null, string | null>;
|
|
29
|
+
list: (workflowId: number, page?: number, perPage?: number) => Promise<{
|
|
30
|
+
revisions: WorkflowRevisionMeta[];
|
|
31
|
+
meta: {
|
|
32
|
+
current_page: number;
|
|
33
|
+
per_page: number;
|
|
34
|
+
total: number;
|
|
35
|
+
last_page: number;
|
|
36
|
+
};
|
|
37
|
+
}>;
|
|
38
|
+
get: (workflowId: number, revision: number) => Promise<WorkflowRevisionDetail>;
|
|
39
|
+
restore: (workflowId: number, revision: number) => Promise<void>;
|
|
40
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
3
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
4
|
+
export function useIntegrationsRevisions() {
|
|
5
|
+
const api = useIntegrationsApi();
|
|
6
|
+
const loading = ref(false);
|
|
7
|
+
const error = ref(null);
|
|
8
|
+
function captureError(e, fallback) {
|
|
9
|
+
if (e instanceof IntegrationsApiError) return e.message;
|
|
10
|
+
return e?.message ?? fallback;
|
|
11
|
+
}
|
|
12
|
+
async function list(workflowId, page = 1, perPage = 25) {
|
|
13
|
+
loading.value = true;
|
|
14
|
+
error.value = null;
|
|
15
|
+
try {
|
|
16
|
+
const res = await api.get(`/workflows/${workflowId}/revisions?page=${page}&per_page=${perPage}`);
|
|
17
|
+
return { revisions: res.data ?? [], meta: res.meta };
|
|
18
|
+
} catch (e) {
|
|
19
|
+
error.value = captureError(e, "Could not load the revision history.");
|
|
20
|
+
throw e;
|
|
21
|
+
} finally {
|
|
22
|
+
loading.value = false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function get(workflowId, revision) {
|
|
26
|
+
const res = await api.get(`/workflows/${workflowId}/revisions/${revision}`);
|
|
27
|
+
const apiBlob = res.blob ?? {};
|
|
28
|
+
const triggers = (res.triggers ?? []).map((t) => ({
|
|
29
|
+
id: t.handle ?? String(t.id ?? ""),
|
|
30
|
+
type: t.type,
|
|
31
|
+
name: typeof t.name === "string" ? t.name : t.name ?? void 0,
|
|
32
|
+
active: t.active,
|
|
33
|
+
config: t.config ?? {}
|
|
34
|
+
}));
|
|
35
|
+
return {
|
|
36
|
+
...res,
|
|
37
|
+
blob: {
|
|
38
|
+
nodeManifestVersion: apiBlob.nodeManifestVersion ?? "v0-draft",
|
|
39
|
+
name: apiBlob.name ?? res.name,
|
|
40
|
+
nodes: apiBlob.nodes ?? [],
|
|
41
|
+
edges: apiBlob.edges ?? [],
|
|
42
|
+
triggerPositions: apiBlob.triggerPositions ?? {},
|
|
43
|
+
stickies: apiBlob.stickies ?? [],
|
|
44
|
+
triggers
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function restore(workflowId, revision) {
|
|
49
|
+
await api.post(`/workflows/${workflowId}/revisions/${revision}/restore`, {});
|
|
50
|
+
}
|
|
51
|
+
return { loading, error, list, get, restore };
|
|
52
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RunStatus, WorkflowRun } from '../types/integrations.js';
|
|
1
|
+
import type { RunStatus, RunStepRow, WorkflowRun } from '../types/integrations.js';
|
|
2
2
|
export declare function useIntegrationsRuns(): {
|
|
3
3
|
runs: any;
|
|
4
4
|
loading: any;
|
|
@@ -8,17 +8,37 @@ export declare function useIntegrationsRuns(): {
|
|
|
8
8
|
failedCount: import("vue").ComputedRef<any>;
|
|
9
9
|
runningCount: import("vue").ComputedRef<any>;
|
|
10
10
|
load: (force?: boolean) => Promise<WorkflowRun[]>;
|
|
11
|
+
loadForWorkflow: (workflowId: number, workflowName: string, opts?: {
|
|
12
|
+
reconcile?: boolean;
|
|
13
|
+
page?: number;
|
|
14
|
+
perPage?: number;
|
|
15
|
+
}) => Promise<{
|
|
16
|
+
runs: WorkflowRun[];
|
|
17
|
+
total: number;
|
|
18
|
+
page: number;
|
|
19
|
+
lastPage: number;
|
|
20
|
+
}>;
|
|
11
21
|
list: (filter?: {
|
|
12
22
|
workflowId?: number;
|
|
13
23
|
status?: RunStatus;
|
|
14
24
|
}) => WorkflowRun[];
|
|
15
25
|
get: (id: string) => WorkflowRun | null;
|
|
26
|
+
fetchRun: (workflowId: number | string, runId: number | string, workflowName: string) => Promise<WorkflowRun>;
|
|
16
27
|
trigger: (workflowId: number | string, payload?: Record<string, unknown>, mode?: "sync" | "async") => Promise<unknown>;
|
|
28
|
+
cancelRun: (workflowId: number | string, runId: number | string, reason?: string) => Promise<unknown>;
|
|
29
|
+
terminateRun: (workflowId: number | string, runId: number | string, reason?: string) => Promise<unknown>;
|
|
30
|
+
retryRun: (workflowId: number | string, runId: number | string) => Promise<unknown>;
|
|
31
|
+
resumeRun: (workflowId: number | string, runId: number | string, reason?: string) => Promise<unknown>;
|
|
17
32
|
getRun: (workflowId: number | string, runId: number | string) => Promise<unknown>;
|
|
18
33
|
getDetails: (workflowId: number | string, runId: number | string) => Promise<{
|
|
19
34
|
source: string;
|
|
20
35
|
data: Record<string, unknown>;
|
|
21
36
|
}>;
|
|
37
|
+
getSteps: (workflowId: number | string, runId: number | string, includePayloads?: boolean) => Promise<{
|
|
38
|
+
source: string;
|
|
39
|
+
run: Record<string, unknown>;
|
|
40
|
+
steps: RunStepRow[];
|
|
41
|
+
}>;
|
|
22
42
|
getHistory: (workflowId: number | string, runId: number | string, params?: {
|
|
23
43
|
page_token?: string;
|
|
24
44
|
page_size?: number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
3
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
3
4
|
function mapStatus(status) {
|
|
4
5
|
switch (status) {
|
|
5
6
|
case "completed":
|
|
@@ -8,14 +9,18 @@ function mapStatus(status) {
|
|
|
8
9
|
return "queued";
|
|
9
10
|
case "terminated":
|
|
10
11
|
return "failed";
|
|
12
|
+
case "timed_out":
|
|
13
|
+
return "failed";
|
|
11
14
|
case "running":
|
|
12
15
|
return "running";
|
|
13
16
|
case "failed":
|
|
14
17
|
return "failed";
|
|
15
18
|
case "cancelled":
|
|
16
19
|
return "cancelled";
|
|
20
|
+
// An unknown/unexpected status must never surface as a stuck `running` —
|
|
21
|
+
// fail closed so a run the backend can't classify is visibly terminal.
|
|
17
22
|
default:
|
|
18
|
-
return "
|
|
23
|
+
return "failed";
|
|
19
24
|
}
|
|
20
25
|
}
|
|
21
26
|
export function useIntegrationsRuns() {
|
|
@@ -23,19 +28,25 @@ export function useIntegrationsRuns() {
|
|
|
23
28
|
const loading = useState("integrations.runs.loading", () => false);
|
|
24
29
|
const error = useState("integrations.runs.error", () => null);
|
|
25
30
|
const loaded = useState("integrations.runs.loaded", () => false);
|
|
31
|
+
const reconciling = useState("integrations.runs.reconciling", () => false);
|
|
32
|
+
const SYNC_LIMIT = 5;
|
|
26
33
|
const api = useIntegrationsApi();
|
|
27
34
|
const { workflows, load: loadWorkflows } = useIntegrationsWorkflows();
|
|
28
35
|
function mapRun(r, workflowName) {
|
|
36
|
+
const startedMs = r.started_at ? new Date(r.started_at).getTime() : null;
|
|
37
|
+
const finishedMs = r.completed_at ? new Date(r.completed_at).getTime() : null;
|
|
29
38
|
return {
|
|
30
39
|
id: String(r.id),
|
|
31
40
|
workflowId: r.workflow_id,
|
|
32
41
|
workflowName,
|
|
33
42
|
status: mapStatus(r.status),
|
|
43
|
+
temporalRunId: r.temporal_run_id ?? null,
|
|
34
44
|
triggerId: "",
|
|
35
45
|
triggerType: "manual",
|
|
36
46
|
startedAt: r.started_at ?? "",
|
|
37
47
|
finishedAt: r.completed_at ?? null,
|
|
38
|
-
|
|
48
|
+
// Derived from the timestamps — the list payload carries no duration.
|
|
49
|
+
durationMs: startedMs != null && finishedMs != null && finishedMs >= startedMs ? finishedMs - startedMs : null,
|
|
39
50
|
steps: []
|
|
40
51
|
};
|
|
41
52
|
}
|
|
@@ -46,13 +57,41 @@ export function useIntegrationsRuns() {
|
|
|
46
57
|
error.value = null;
|
|
47
58
|
try {
|
|
48
59
|
await loadWorkflows();
|
|
60
|
+
const MAX_PAGES = 100;
|
|
49
61
|
const perWorkflow = await Promise.allSettled(
|
|
50
62
|
workflows.value.map(async (wf) => {
|
|
51
|
-
const
|
|
52
|
-
|
|
63
|
+
const out = [];
|
|
64
|
+
let page = 1;
|
|
65
|
+
while (page <= MAX_PAGES) {
|
|
66
|
+
const res = await api.get(
|
|
67
|
+
`/workflows/${wf.id}/runs?page=${page}&per_page=100`
|
|
68
|
+
);
|
|
69
|
+
out.push(...(res?.data ?? []).map((r) => mapRun(r, wf.name)));
|
|
70
|
+
const last = res?.meta?.last_page ?? 1;
|
|
71
|
+
if (page >= last) break;
|
|
72
|
+
page++;
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
53
75
|
})
|
|
54
76
|
);
|
|
55
77
|
runs.value = perWorkflow.flatMap((p) => p.status === "fulfilled" ? p.value : []).sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
|
|
78
|
+
if (!reconciling.value) {
|
|
79
|
+
reconciling.value = true;
|
|
80
|
+
try {
|
|
81
|
+
const active = runs.value.filter((r) => r.status === "running" || r.status === "queued").sort((a, b) => Number(b.id) - Number(a.id)).slice(0, SYNC_LIMIT);
|
|
82
|
+
await Promise.allSettled(active.map(async (r) => {
|
|
83
|
+
try {
|
|
84
|
+
const raw = await api.get(`/workflows/${r.workflowId}/runs/${r.id}`);
|
|
85
|
+
const apiRun = raw?.data ?? raw;
|
|
86
|
+
const fresh = mapRun(apiRun, r.workflowName);
|
|
87
|
+
runs.value = runs.value.map((x) => x.id === fresh.id ? fresh : x);
|
|
88
|
+
} catch {
|
|
89
|
+
}
|
|
90
|
+
}));
|
|
91
|
+
} finally {
|
|
92
|
+
reconciling.value = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
56
95
|
loaded.value = true;
|
|
57
96
|
} catch (e) {
|
|
58
97
|
error.value = e instanceof IntegrationsApiError ? e.message : e?.message ?? "Could not load runs.";
|
|
@@ -61,6 +100,32 @@ export function useIntegrationsRuns() {
|
|
|
61
100
|
}
|
|
62
101
|
return runs.value;
|
|
63
102
|
}
|
|
103
|
+
async function loadForWorkflow(workflowId, workflowName, opts = {}) {
|
|
104
|
+
const page = opts.page ?? 1;
|
|
105
|
+
const perPage = opts.perPage ?? 25;
|
|
106
|
+
const res = await api.get(
|
|
107
|
+
`/workflows/${workflowId}/runs?page=${page}&per_page=${perPage}`
|
|
108
|
+
);
|
|
109
|
+
let list2 = (res?.data ?? []).map((r) => mapRun(r, workflowName)).sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
|
|
110
|
+
if (opts.reconcile) {
|
|
111
|
+
const active = list2.filter((r) => r.status === "running" || r.status === "queued").sort((a, b) => Number(b.id) - Number(a.id)).slice(0, SYNC_LIMIT);
|
|
112
|
+
await Promise.allSettled(active.map(async (r) => {
|
|
113
|
+
try {
|
|
114
|
+
const raw = await api.get(`/workflows/${workflowId}/runs/${r.id}`);
|
|
115
|
+
const apiRun = raw?.data ?? raw;
|
|
116
|
+
const fresh = mapRun(apiRun, workflowName);
|
|
117
|
+
list2 = list2.map((x) => x.id === fresh.id ? fresh : x);
|
|
118
|
+
} catch {
|
|
119
|
+
}
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
runs: list2,
|
|
124
|
+
total: res?.meta?.total ?? list2.length,
|
|
125
|
+
page: res?.meta?.current_page ?? page,
|
|
126
|
+
lastPage: res?.meta?.last_page ?? 1
|
|
127
|
+
};
|
|
128
|
+
}
|
|
64
129
|
function list(filter) {
|
|
65
130
|
let result = [...runs.value];
|
|
66
131
|
if (filter?.workflowId !== void 0) result = result.filter((r) => r.workflowId === filter.workflowId);
|
|
@@ -76,8 +141,25 @@ export function useIntegrationsRuns() {
|
|
|
76
141
|
const res = await api.post(`/workflows/${workflowId}/runs`, body);
|
|
77
142
|
return res?.data ?? res;
|
|
78
143
|
}
|
|
144
|
+
async function runAction(workflowId, runId, action, reason) {
|
|
145
|
+
const body = reason ? { reason } : {};
|
|
146
|
+
const res = await api.post(`/workflows/${workflowId}/runs/${runId}/${action}`, body);
|
|
147
|
+
return res?.data ?? res;
|
|
148
|
+
}
|
|
149
|
+
const cancelRun = (workflowId, runId, reason) => runAction(workflowId, runId, "cancel", reason);
|
|
150
|
+
const terminateRun = (workflowId, runId, reason) => runAction(workflowId, runId, "terminate", reason);
|
|
151
|
+
const retryRun = (workflowId, runId) => runAction(workflowId, runId, "retry");
|
|
152
|
+
const resumeRun = (workflowId, runId, reason) => runAction(workflowId, runId, "resume", reason);
|
|
79
153
|
const getRun = (workflowId, runId) => api.get(`/workflows/${workflowId}/runs/${runId}`);
|
|
154
|
+
async function fetchRun(workflowId, runId, workflowName) {
|
|
155
|
+
const raw = await getRun(workflowId, runId);
|
|
156
|
+
const apiRun = raw?.data ?? raw;
|
|
157
|
+
return mapRun(apiRun, workflowName);
|
|
158
|
+
}
|
|
80
159
|
const getDetails = (workflowId, runId) => api.get(`/workflows/${workflowId}/runs/${runId}/details`);
|
|
160
|
+
const getSteps = (workflowId, runId, includePayloads = false) => api.get(
|
|
161
|
+
`/workflows/${workflowId}/runs/${runId}/steps${includePayloads ? "?include_payloads=1" : ""}`
|
|
162
|
+
);
|
|
81
163
|
const getHistory = (workflowId, runId, params = {}) => {
|
|
82
164
|
const qs = new URLSearchParams();
|
|
83
165
|
if (params.page_token) qs.set("page_token", params.page_token);
|
|
@@ -98,11 +180,18 @@ export function useIntegrationsRuns() {
|
|
|
98
180
|
failedCount,
|
|
99
181
|
runningCount,
|
|
100
182
|
load,
|
|
183
|
+
loadForWorkflow,
|
|
101
184
|
list,
|
|
102
185
|
get,
|
|
186
|
+
fetchRun,
|
|
103
187
|
trigger,
|
|
188
|
+
cancelRun,
|
|
189
|
+
terminateRun,
|
|
190
|
+
retryRun,
|
|
191
|
+
resumeRun,
|
|
104
192
|
getRun,
|
|
105
193
|
getDetails,
|
|
194
|
+
getSteps,
|
|
106
195
|
getHistory,
|
|
107
196
|
getStackTrace
|
|
108
197
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { useIntegrationsApi } from "./integrationsApi.js";
|
|
3
|
+
import { IntegrationsApiError } from "../utils/apiError.js";
|
|
3
4
|
const KEY_PATTERN = /^[A-Z0-9_]+$/;
|
|
4
5
|
export function useIntegrationsSecrets() {
|
|
5
6
|
const secrets = useState("integrations.secrets", () => []);
|
|
@@ -10,6 +10,7 @@ export declare function useIntegrationsTemplates(): {
|
|
|
10
10
|
list: () => WorkflowTemplate[];
|
|
11
11
|
get: (slug: string) => WorkflowTemplate | null;
|
|
12
12
|
fetchDetail: (slug: string) => Promise<WorkflowTemplate | null>;
|
|
13
|
+
ensureDetails: (slugs: string[], concurrency?: number) => Promise<void>;
|
|
13
14
|
requirements: (slug: string) => Promise<TemplateRequirements | null>;
|
|
14
15
|
instantiate: (slug: string, opts?: {
|
|
15
16
|
name?: string;
|