@revenexx/studio-integrations 0.5.1 → 0.7.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/CHANGELOG.md +428 -0
- package/README.md +48 -4
- package/dist/module.d.mts +17 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +10 -2
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +43 -41
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +123 -50
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +108 -71
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue +12 -15
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue +18 -17
- package/dist/runtime/components/Integrations/EventTypeCombobox.d.vue.ts +1 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue +7 -4
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue.d.ts +1 -0
- package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +4 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue +67 -37
- package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +4 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue +30 -20
- package/dist/runtime/components/Integrations/Layout.vue +48 -4
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue +23 -23
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue +11 -13
- package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +2 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue +187 -93
- package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +2 -0
- package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +6 -0
- package/dist/runtime/components/Integrations/NodeInspector.vue +1157 -376
- package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +6 -0
- package/dist/runtime/components/Integrations/NodeLogo.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/NodeLogo.vue +2 -30
- package/dist/runtime/components/Integrations/NodeLogo.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/NodeMark.d.vue.ts +15 -0
- package/dist/runtime/components/Integrations/NodeMark.vue +79 -0
- package/dist/runtime/components/Integrations/NodeMark.vue.d.ts +15 -0
- package/dist/runtime/components/Integrations/NodeOutputSchema.d.vue.ts +21 -0
- package/dist/runtime/components/Integrations/NodeOutputSchema.vue +43 -0
- package/dist/runtime/components/Integrations/NodeOutputSchema.vue.d.ts +21 -0
- package/dist/runtime/components/Integrations/NodePalette.vue +122 -55
- package/dist/runtime/components/Integrations/QueryBuilder.vue +46 -38
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +38 -12
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +114 -62
- package/dist/runtime/components/Integrations/RunPayloadInput.vue +27 -13
- package/dist/runtime/components/Integrations/RunResponseModal.vue +11 -10
- package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +0 -1
- package/dist/runtime/components/Integrations/RunsTable.vue +38 -16
- package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +0 -1
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +8 -7
- package/dist/runtime/components/Integrations/Sidebar.vue +14 -10
- package/dist/runtime/components/Integrations/StickyNoteView.d.vue.ts +14 -4
- package/dist/runtime/components/Integrations/StickyNoteView.vue +38 -23
- package/dist/runtime/components/Integrations/StickyNoteView.vue.d.ts +14 -4
- package/dist/runtime/components/Integrations/TemplateCard.d.vue.ts +18 -0
- package/dist/runtime/components/Integrations/TemplateCard.vue +119 -0
- package/dist/runtime/components/Integrations/TemplateCard.vue.d.ts +18 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.d.vue.ts +2 -2
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +16 -18
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue.d.ts +2 -2
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +34 -33
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +52 -67
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +8 -7
- package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +18 -4
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +29 -11
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +18 -4
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +20 -1
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +240 -116
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +20 -1
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +28 -43
- package/dist/runtime/components/Integrations/WorkflowIconPicker.d.vue.ts +19 -1
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue +17 -7
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue.d.ts +19 -1
- package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +4 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +198 -56
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +4 -0
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +56 -59
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue +28 -21
- package/dist/runtime/components/Integrations/WorkflowTagsInput.d.vue.ts +1 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue +15 -9
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue.d.ts +1 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +15 -10
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +50 -36
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +126 -48
- package/dist/runtime/composables/integrationsApi.js +4 -2
- package/dist/runtime/composables/useCredentialTypes.js +8 -6
- package/dist/runtime/composables/useIntegrationsAudit.js +4 -3
- package/dist/runtime/composables/useIntegrationsCredentials.js +10 -8
- package/dist/runtime/composables/useIntegrationsDeadLetters.js +7 -6
- package/dist/runtime/composables/useIntegrationsFocus.d.ts +12 -0
- package/dist/runtime/composables/useIntegrationsLocale.d.ts +26 -0
- package/dist/runtime/composables/useIntegrationsLocale.js +8 -0
- package/dist/runtime/composables/useIntegrationsNodes.js +7 -5
- package/dist/runtime/composables/useIntegrationsRealtime.d.ts +149 -0
- package/dist/runtime/composables/useIntegrationsRealtime.js +80 -0
- package/dist/runtime/composables/useIntegrationsRevisions.js +9 -7
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +1 -1
- package/dist/runtime/composables/useIntegrationsRuns.js +14 -7
- package/dist/runtime/composables/useIntegrationsSchedules.d.ts +4 -0
- package/dist/runtime/composables/useIntegrationsSchedules.js +10 -3
- package/dist/runtime/composables/useIntegrationsSecrets.js +14 -9
- package/dist/runtime/composables/useIntegrationsT.d.ts +35 -0
- package/dist/runtime/composables/useIntegrationsT.js +9 -0
- package/dist/runtime/composables/useIntegrationsTemplates.d.ts +3 -3
- package/dist/runtime/composables/useIntegrationsTemplates.js +28 -16
- package/dist/runtime/composables/useIntegrationsTriggers.js +10 -8
- package/dist/runtime/composables/useIntegrationsWorkflows.js +13 -7
- package/dist/runtime/composables/useLoadGate.d.ts +17 -0
- package/dist/runtime/composables/useLoadGate.js +8 -0
- package/dist/runtime/composables/useNodeConfigResolve.js +2 -1
- package/dist/runtime/data/branchReorder.d.ts +37 -0
- package/dist/runtime/data/branchReorder.js +71 -0
- package/dist/runtime/data/handleId.d.ts +23 -0
- package/dist/runtime/data/handleId.js +6 -0
- package/dist/runtime/data/integrationNodeCatalog.d.ts +41 -0
- package/dist/runtime/data/integrationNodeCatalog.js +14 -0
- package/dist/runtime/data/integrationTemplates.d.ts +48 -0
- package/dist/runtime/data/integrationTemplates.js +21 -0
- package/dist/runtime/data/integrationWorkflowSamples.js +1 -1
- package/dist/runtime/data/nodeIcons.d.ts +2 -0
- package/dist/runtime/data/nodeIcons.js +73 -0
- package/dist/runtime/data/nodeInputData.d.ts +16 -4
- package/dist/runtime/data/nodeInputData.js +4 -0
- package/dist/runtime/data/payloadForm.d.ts +9 -2
- package/dist/runtime/data/payloadForm.js +29 -4
- package/dist/runtime/data/portTone.d.ts +17 -0
- package/dist/runtime/data/portTone.js +7 -0
- package/dist/runtime/data/webhookAuth.d.ts +18 -0
- package/dist/runtime/data/webhookAuth.js +19 -0
- package/dist/runtime/data/workflowIconCatalog.js +4 -6
- package/dist/runtime/i18n/messages/de.json +1207 -0
- package/dist/runtime/i18n/messages/en.json +1207 -0
- package/dist/runtime/i18n/translate.d.ts +83 -0
- package/dist/runtime/i18n/translate.js +41 -0
- package/dist/runtime/pages/integrations/audit.vue +140 -37
- package/dist/runtime/pages/integrations/credentials/oauth-complete.vue +9 -6
- package/dist/runtime/pages/integrations/credentials.vue +180 -64
- package/dist/runtime/pages/integrations/index.vue +91 -92
- package/dist/runtime/pages/integrations/runs.vue +33 -21
- package/dist/runtime/pages/integrations/schedules.vue +88 -23
- package/dist/runtime/pages/integrations/secrets.vue +57 -35
- package/dist/runtime/pages/integrations/templates/[slug].vue +119 -88
- package/dist/runtime/pages/integrations/templates/index.vue +82 -103
- package/dist/runtime/pages/integrations/workflows/[id].vue +344 -91
- package/dist/runtime/pages/integrations/workflows/index.vue +23 -5
- package/dist/runtime/plugins/locale.d.ts +10 -0
- package/dist/runtime/plugins/locale.js +6 -0
- package/dist/runtime/plugins/realtime.client.d.ts +32 -0
- package/dist/runtime/plugins/realtime.client.js +4 -0
- package/dist/runtime/types/integrations.d.ts +65 -6
- package/dist/runtime/utils/apiError.d.ts +47 -0
- package/dist/runtime/utils/apiError.js +32 -0
- package/dist/runtime/utils/cockpitSources.d.ts +153 -0
- package/dist/runtime/utils/cockpitSources.js +14 -0
- package/dist/runtime/utils/credentialState.d.ts +24 -1
- package/dist/runtime/utils/credentialState.js +26 -11
- package/dist/runtime/utils/loadGate.d.ts +61 -0
- package/dist/runtime/utils/loadGate.js +22 -0
- package/dist/runtime/utils/localize.d.ts +46 -4
- package/dist/runtime/utils/localize.js +34 -7
- package/dist/runtime/utils/notify.d.ts +59 -0
- package/dist/runtime/utils/notify.js +21 -0
- package/dist/runtime/utils/pollBudget.d.ts +72 -0
- package/dist/runtime/utils/pollBudget.js +17 -0
- package/dist/runtime/utils/revenexxCredentialSource.d.ts +26 -0
- package/dist/runtime/utils/revenexxCredentialSource.js +8 -0
- package/dist/runtime/utils/schedule.d.ts +116 -0
- package/dist/runtime/utils/schedule.js +219 -0
- package/dist/runtime/utils/statusStyle.d.ts +26 -2
- package/dist/runtime/utils/statusStyle.js +9 -1
- package/dist/runtime/utils/validationFindings.d.ts +101 -0
- package/dist/runtime/utils/validationFindings.js +54 -0
- package/dist/runtime/utils/whenIdle.d.ts +42 -0
- package/dist/runtime/utils/whenIdle.js +12 -0
- package/dist/types.d.mts +2 -6
- package/package.json +10 -3
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, resolveComponent } from "vue";
|
|
3
|
+
import { RefreshCircle as Loader2, ClockCircle as Clock, Global as Webhook, Play, Bolt as Zap } from "#solar-icons";
|
|
4
|
+
import { templateCategoryLabel, templatePackageLabel } from "../../data/integrationTemplates";
|
|
5
|
+
import TemplateFlowPreview from "./TemplateFlowPreview.vue";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
template: { type: Object, required: true },
|
|
8
|
+
density: { type: String, required: true },
|
|
9
|
+
to: { type: String, required: false },
|
|
10
|
+
busy: { type: Boolean, required: false },
|
|
11
|
+
disabled: { type: Boolean, required: false }
|
|
12
|
+
});
|
|
13
|
+
const emit = defineEmits(["select"]);
|
|
14
|
+
const t = useIntegrationsT();
|
|
15
|
+
const NuxtLink = resolveComponent("NuxtLink");
|
|
16
|
+
const full = computed(() => props.density === "full");
|
|
17
|
+
const banner = computed(
|
|
18
|
+
() => full.value ? props.template.images.find((i) => i.category === "banner")?.src ?? null : null
|
|
19
|
+
);
|
|
20
|
+
const TRIGGER_ICON = { schedule: Clock, webhook: Webhook, manual: Play, event: Zap };
|
|
21
|
+
const TRIGGER_LABEL_KEY = {
|
|
22
|
+
schedule: "integration.templates.card.trigger.schedule",
|
|
23
|
+
webhook: "integration.templates.trigger.webhook",
|
|
24
|
+
manual: "integration.templates.trigger.manual",
|
|
25
|
+
event: "integration.templates.card.trigger.event"
|
|
26
|
+
};
|
|
27
|
+
function triggerTypeLabel(type) {
|
|
28
|
+
const key = TRIGGER_LABEL_KEY[type];
|
|
29
|
+
return key ? t(key) : type;
|
|
30
|
+
}
|
|
31
|
+
function levelDot(level) {
|
|
32
|
+
return level === "beginner" ? "bg-emerald-500" : level === "intermediate" ? "bg-amber-500" : "bg-rose-500";
|
|
33
|
+
}
|
|
34
|
+
const packageLabel = computed(() => templatePackageLabel(props.template));
|
|
35
|
+
const categoryLabel = computed(() => templateCategoryLabel(props.template.category));
|
|
36
|
+
const CHIP = "inline-flex items-center whitespace-nowrap rounded-full uppercase font-medium";
|
|
37
|
+
const chipSize = computed(() => full.value ? "px-2 py-0.5 text-xs" : "px-1.5 py-px text-[11px]");
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<component
|
|
42
|
+
:is="to ? NuxtLink : 'button'"
|
|
43
|
+
v-bind="to ? { to } : { type: 'button', disabled: disabled || busy }"
|
|
44
|
+
class="flex flex-col overflow-hidden rounded-lg border border-black/[0.06] bg-white text-left transition hover:border-black/20 hover:shadow-sm disabled:opacity-60"
|
|
45
|
+
@click="to ? void 0 : emit('select')"
|
|
46
|
+
>
|
|
47
|
+
<!-- The picture: the flow this template builds, drawn from its own
|
|
48
|
+
definition, or the publisher's banner where one ships. -->
|
|
49
|
+
<div
|
|
50
|
+
class="relative shrink-0 border-b border-black/[0.06] bg-slate-50/70 [background-image:radial-gradient(circle,rgba(15,23,42,0.07)_1px,transparent_1px)]"
|
|
51
|
+
:class="full ? 'h-36 [background-size:14px_14px]' : 'h-24 [background-size:12px_12px]'"
|
|
52
|
+
>
|
|
53
|
+
<img v-if="banner" :src="banner" alt="" class="h-full w-full object-cover">
|
|
54
|
+
<!-- `full` keeps its chips on the picture, so the drawing starts below
|
|
55
|
+
them: the graph is fitted to whichever axis binds, and a flow slightly
|
|
56
|
+
taller in proportion than this box reaches the top edge — where the
|
|
57
|
+
chip is. The 28px are the chip's own 20 plus its 8 of inset, so the
|
|
58
|
+
two can no longer meet (PO-243).
|
|
59
|
+
|
|
60
|
+
No horizontal padding, deliberately: all three surfaces used to pass
|
|
61
|
+
one (`px-2` in the gallery, `px-1` in the compact places) and none of
|
|
62
|
+
them insetted anything. The preview's `svg` is `absolute inset-0`, so
|
|
63
|
+
it is laid out against its parent's *padding box* and fills it whatever
|
|
64
|
+
the padding is — measured identical to the picture, 421.3px wide either
|
|
65
|
+
way. The graph's own inset is `TemplateFlowPreview`'s `padding` prop,
|
|
66
|
+
36 logical units, which is where it belongs. -->
|
|
67
|
+
<TemplateFlowPreview
|
|
68
|
+
v-else-if="template.detailLoaded"
|
|
69
|
+
:blob="template.blob"
|
|
70
|
+
:height="full ? 116 : 96"
|
|
71
|
+
:class="full ? 'mt-7' : ''"
|
|
72
|
+
/>
|
|
73
|
+
<!-- Named, because "still on its way" and "this template draws nothing"
|
|
74
|
+
are the same sight otherwise — and a spinner nobody can address is a
|
|
75
|
+
promise no test can hold to. -->
|
|
76
|
+
<div
|
|
77
|
+
v-else
|
|
78
|
+
role="status"
|
|
79
|
+
:aria-label="t('integration.templates.card.state.loadingFlow')"
|
|
80
|
+
class="flex h-full items-center justify-center"
|
|
81
|
+
>
|
|
82
|
+
<Loader2 :size="full ? 16 : 14" class="animate-spin text-muted-foreground/50" />
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div v-if="full" class="absolute left-2 top-2 flex items-center gap-1.5">
|
|
86
|
+
<span v-if="categoryLabel" :class="[CHIP, chipSize, 'bg-slate-100 text-slate-700']">{{ categoryLabel }}</span>
|
|
87
|
+
<span v-if="packageLabel" :class="[CHIP, chipSize, 'bg-violet-100 text-violet-700']">{{ packageLabel }}</span>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<Loader2 v-if="busy" :size="13" class="absolute right-1.5 top-1.5 animate-spin text-muted-foreground" />
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div class="flex min-h-0 flex-1 flex-col" :class="full ? 'p-4' : 'p-3'">
|
|
94
|
+
<div class="flex items-center gap-2">
|
|
95
|
+
<div class="min-w-0 flex-1 truncate text-sm font-semibold text-foreground">{{ template.name }}</div>
|
|
96
|
+
<!-- Compact has no room on the picture, so the category rides the name. -->
|
|
97
|
+
<span v-if="!full && categoryLabel" :class="[CHIP, chipSize, 'bg-slate-100 text-slate-700']">{{ categoryLabel }}</span>
|
|
98
|
+
</div>
|
|
99
|
+
<p class="mt-1 flex-1 text-sm text-muted-foreground line-clamp-2">{{ template.description }}</p>
|
|
100
|
+
|
|
101
|
+
<div v-if="full" class="mt-3 flex items-center gap-2 text-xs text-muted-foreground">
|
|
102
|
+
<span
|
|
103
|
+
v-for="triggerType in template.triggerTypes"
|
|
104
|
+
:key="triggerType"
|
|
105
|
+
class="inline-flex items-center gap-1 whitespace-nowrap rounded-full bg-slate-100 px-2 py-0.5 uppercase"
|
|
106
|
+
>
|
|
107
|
+
<component :is="TRIGGER_ICON[triggerType] ?? Zap" :size="10" />
|
|
108
|
+
{{ triggerTypeLabel(triggerType) }}
|
|
109
|
+
</span>
|
|
110
|
+
<span class="flex-1" />
|
|
111
|
+
<span class="inline-flex items-center gap-1 whitespace-nowrap rounded-full bg-slate-100 px-2 py-0.5 uppercase">
|
|
112
|
+
<span class="size-1.5 rounded-full" :class="levelDot(template.level)" />
|
|
113
|
+
{{ template.level }}
|
|
114
|
+
</span>
|
|
115
|
+
<span v-if="template.publisher.kind !== 'revenexx'" class="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 uppercase">{{ template.publisher.name }}</span>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</component>
|
|
119
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { WorkflowTemplate } from '../../types/integrations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
template: WorkflowTemplate;
|
|
4
|
+
/** How much room the surface has. See the comment above; no default on purpose. */
|
|
5
|
+
density: 'full' | 'compact';
|
|
6
|
+
/** Given → the card is a link there. Omitted → a button that emits `select`. */
|
|
7
|
+
to?: string;
|
|
8
|
+
/** This card is the one being acted on: it says so and cannot be pressed again. */
|
|
9
|
+
busy?: boolean;
|
|
10
|
+
/** Another card on the surface is being acted on, so this one is out of reach. */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
};
|
|
13
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
+
select: () => any;
|
|
15
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
|
+
onSelect?: (() => any) | undefined;
|
|
17
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
export default _default;
|
|
@@ -11,9 +11,9 @@ type __VLS_Props = {
|
|
|
11
11
|
*/
|
|
12
12
|
showErrorBranches?: boolean;
|
|
13
13
|
};
|
|
14
|
-
declare var
|
|
14
|
+
declare var __VLS_8: {};
|
|
15
15
|
type __VLS_Slots = {} & {
|
|
16
|
-
empty?: (props: typeof
|
|
16
|
+
empty?: (props: typeof __VLS_8) => any;
|
|
17
17
|
};
|
|
18
18
|
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
19
19
|
height: number;
|
|
@@ -3,13 +3,15 @@ import { computed } from "vue";
|
|
|
3
3
|
import * as Lucide from "lucide-vue-next";
|
|
4
4
|
import { findManifest, NODE_CATEGORIES, TRIGGER_TEMPLATES } from "../../data/integrationNodeCatalog";
|
|
5
5
|
import { resolveLocalized } from "../../utils/localize";
|
|
6
|
-
import
|
|
6
|
+
import { describeCron } from "../../utils/schedule";
|
|
7
|
+
import IntegrationsNodeMark from "./NodeMark.vue";
|
|
7
8
|
const props = defineProps({
|
|
8
9
|
blob: { type: [Object, null], required: true },
|
|
9
10
|
height: { type: Number, required: false, default: 144 },
|
|
10
11
|
padding: { type: Number, required: false, default: 36 },
|
|
11
12
|
showErrorBranches: { type: Boolean, required: false, default: false }
|
|
12
13
|
});
|
|
14
|
+
const t = useIntegrationsT();
|
|
13
15
|
const STOP_SLUG = "revenexx:stop-and-error";
|
|
14
16
|
const NODE_W = 220;
|
|
15
17
|
const NODE_H = 58;
|
|
@@ -20,20 +22,20 @@ const boxes = computed(() => {
|
|
|
20
22
|
if (!blob) return [];
|
|
21
23
|
const out = [];
|
|
22
24
|
const triggers = blob.triggers ?? [];
|
|
23
|
-
triggers.forEach((
|
|
24
|
-
const pos = blob.triggerPositions?.[
|
|
25
|
-
const template = TRIGGER_TEMPLATES.find((tt) => tt.type ===
|
|
26
|
-
const subtitle =
|
|
25
|
+
triggers.forEach((t2, i) => {
|
|
26
|
+
const pos = blob.triggerPositions?.[t2.id] ?? { x: 40, y: 40 + i * 160 };
|
|
27
|
+
const template = TRIGGER_TEMPLATES.find((tt) => tt.type === t2.type);
|
|
28
|
+
const subtitle = t2.type === "schedule" && t2.config?.cron ? describeCron(String(t2.config.cron)) ?? String(t2.config.cron) : t2.type === "webhook" && t2.config?.path ? String(t2.config.path) : resolveLocalized(template?.description ?? "");
|
|
27
29
|
out.push({
|
|
28
|
-
key: `t-${
|
|
30
|
+
key: `t-${t2.id}`,
|
|
29
31
|
kind: "trigger",
|
|
30
32
|
x: pos.x,
|
|
31
33
|
y: pos.y,
|
|
32
34
|
w: TRIG_W,
|
|
33
35
|
h: TRIG_H,
|
|
34
|
-
label: typeof
|
|
36
|
+
label: typeof t2.name === "string" && t2.name || t2.type.charAt(0).toUpperCase() + t2.type.slice(1),
|
|
35
37
|
subtitle,
|
|
36
|
-
type:
|
|
38
|
+
type: t2.type,
|
|
37
39
|
manifest: null,
|
|
38
40
|
icon: iconFor(template?.icon ?? "Zap")
|
|
39
41
|
});
|
|
@@ -59,9 +61,6 @@ const boxes = computed(() => {
|
|
|
59
61
|
});
|
|
60
62
|
return out;
|
|
61
63
|
});
|
|
62
|
-
function hasLogo(m) {
|
|
63
|
-
return (m?.images ?? []).some((i) => i.category === "logo");
|
|
64
|
-
}
|
|
65
64
|
function prettify(slug) {
|
|
66
65
|
const tail = slug.includes(":") ? slug.split(":").pop() : slug;
|
|
67
66
|
return tail.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" ");
|
|
@@ -100,8 +99,8 @@ const edgePaths = computed(() => {
|
|
|
100
99
|
});
|
|
101
100
|
const EDGE_STROKE = {
|
|
102
101
|
default: "#94a3b8",
|
|
103
|
-
trigger: "#
|
|
104
|
-
error: "#
|
|
102
|
+
trigger: "#94a3b8",
|
|
103
|
+
error: "#cbd5e1"
|
|
105
104
|
};
|
|
106
105
|
const bounds = computed(() => {
|
|
107
106
|
if (!boxes.value.length) return { x: 0, y: 0, w: 1, h: 1 };
|
|
@@ -171,7 +170,7 @@ const bounds = computed(() => {
|
|
|
171
170
|
</div>
|
|
172
171
|
</div>
|
|
173
172
|
<div class="rounded-b-md border-t border-emerald-500/15 bg-emerald-500/[0.04] px-3 py-1 text-mono font-semibold text-emerald-700/80">
|
|
174
|
-
|
|
173
|
+
{{ t("integration.templates.preview.triggerLabel") }} · {{ b.type }}
|
|
175
174
|
</div>
|
|
176
175
|
</div>
|
|
177
176
|
|
|
@@ -182,10 +181,9 @@ const bounds = computed(() => {
|
|
|
182
181
|
>
|
|
183
182
|
<span
|
|
184
183
|
class="flex size-8 shrink-0 items-center justify-center rounded-md"
|
|
185
|
-
:class="
|
|
184
|
+
:class="b.categoryColor"
|
|
186
185
|
>
|
|
187
|
-
<
|
|
188
|
-
<component :is="b.icon" v-else :size="15" :stroke-width="2.25" />
|
|
186
|
+
<IntegrationsNodeMark :manifest="b.manifest" :size="18" />
|
|
189
187
|
</span>
|
|
190
188
|
<div class="min-w-0 flex-1">
|
|
191
189
|
<div class="truncate text-sm font-semibold leading-tight text-foreground">{{ b.label }}</div>
|
|
@@ -195,7 +193,7 @@ const bounds = computed(() => {
|
|
|
195
193
|
</foreignObject>
|
|
196
194
|
</svg>
|
|
197
195
|
<div v-else class="flex h-full items-center justify-center text-sm text-muted-foreground">
|
|
198
|
-
<slot name="empty">
|
|
196
|
+
<slot name="empty">{{ t("integration.templates.preview.state.loading") }}</slot>
|
|
199
197
|
</div>
|
|
200
198
|
</div>
|
|
201
199
|
</template>
|
|
@@ -11,9 +11,9 @@ type __VLS_Props = {
|
|
|
11
11
|
*/
|
|
12
12
|
showErrorBranches?: boolean;
|
|
13
13
|
};
|
|
14
|
-
declare var
|
|
14
|
+
declare var __VLS_8: {};
|
|
15
15
|
type __VLS_Slots = {} & {
|
|
16
|
-
empty?: (props: typeof
|
|
16
|
+
empty?: (props: typeof __VLS_8) => any;
|
|
17
17
|
};
|
|
18
18
|
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
19
19
|
height: number;
|
|
@@ -17,23 +17,24 @@ const props = defineProps({
|
|
|
17
17
|
runBusy: { type: Boolean, required: false }
|
|
18
18
|
});
|
|
19
19
|
const emit = defineEmits(["action", "update:open"]);
|
|
20
|
+
const t = useIntegrationsT();
|
|
20
21
|
const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "");
|
|
21
22
|
function formatShortcut(tokens) {
|
|
22
23
|
const parts = tokens.split("+");
|
|
23
24
|
const out = [];
|
|
24
25
|
for (const raw of parts) {
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
else if (
|
|
28
|
-
else if (
|
|
29
|
-
else if (
|
|
30
|
-
else if (
|
|
31
|
-
else if (
|
|
32
|
-
else if (
|
|
33
|
-
else if (
|
|
34
|
-
else if (
|
|
35
|
-
else if (
|
|
36
|
-
else out.push(
|
|
26
|
+
const t2 = raw.toLowerCase();
|
|
27
|
+
if (t2 === "mod") out.push(isMac ? "\u2318" : "Ctrl");
|
|
28
|
+
else if (t2 === "shift") out.push("\u21E7");
|
|
29
|
+
else if (t2 === "alt") out.push(isMac ? "\u2325" : "Alt");
|
|
30
|
+
else if (t2 === "enter") out.push("\u21B5");
|
|
31
|
+
else if (t2 === "backspace") out.push("\u232B");
|
|
32
|
+
else if (t2 === "delete") out.push("Del");
|
|
33
|
+
else if (t2 === "escape") out.push("Esc");
|
|
34
|
+
else if (t2 === "tab") out.push("Tab");
|
|
35
|
+
else if (t2 === "space") out.push("Space");
|
|
36
|
+
else if (t2 === "f2") out.push("F2");
|
|
37
|
+
else out.push(t2.toUpperCase());
|
|
37
38
|
}
|
|
38
39
|
return isMac ? out.join("") : out.join("+");
|
|
39
40
|
}
|
|
@@ -42,19 +43,19 @@ const sections = computed(() => {
|
|
|
42
43
|
if (props.kind === "node") {
|
|
43
44
|
return [
|
|
44
45
|
[
|
|
45
|
-
{ id: "open", label: "
|
|
46
|
-
{ id: "rename", label: "
|
|
46
|
+
{ id: "open", label: t("integration.canvas.contextMenu.item.open"), shortcut: "enter" },
|
|
47
|
+
{ id: "rename", label: t("integration.canvas.contextMenu.item.rename"), shortcut: "f2" }
|
|
47
48
|
],
|
|
48
49
|
[
|
|
49
|
-
{ id: "copy", label: "
|
|
50
|
-
{ id: "duplicate", label: "
|
|
50
|
+
{ id: "copy", label: t("integration.canvas.contextMenu.item.copy"), shortcut: "mod+c", disabled: props.targetIsTrigger },
|
|
51
|
+
{ id: "duplicate", label: t("integration.canvas.contextMenu.item.duplicate"), shortcut: "mod+d", disabled: props.targetIsTrigger }
|
|
51
52
|
],
|
|
52
53
|
[
|
|
53
|
-
{ id: "run", label: "
|
|
54
|
-
{ id: "tidy-up", label: "
|
|
54
|
+
{ id: "run", label: t("integration.canvas.contextMenu.item.runWorkflow"), shortcut: "mod+enter", disabled: props.runBusy },
|
|
55
|
+
{ id: "tidy-up", label: t("integration.canvas.contextMenu.item.tidyUp"), shortcut: "shift+alt+t" }
|
|
55
56
|
],
|
|
56
57
|
[
|
|
57
|
-
{ id: "delete", label: "
|
|
58
|
+
{ id: "delete", label: t("integration.common.action.delete"), shortcut: "backspace", danger: true }
|
|
58
59
|
]
|
|
59
60
|
];
|
|
60
61
|
}
|
|
@@ -62,37 +63,37 @@ const sections = computed(() => {
|
|
|
62
63
|
const n = props.selectionCount;
|
|
63
64
|
return [
|
|
64
65
|
[
|
|
65
|
-
{ id: "copy", label:
|
|
66
|
-
{ id: "duplicate", label:
|
|
66
|
+
{ id: "copy", label: t("integration.canvas.contextMenu.item.copyNodes", n), shortcut: "mod+c" },
|
|
67
|
+
{ id: "duplicate", label: t("integration.canvas.contextMenu.item.duplicateNodes", n), shortcut: "mod+d" }
|
|
67
68
|
],
|
|
68
69
|
[
|
|
69
|
-
{ id: "group", label:
|
|
70
|
-
{ id: "tidy-up", label: "
|
|
71
|
-
{ id: "select-all", label: "
|
|
72
|
-
{ id: "clear-selection", label: "
|
|
70
|
+
{ id: "group", label: t("integration.canvas.contextMenu.item.groupNodes", n), shortcut: "mod+g" },
|
|
71
|
+
{ id: "tidy-up", label: t("integration.canvas.contextMenu.item.tidyUp"), shortcut: "shift+alt+t" },
|
|
72
|
+
{ id: "select-all", label: t("integration.canvas.contextMenu.item.selectAll"), shortcut: "mod+a", disabled: allSelected.value },
|
|
73
|
+
{ id: "clear-selection", label: t("integration.canvas.contextMenu.item.clearSelection"), shortcut: "escape" }
|
|
73
74
|
],
|
|
74
75
|
[
|
|
75
|
-
{ id: "delete", label:
|
|
76
|
+
{ id: "delete", label: t("integration.canvas.contextMenu.item.deleteNodes", n), shortcut: "backspace", danger: true }
|
|
76
77
|
]
|
|
77
78
|
];
|
|
78
79
|
}
|
|
79
80
|
return [
|
|
80
81
|
[
|
|
81
|
-
{ id: "add-node", label: "
|
|
82
|
-
{ id: "add-sticky", label: "
|
|
83
|
-
{ id: "paste", label: "
|
|
82
|
+
{ id: "add-node", label: t("integration.canvas.contextMenu.item.addNode"), shortcut: "tab" },
|
|
83
|
+
{ id: "add-sticky", label: t("integration.canvas.contextMenu.item.addSticky"), shortcut: "shift+s" },
|
|
84
|
+
{ id: "paste", label: t("integration.canvas.contextMenu.item.paste"), shortcut: "mod+v" }
|
|
84
85
|
],
|
|
85
86
|
[
|
|
86
|
-
{ id: "tidy-up", label: "
|
|
87
|
-
{ id: "fit-view", label: "
|
|
87
|
+
{ id: "tidy-up", label: t("integration.canvas.contextMenu.item.tidyUp"), shortcut: "shift+alt+t" },
|
|
88
|
+
{ id: "fit-view", label: t("integration.canvas.contextMenu.item.fitView"), shortcut: "1" }
|
|
88
89
|
],
|
|
89
90
|
[
|
|
90
|
-
{ id: "select-all", label: "
|
|
91
|
+
{ id: "select-all", label: t("integration.canvas.contextMenu.item.selectAll"), shortcut: "mod+a", disabled: allSelected.value || props.totalNodes === 0 }
|
|
91
92
|
]
|
|
92
93
|
];
|
|
93
94
|
});
|
|
94
95
|
const headerLabel = computed(
|
|
95
|
-
() => props.kind === "selection" ?
|
|
96
|
+
() => props.kind === "selection" ? t("integration.canvas.contextMenu.header.selectionCount", props.selectionCount) : null
|
|
96
97
|
);
|
|
97
98
|
function onSelect(item) {
|
|
98
99
|
if (item.disabled) return;
|