@nvent-addon/app 0.4.5 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.d.mts +19 -1
- package/dist/module.mjs +20 -8
- package/dist/runtime/app/components/{nhealth/component-router.d.vue.ts → ComponentRouter.d.vue.ts} +1 -5
- package/dist/runtime/app/components/{nhealth/component-router.vue.d.ts → ComponentRouter.vue.d.ts} +1 -5
- package/dist/runtime/app/components/{nhealth/component-shell.d.vue.ts → ComponentShell.d.vue.ts} +4 -9
- package/dist/runtime/app/components/ComponentShell.vue +87 -0
- package/dist/runtime/app/components/{nhealth/component-shell.vue.d.ts → ComponentShell.vue.d.ts} +4 -9
- package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +1 -6
- package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +1 -6
- package/dist/runtime/app/components/ListItem.d.vue.ts +3 -6
- package/dist/runtime/app/components/ListItem.vue.d.ts +3 -6
- package/dist/runtime/app/components/LiveIndicator.d.vue.ts +7 -0
- package/dist/runtime/app/components/LiveIndicator.vue +30 -0
- package/dist/runtime/app/components/LiveIndicator.vue.d.ts +7 -0
- package/dist/runtime/app/components/{QueueConfigDetails.d.vue.ts → QueueConfiguration.d.vue.ts} +1 -10
- package/dist/runtime/app/components/QueueConfiguration.vue +387 -0
- package/dist/runtime/app/components/{QueueConfigDetails.vue.d.ts → QueueConfiguration.vue.d.ts} +1 -10
- package/dist/runtime/app/components/StatCard.d.vue.ts +9 -0
- package/dist/runtime/app/components/StatCard.vue +57 -0
- package/dist/runtime/app/components/StatCard.vue.d.ts +9 -0
- package/dist/runtime/app/components/TimelineList.vue +67 -0
- package/dist/runtime/app/components/flow/AwaitNode.d.vue.ts +18 -0
- package/dist/runtime/app/components/flow/AwaitNode.vue +91 -0
- package/dist/runtime/app/components/flow/AwaitNode.vue.d.ts +18 -0
- package/dist/runtime/app/components/{FlowDiagram.d.vue.ts → flow/Diagram.d.vue.ts} +12 -1
- package/dist/runtime/app/components/{FlowDiagram.vue → flow/Diagram.vue} +92 -11
- package/dist/runtime/app/components/{FlowDiagram.vue.d.ts → flow/Diagram.vue.d.ts} +12 -1
- package/dist/runtime/app/components/{FlowRunOverview.d.vue.ts → flow/RunOverview.d.vue.ts} +3 -0
- package/dist/runtime/app/components/{FlowRunOverview.vue → flow/RunOverview.vue} +94 -8
- package/dist/runtime/app/components/{FlowRunOverview.vue.d.ts → flow/RunOverview.vue.d.ts} +3 -0
- package/dist/runtime/app/components/{FlowRunStatusBadge.d.vue.ts → flow/RunStatusBadge.d.vue.ts} +2 -8
- package/dist/runtime/app/components/{FlowRunStatusBadge.vue → flow/RunStatusBadge.vue} +8 -1
- package/dist/runtime/app/components/{FlowRunStatusBadge.vue.d.ts → flow/RunStatusBadge.vue.d.ts} +2 -8
- package/dist/runtime/app/components/{FlowRunTimeline.vue → flow/RunTimeline.vue} +1 -1
- package/dist/runtime/app/components/{FlowStepSelector.d.vue.ts → flow/StepSelector.d.vue.ts} +1 -0
- package/dist/runtime/app/components/flow/StepSelector.vue +553 -0
- package/dist/runtime/app/components/{FlowStepSelector.vue.d.ts → flow/StepSelector.vue.d.ts} +1 -0
- package/dist/runtime/app/components/trigger/BasicInfoCard.d.vue.ts +33 -0
- package/dist/runtime/app/components/trigger/BasicInfoCard.vue +168 -0
- package/dist/runtime/app/components/trigger/BasicInfoCard.vue.d.ts +33 -0
- package/dist/runtime/app/components/{FlowSchedulesList.d.vue.ts → trigger/DangerZone.d.vue.ts} +4 -6
- package/dist/runtime/app/components/trigger/DangerZone.vue +46 -0
- package/dist/runtime/app/components/{FlowSchedulesList.vue.d.ts → trigger/DangerZone.vue.d.ts} +4 -6
- package/dist/runtime/app/components/trigger/EditHeader.d.vue.ts +15 -0
- package/dist/runtime/app/components/trigger/EditHeader.vue +55 -0
- package/dist/runtime/app/components/trigger/EditHeader.vue.d.ts +15 -0
- package/dist/runtime/app/components/trigger/EventConfig.d.vue.ts +24 -0
- package/dist/runtime/app/components/trigger/EventConfig.vue +68 -0
- package/dist/runtime/app/components/trigger/EventConfig.vue.d.ts +24 -0
- package/dist/runtime/app/components/trigger/FlowSubscriptions.d.vue.ts +14 -0
- package/dist/runtime/app/components/trigger/FlowSubscriptions.vue +128 -0
- package/dist/runtime/app/components/trigger/FlowSubscriptions.vue.d.ts +14 -0
- package/dist/runtime/app/components/trigger/ScheduleConfig.d.vue.ts +27 -0
- package/dist/runtime/app/components/trigger/ScheduleConfig.vue +375 -0
- package/dist/runtime/app/components/trigger/ScheduleConfig.vue.d.ts +27 -0
- package/dist/runtime/app/components/{FlowScheduleDialog.d.vue.ts → trigger/StatusConfig.d.vue.ts} +6 -6
- package/dist/runtime/app/components/trigger/StatusConfig.vue +78 -0
- package/dist/runtime/app/components/{FlowScheduleDialog.vue.d.ts → trigger/StatusConfig.vue.d.ts} +6 -6
- package/dist/runtime/app/components/trigger/WebhookConfig.d.vue.ts +30 -0
- package/dist/runtime/app/components/trigger/WebhookConfig.vue +97 -0
- package/dist/runtime/app/components/trigger/WebhookConfig.vue.d.ts +30 -0
- package/dist/runtime/app/composables/useAnalyzedFlows.d.ts +5 -0
- package/dist/runtime/app/composables/useAnalyzedFlows.js +15 -1
- package/dist/runtime/app/composables/useComponentRouter.d.ts +8 -0
- package/dist/runtime/app/composables/useComponentRouter.js +10 -2
- package/dist/runtime/app/composables/useFlowRunsInfinite.d.ts +1 -1
- package/dist/runtime/app/composables/useFlowState.js +65 -0
- package/dist/runtime/app/composables/useFlowWebSocket.d.ts +11 -2
- package/dist/runtime/app/composables/useFlowWebSocket.js +181 -65
- package/dist/runtime/app/composables/useQueueJobs.d.ts +12 -1
- package/dist/runtime/app/composables/useQueueJobs.js +13 -7
- package/dist/runtime/app/composables/useTrigger.d.ts +137 -0
- package/dist/runtime/app/composables/useTrigger.js +116 -0
- package/dist/runtime/app/composables/useTriggerWebSocket.d.ts +35 -0
- package/dist/runtime/app/composables/useTriggerWebSocket.js +333 -0
- package/dist/runtime/app/pages/dashboard.d.vue.ts +3 -0
- package/dist/runtime/app/pages/dashboard.vue +738 -0
- package/dist/runtime/app/pages/dashboard.vue.d.ts +3 -0
- package/dist/runtime/app/pages/flows/[name].d.vue.ts +3 -0
- package/dist/runtime/app/pages/flows/[name].vue +680 -0
- package/dist/runtime/app/pages/flows/[name].vue.d.ts +3 -0
- package/dist/runtime/app/pages/flows/index.vue +321 -620
- package/dist/runtime/app/pages/index.vue +39 -9
- package/dist/runtime/app/pages/queues/index.vue +202 -194
- package/dist/runtime/app/pages/queues/jobs.vue +534 -207
- package/dist/runtime/app/pages/settings/scheduler.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/scheduler.vue +310 -0
- package/dist/runtime/app/pages/settings/scheduler.vue.d.ts +3 -0
- package/dist/runtime/app/pages/triggers/[name]/edit.d.vue.ts +3 -0
- package/dist/runtime/app/pages/triggers/[name]/edit.vue +429 -0
- package/dist/runtime/app/pages/triggers/[name]/edit.vue.d.ts +3 -0
- package/dist/runtime/app/pages/triggers/[name].d.vue.ts +3 -0
- package/dist/runtime/app/pages/triggers/[name].vue +898 -0
- package/dist/runtime/app/pages/triggers/[name].vue.d.ts +3 -0
- package/dist/runtime/app/pages/triggers/index.d.vue.ts +3 -0
- package/dist/runtime/app/pages/triggers/index.vue +528 -0
- package/dist/runtime/app/pages/triggers/index.vue.d.ts +3 -0
- package/dist/runtime/app/pages/triggers/new.d.vue.ts +3 -0
- package/dist/runtime/app/pages/triggers/new.vue +610 -0
- package/dist/runtime/app/pages/triggers/new.vue.d.ts +3 -0
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +10 -0
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +49 -0
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +2 -0
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +21 -0
- package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +17 -0
- package/dist/runtime/server/api/_flows/[name]/runs.get.js +64 -0
- package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +2 -0
- package/dist/runtime/server/api/_flows/[name]/start.post.js +9 -0
- package/dist/runtime/server/api/_flows/index.get.d.ts +7 -0
- package/dist/runtime/server/api/_flows/index.get.js +5 -0
- package/dist/runtime/server/api/_flows/recent-runs.get.d.ts +15 -0
- package/dist/runtime/server/api/_flows/recent-runs.get.js +67 -0
- package/dist/runtime/server/api/_flows/ws.d.ts +80 -0
- package/dist/runtime/server/api/_flows/ws.js +309 -0
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +2 -0
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +14 -0
- package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +2 -0
- package/dist/runtime/server/api/_queues/[name]/job/index.get.js +39 -0
- package/dist/runtime/server/api/_queues/index.get.d.ts +2 -0
- package/dist/runtime/server/api/_queues/index.get.js +106 -0
- package/dist/runtime/server/api/_queues/ws.d.ts +48 -0
- package/dist/runtime/server/api/_queues/ws.js +215 -0
- package/dist/runtime/server/api/_scheduler/jobs.get.d.ts +19 -0
- package/dist/runtime/server/api/_scheduler/jobs.get.js +36 -0
- package/dist/runtime/server/api/_triggers/[name]/events.get.d.ts +6 -0
- package/dist/runtime/server/api/_triggers/[name]/events.get.js +43 -0
- package/dist/runtime/server/api/_triggers/[name]/index.get.d.ts +6 -0
- package/dist/runtime/server/api/_triggers/[name]/index.get.js +76 -0
- package/dist/runtime/server/api/_triggers/[name].delete.d.ts +7 -0
- package/dist/runtime/server/api/_triggers/[name].delete.js +37 -0
- package/dist/runtime/server/api/_triggers/[name].patch.d.ts +7 -0
- package/dist/runtime/server/api/_triggers/[name].patch.js +117 -0
- package/dist/runtime/server/api/_triggers/index.get.d.ts +6 -0
- package/dist/runtime/server/api/_triggers/index.get.js +44 -0
- package/dist/runtime/server/api/_triggers/index.post.d.ts +7 -0
- package/dist/runtime/server/api/_triggers/index.post.js +124 -0
- package/dist/runtime/server/api/_triggers/stats.get.d.ts +6 -0
- package/dist/runtime/server/api/_triggers/stats.get.js +41 -0
- package/dist/runtime/server/api/_triggers/ws.d.ts +74 -0
- package/dist/runtime/server/api/_triggers/ws.js +315 -0
- package/dist/runtime/server/tsconfig.json +7 -0
- package/package.json +8 -8
- package/dist/runtime/app/components/FlowScheduleDialog.vue +0 -226
- package/dist/runtime/app/components/FlowSchedulesList.vue +0 -99
- package/dist/runtime/app/components/FlowStepSelector.vue +0 -238
- package/dist/runtime/app/components/QueueConfigDetails.vue +0 -412
- package/dist/runtime/app/components/nhealth/component-shell.vue +0 -89
- /package/dist/runtime/app/components/{nhealth/component-router.vue → ComponentRouter.vue} +0 -0
- /package/dist/runtime/app/components/{FlowNodeCard.d.vue.ts → flow/NodeCard.d.vue.ts} +0 -0
- /package/dist/runtime/app/components/{FlowNodeCard.vue → flow/NodeCard.vue} +0 -0
- /package/dist/runtime/app/components/{FlowNodeCard.vue.d.ts → flow/NodeCard.vue.d.ts} +0 -0
- /package/dist/runtime/app/components/{FlowRunTimeline.d.vue.ts → flow/RunTimeline.d.vue.ts} +0 -0
- /package/dist/runtime/app/components/{FlowRunTimeline.vue.d.ts → flow/RunTimeline.vue.d.ts} +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="px-3 py-2 rounded-lg border-2 min-w-[180px] bg-white dark:bg-gray-900 transition-all duration-300"
|
|
4
|
+
:class="borderClass"
|
|
5
|
+
>
|
|
6
|
+
<div class="flex items-center justify-between gap-2 text-xs mb-2">
|
|
7
|
+
<div class="flex items-center gap-2">
|
|
8
|
+
<UIcon
|
|
9
|
+
:name="getAwaitIcon(data.awaitType)"
|
|
10
|
+
class="w-3.5 h-3.5"
|
|
11
|
+
/>
|
|
12
|
+
<span class="font-medium text-gray-700 dark:text-gray-300">
|
|
13
|
+
{{ data.label }}
|
|
14
|
+
</span>
|
|
15
|
+
</div>
|
|
16
|
+
<UBadge
|
|
17
|
+
:label="statusLabel"
|
|
18
|
+
size="xs"
|
|
19
|
+
:color="statusColor"
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
22
|
+
<div
|
|
23
|
+
v-if="data.awaitConfig"
|
|
24
|
+
class="text-[10px] text-gray-500 dark:text-gray-400"
|
|
25
|
+
>
|
|
26
|
+
<div v-if="data.awaitType === 'time'">
|
|
27
|
+
Delay: {{ formatDelay(data.awaitConfig.delay) }}
|
|
28
|
+
</div>
|
|
29
|
+
<div v-else-if="data.awaitType === 'event'">
|
|
30
|
+
Event: {{ data.awaitConfig.event }}
|
|
31
|
+
</div>
|
|
32
|
+
<div v-else-if="data.awaitType === 'webhook'">
|
|
33
|
+
Webhook: {{ data.awaitConfig.method || "POST" }}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script setup>
|
|
40
|
+
import { computed } from "#imports";
|
|
41
|
+
import { UIcon, UBadge } from "#components";
|
|
42
|
+
const props = defineProps({
|
|
43
|
+
data: { type: Object, required: true }
|
|
44
|
+
});
|
|
45
|
+
const statusLabel = computed(() => {
|
|
46
|
+
return (props.data.status || "idle").toUpperCase();
|
|
47
|
+
});
|
|
48
|
+
const statusColor = computed(() => {
|
|
49
|
+
switch (props.data.status) {
|
|
50
|
+
case "waiting":
|
|
51
|
+
return "warning";
|
|
52
|
+
case "resolved":
|
|
53
|
+
return "success";
|
|
54
|
+
case "timeout":
|
|
55
|
+
return "error";
|
|
56
|
+
default:
|
|
57
|
+
return "neutral";
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const borderClass = computed(() => {
|
|
61
|
+
switch (props.data.status) {
|
|
62
|
+
case "waiting":
|
|
63
|
+
return "border-amber-400 dark:border-amber-500 bg-amber-50 dark:bg-amber-950/20";
|
|
64
|
+
case "resolved":
|
|
65
|
+
return "border-emerald-400 dark:border-emerald-500 bg-emerald-50 dark:bg-emerald-950/20";
|
|
66
|
+
case "timeout":
|
|
67
|
+
return "border-red-400 dark:border-red-500 bg-red-50 dark:bg-red-950/20";
|
|
68
|
+
default:
|
|
69
|
+
return "border-gray-300 dark:border-gray-700";
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
function getAwaitIcon(type) {
|
|
73
|
+
switch (type) {
|
|
74
|
+
case "time":
|
|
75
|
+
return "i-lucide-clock";
|
|
76
|
+
case "event":
|
|
77
|
+
return "i-lucide-zap";
|
|
78
|
+
case "webhook":
|
|
79
|
+
return "i-lucide-webhook";
|
|
80
|
+
default:
|
|
81
|
+
return "i-lucide-clock";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function formatDelay(ms) {
|
|
85
|
+
if (!ms) return "0ms";
|
|
86
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
87
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
88
|
+
if (ms < 36e5) return `${(ms / 6e4).toFixed(1)}m`;
|
|
89
|
+
return `${(ms / 36e5).toFixed(1)}h`;
|
|
90
|
+
}
|
|
91
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface AwaitConfig {
|
|
2
|
+
type?: 'time' | 'event' | 'webhook';
|
|
3
|
+
delay?: number;
|
|
4
|
+
event?: string;
|
|
5
|
+
method?: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}
|
|
8
|
+
type __VLS_Props = {
|
|
9
|
+
data: {
|
|
10
|
+
label: string;
|
|
11
|
+
awaitType?: 'time' | 'event' | 'webhook';
|
|
12
|
+
awaitConfig?: AwaitConfig;
|
|
13
|
+
status?: 'idle' | 'waiting' | 'resolved' | 'timeout';
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
interface AwaitConfig {
|
|
2
|
+
type: 'time' | 'event' | 'webhook';
|
|
3
|
+
delay?: number;
|
|
4
|
+
event?: string;
|
|
5
|
+
method?: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
timeoutAction?: 'fail' | 'continue';
|
|
8
|
+
}
|
|
1
9
|
interface FlowEntry {
|
|
2
10
|
step: string;
|
|
3
11
|
queue: string;
|
|
@@ -5,6 +13,7 @@ interface FlowEntry {
|
|
|
5
13
|
runtime?: 'nodejs' | 'python';
|
|
6
14
|
runtype?: 'inprocess' | 'task';
|
|
7
15
|
emits?: string[];
|
|
16
|
+
awaitAfter?: AwaitConfig;
|
|
8
17
|
}
|
|
9
18
|
interface FlowStep {
|
|
10
19
|
queue: string;
|
|
@@ -13,6 +22,8 @@ interface FlowStep {
|
|
|
13
22
|
runtime?: 'nodejs' | 'python';
|
|
14
23
|
runtype?: 'inprocess' | 'task';
|
|
15
24
|
emits?: string[];
|
|
25
|
+
awaitBefore?: AwaitConfig;
|
|
26
|
+
awaitAfter?: AwaitConfig;
|
|
16
27
|
}
|
|
17
28
|
interface AnalyzedStep extends FlowStep {
|
|
18
29
|
name: string;
|
|
@@ -42,7 +53,7 @@ type __VLS_Props = {
|
|
|
42
53
|
showMiniMap?: boolean;
|
|
43
54
|
showBackground?: boolean;
|
|
44
55
|
stepStates?: Record<string, StepStatus>;
|
|
45
|
-
flowStatus?: 'running' | 'completed' | 'failed' | 'canceled';
|
|
56
|
+
flowStatus?: 'running' | 'completed' | 'failed' | 'canceled' | 'stalled';
|
|
46
57
|
};
|
|
47
58
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
48
59
|
nodeSelected: (payload: {
|
|
@@ -52,6 +52,20 @@
|
|
|
52
52
|
/>
|
|
53
53
|
</template>
|
|
54
54
|
|
|
55
|
+
<template #node-flow-await="{ data }">
|
|
56
|
+
<FlowAwaitNode
|
|
57
|
+
:data="data"
|
|
58
|
+
/>
|
|
59
|
+
<Handle
|
|
60
|
+
type="target"
|
|
61
|
+
:position="Position.Top"
|
|
62
|
+
/>
|
|
63
|
+
<Handle
|
|
64
|
+
type="source"
|
|
65
|
+
:position="Position.Bottom"
|
|
66
|
+
/>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
55
69
|
<Background
|
|
56
70
|
v-if="showBackground"
|
|
57
71
|
pattern-color="#888"
|
|
@@ -68,7 +82,8 @@
|
|
|
68
82
|
<script setup>
|
|
69
83
|
import { computed, ref, watch, nextTick } from "#imports";
|
|
70
84
|
import { Handle, Position } from "@vue-flow/core";
|
|
71
|
-
import FlowNodeCard from "
|
|
85
|
+
import FlowNodeCard from "./NodeCard.vue";
|
|
86
|
+
import FlowAwaitNode from "./AwaitNode.vue";
|
|
72
87
|
const props = defineProps({
|
|
73
88
|
flow: { type: [Object, null], required: false },
|
|
74
89
|
heightClass: { type: String, required: false },
|
|
@@ -190,7 +205,50 @@ const nodes = computed(() => {
|
|
|
190
205
|
});
|
|
191
206
|
});
|
|
192
207
|
}
|
|
193
|
-
|
|
208
|
+
const awaitNodes = [];
|
|
209
|
+
const awaitGap = 70;
|
|
210
|
+
if (f.entry?.awaitAfter && f.entry) {
|
|
211
|
+
const entryNode = out.find((n) => n.id === `entry:${f.entry.step}`);
|
|
212
|
+
if (entryNode) {
|
|
213
|
+
const awaitKey = `${f.entry.step}:await-after`;
|
|
214
|
+
const awaitState = states[awaitKey];
|
|
215
|
+
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
216
|
+
awaitNodes.push({
|
|
217
|
+
id: `await:entry-after:${f.entry.step}`,
|
|
218
|
+
position: { x: -90, y: entryNode.position.y + rowHeight + awaitGap },
|
|
219
|
+
data: {
|
|
220
|
+
label: `Await (${f.entry.awaitAfter.type})`,
|
|
221
|
+
awaitType: f.entry.awaitAfter.type,
|
|
222
|
+
awaitConfig: f.entry.awaitAfter,
|
|
223
|
+
status: awaitStatus
|
|
224
|
+
},
|
|
225
|
+
type: "flow-await",
|
|
226
|
+
style: { minWidth: "180px" }
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
Object.entries(steps).forEach(([stepName, step]) => {
|
|
231
|
+
if (step.awaitBefore) {
|
|
232
|
+
const stepNode = out.find((n) => n.id === `step:${stepName}`);
|
|
233
|
+
if (stepNode) {
|
|
234
|
+
const awaitState = states[`${stepName}:await-before`];
|
|
235
|
+
const awaitStatus = awaitState?.status === "waiting" ? "waiting" : awaitState?.status === "completed" ? "resolved" : awaitState?.status === "timeout" ? "timeout" : "idle";
|
|
236
|
+
awaitNodes.push({
|
|
237
|
+
id: `await:step-before:${stepName}`,
|
|
238
|
+
position: { x: stepNode.position.x + 20, y: stepNode.position.y - awaitGap - 50 },
|
|
239
|
+
data: {
|
|
240
|
+
label: `Await (${step.awaitBefore.type})`,
|
|
241
|
+
awaitType: step.awaitBefore.type,
|
|
242
|
+
awaitConfig: step.awaitBefore,
|
|
243
|
+
status: awaitStatus
|
|
244
|
+
},
|
|
245
|
+
type: "flow-await",
|
|
246
|
+
style: { minWidth: "180px" }
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
return [...out, ...awaitNodes];
|
|
194
252
|
});
|
|
195
253
|
function mapStatusToNodeStatus(status) {
|
|
196
254
|
switch (status) {
|
|
@@ -213,6 +271,7 @@ const edges = computed(() => {
|
|
|
213
271
|
const f = props.flow;
|
|
214
272
|
if (!f) return [];
|
|
215
273
|
const states = props.stepStates || {};
|
|
274
|
+
const steps = f.steps || {};
|
|
216
275
|
const added = /* @__PURE__ */ new Set();
|
|
217
276
|
const out = [];
|
|
218
277
|
function addEdge(source, target, label) {
|
|
@@ -229,14 +288,32 @@ const edges = computed(() => {
|
|
|
229
288
|
if (f.analyzed?.steps) {
|
|
230
289
|
const analyzedSteps = f.analyzed.steps;
|
|
231
290
|
for (const [stepName, stepInfo] of Object.entries(analyzedSteps)) {
|
|
291
|
+
const targetStep = steps[stepName];
|
|
232
292
|
const target = `step:${stepName}`;
|
|
233
293
|
if (stepInfo.dependsOn.length > 0) {
|
|
234
294
|
for (const depName of stepInfo.dependsOn) {
|
|
235
295
|
const source = depName === f.entry?.step ? `entry:${depName}` : `step:${depName}`;
|
|
236
|
-
|
|
296
|
+
if (targetStep?.awaitBefore) {
|
|
297
|
+
const awaitNodeId = `await:step-before:${stepName}`;
|
|
298
|
+
addEdge(source, awaitNodeId);
|
|
299
|
+
addEdge(awaitNodeId, target);
|
|
300
|
+
} else {
|
|
301
|
+
addEdge(source, target);
|
|
302
|
+
}
|
|
237
303
|
}
|
|
238
304
|
} else if (f.entry) {
|
|
239
|
-
|
|
305
|
+
const entryId = `entry:${f.entry.step}`;
|
|
306
|
+
if (f.entry.awaitAfter) {
|
|
307
|
+
const awaitNodeId = `await:entry-after:${f.entry.step}`;
|
|
308
|
+
addEdge(entryId, awaitNodeId);
|
|
309
|
+
addEdge(awaitNodeId, target);
|
|
310
|
+
} else if (targetStep?.awaitBefore) {
|
|
311
|
+
const awaitNodeId = `await:step-before:${stepName}`;
|
|
312
|
+
addEdge(entryId, awaitNodeId);
|
|
313
|
+
addEdge(awaitNodeId, target);
|
|
314
|
+
} else {
|
|
315
|
+
addEdge(entryId, target);
|
|
316
|
+
}
|
|
240
317
|
}
|
|
241
318
|
}
|
|
242
319
|
} else {
|
|
@@ -289,15 +366,19 @@ watch(() => props.flow, (f) => {
|
|
|
289
366
|
}
|
|
290
367
|
}, 100);
|
|
291
368
|
}, { immediate: true, deep: false });
|
|
292
|
-
watch(() => props.stepStates, () => {
|
|
369
|
+
watch([() => props.stepStates, () => props.flowStatus], () => {
|
|
293
370
|
if (!props.flow) return;
|
|
294
|
-
const
|
|
371
|
+
const latestNodes = nodes.value;
|
|
295
372
|
const positionMap = new Map(internalNodes.value.map((n) => [n.id, n.position]));
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
373
|
+
const updatedNodes = latestNodes.map((n) => ({
|
|
374
|
+
id: n.id,
|
|
375
|
+
position: positionMap.get(n.id) || { ...n.position },
|
|
376
|
+
data: { ...n.data },
|
|
377
|
+
// Create new data object reference
|
|
378
|
+
type: n.type,
|
|
379
|
+
style: n.style
|
|
380
|
+
}));
|
|
381
|
+
internalNodes.value = updatedNodes;
|
|
301
382
|
const builtEdges = edges.value.map((e) => ({ id: e.id, source: e.source, target: e.target, label: e.label, animated: e.animated }));
|
|
302
383
|
internalEdges.value = builtEdges;
|
|
303
384
|
}, { deep: true });
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
interface AwaitConfig {
|
|
2
|
+
type: 'time' | 'event' | 'webhook';
|
|
3
|
+
delay?: number;
|
|
4
|
+
event?: string;
|
|
5
|
+
method?: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
timeoutAction?: 'fail' | 'continue';
|
|
8
|
+
}
|
|
1
9
|
interface FlowEntry {
|
|
2
10
|
step: string;
|
|
3
11
|
queue: string;
|
|
@@ -5,6 +13,7 @@ interface FlowEntry {
|
|
|
5
13
|
runtime?: 'nodejs' | 'python';
|
|
6
14
|
runtype?: 'inprocess' | 'task';
|
|
7
15
|
emits?: string[];
|
|
16
|
+
awaitAfter?: AwaitConfig;
|
|
8
17
|
}
|
|
9
18
|
interface FlowStep {
|
|
10
19
|
queue: string;
|
|
@@ -13,6 +22,8 @@ interface FlowStep {
|
|
|
13
22
|
runtime?: 'nodejs' | 'python';
|
|
14
23
|
runtype?: 'inprocess' | 'task';
|
|
15
24
|
emits?: string[];
|
|
25
|
+
awaitBefore?: AwaitConfig;
|
|
26
|
+
awaitAfter?: AwaitConfig;
|
|
16
27
|
}
|
|
17
28
|
interface AnalyzedStep extends FlowStep {
|
|
18
29
|
name: string;
|
|
@@ -42,7 +53,7 @@ type __VLS_Props = {
|
|
|
42
53
|
showMiniMap?: boolean;
|
|
43
54
|
showBackground?: boolean;
|
|
44
55
|
stepStates?: Record<string, StepStatus>;
|
|
45
|
-
flowStatus?: 'running' | 'completed' | 'failed' | 'canceled';
|
|
56
|
+
flowStatus?: 'running' | 'completed' | 'failed' | 'canceled' | 'stalled';
|
|
46
57
|
};
|
|
47
58
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
48
59
|
nodeSelected: (payload: {
|
|
@@ -5,6 +5,9 @@ type __VLS_Props = {
|
|
|
5
5
|
steps: any[];
|
|
6
6
|
flowName?: string;
|
|
7
7
|
runId?: string;
|
|
8
|
+
triggerName?: string;
|
|
9
|
+
triggerType?: 'manual' | 'event' | 'webhook' | 'schedule';
|
|
10
|
+
flowDef?: any;
|
|
8
11
|
};
|
|
9
12
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
13
|
"select-step": (stepKey: string | null) => any;
|
|
@@ -18,6 +18,23 @@
|
|
|
18
18
|
<!-- Divider -->
|
|
19
19
|
<div class="w-px h-3 bg-gray-300 dark:bg-gray-700" />
|
|
20
20
|
|
|
21
|
+
<!-- Entry Trigger -->
|
|
22
|
+
<div
|
|
23
|
+
v-if="triggerName"
|
|
24
|
+
class="flex items-center gap-1.5"
|
|
25
|
+
>
|
|
26
|
+
<UIcon
|
|
27
|
+
:name="getTriggerIcon(triggerType)"
|
|
28
|
+
class="w-3 h-3 text-gray-500"
|
|
29
|
+
/>
|
|
30
|
+
<span class="text-gray-700 dark:text-gray-300">
|
|
31
|
+
{{ triggerName }}
|
|
32
|
+
</span>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- Divider -->
|
|
36
|
+
<div class="w-px h-3 bg-gray-300 dark:bg-gray-700" />
|
|
37
|
+
|
|
21
38
|
<!-- Total Steps -->
|
|
22
39
|
<div class="flex items-center gap-1.5">
|
|
23
40
|
<UIcon
|
|
@@ -96,14 +113,17 @@
|
|
|
96
113
|
<script setup>
|
|
97
114
|
import { ref, computed, watch } from "#imports";
|
|
98
115
|
import { UIcon, UButton } from "#components";
|
|
99
|
-
import FlowStepSelector from "./
|
|
116
|
+
import FlowStepSelector from "./StepSelector.vue";
|
|
100
117
|
const props = defineProps({
|
|
101
118
|
runStatus: { type: String, required: false },
|
|
102
119
|
startedAt: { type: [String, Number], required: false },
|
|
103
120
|
completedAt: { type: [String, Number], required: false },
|
|
104
121
|
steps: { type: Array, required: true },
|
|
105
122
|
flowName: { type: String, required: false },
|
|
106
|
-
runId: { type: String, required: false }
|
|
123
|
+
runId: { type: String, required: false },
|
|
124
|
+
triggerName: { type: String, required: false },
|
|
125
|
+
triggerType: { type: String, required: false },
|
|
126
|
+
flowDef: { type: null, required: false }
|
|
107
127
|
});
|
|
108
128
|
const emit = defineEmits(["select-step", "cancel-flow"]);
|
|
109
129
|
const handleCancelFlow = () => {
|
|
@@ -119,6 +139,23 @@ watch(firstStepKey, (newKey, oldKey) => {
|
|
|
119
139
|
watch(selectedStep, (newStep) => {
|
|
120
140
|
emit("select-step", newStep === "all-steps" ? null : newStep);
|
|
121
141
|
});
|
|
142
|
+
const isValidAwaitStep = (stepKey) => {
|
|
143
|
+
if (!stepKey.includes(":await-")) return true;
|
|
144
|
+
if (!props.flowDef) return false;
|
|
145
|
+
const parts = stepKey.split(":await-");
|
|
146
|
+
const stepName = parts[0];
|
|
147
|
+
const position = parts[1];
|
|
148
|
+
if (props.flowDef.entry?.step === stepName) {
|
|
149
|
+
if (position === "after" && props.flowDef.entry?.awaitAfter) return true;
|
|
150
|
+
if (position === "before" && props.flowDef.entry?.awaitBefore) return true;
|
|
151
|
+
}
|
|
152
|
+
const step = stepName ? props.flowDef.steps?.[stepName] : void 0;
|
|
153
|
+
if (step) {
|
|
154
|
+
if (position === "after" && step.awaitAfter) return true;
|
|
155
|
+
if (position === "before" && step.awaitBefore) return true;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
};
|
|
122
159
|
const radioItems = computed(() => {
|
|
123
160
|
const allItem = {
|
|
124
161
|
value: "all-steps",
|
|
@@ -127,13 +164,48 @@ const radioItems = computed(() => {
|
|
|
127
164
|
key: "All Steps",
|
|
128
165
|
status: null,
|
|
129
166
|
showAllIndicator: true
|
|
130
|
-
}
|
|
167
|
+
},
|
|
168
|
+
clickable: true
|
|
131
169
|
};
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
170
|
+
const filteredSteps = props.steps.filter((step) => isValidAwaitStep(step.key));
|
|
171
|
+
const stepItems = filteredSteps.map((step) => {
|
|
172
|
+
const isAwait = step.key.includes(":await-");
|
|
173
|
+
let awaitConfig = void 0;
|
|
174
|
+
let webhookUrl = void 0;
|
|
175
|
+
if (isAwait && props.flowDef) {
|
|
176
|
+
const parts = step.key.split(":await-");
|
|
177
|
+
const stepName = parts[0];
|
|
178
|
+
const position = parts[1];
|
|
179
|
+
if (props.flowDef.entry?.step === stepName) {
|
|
180
|
+
awaitConfig = position === "after" ? props.flowDef.entry?.awaitAfter : props.flowDef.entry?.awaitBefore;
|
|
181
|
+
} else {
|
|
182
|
+
const stepDef = stepName ? props.flowDef.steps?.[stepName] : void 0;
|
|
183
|
+
if (stepDef) {
|
|
184
|
+
awaitConfig = position === "after" ? stepDef.awaitAfter : stepDef.awaitBefore;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (awaitConfig?.type === "webhook" && props.flowName && props.runId) {
|
|
188
|
+
const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.host}` : "";
|
|
189
|
+
webhookUrl = `${baseUrl}/api/_webhook/await/${props.flowName}/${props.runId}/${stepName}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const finalStep = {
|
|
193
|
+
...step,
|
|
194
|
+
awaitConfig,
|
|
195
|
+
// Add await config from flow definition
|
|
196
|
+
// Extract awaitType from config if available
|
|
197
|
+
awaitType: awaitConfig?.type || step.awaitType,
|
|
198
|
+
webhookUrl
|
|
199
|
+
// Add constructed webhook URL
|
|
200
|
+
};
|
|
201
|
+
return {
|
|
202
|
+
value: step.key,
|
|
203
|
+
label: step.key,
|
|
204
|
+
step: finalStep,
|
|
205
|
+
clickable: !isAwait
|
|
206
|
+
// Await steps are not clickable
|
|
207
|
+
};
|
|
208
|
+
});
|
|
137
209
|
return [allItem, ...stepItems];
|
|
138
210
|
});
|
|
139
211
|
const formatTime = (timestamp) => {
|
|
@@ -185,4 +257,18 @@ const getStatusColor = (status) => {
|
|
|
185
257
|
return "bg-gray-300";
|
|
186
258
|
}
|
|
187
259
|
};
|
|
260
|
+
const getTriggerIcon = (type) => {
|
|
261
|
+
switch (type) {
|
|
262
|
+
case "manual":
|
|
263
|
+
return "i-lucide-hand";
|
|
264
|
+
case "event":
|
|
265
|
+
return "i-lucide-zap";
|
|
266
|
+
case "webhook":
|
|
267
|
+
return "i-lucide-webhook";
|
|
268
|
+
case "schedule":
|
|
269
|
+
return "i-lucide-calendar-clock";
|
|
270
|
+
default:
|
|
271
|
+
return "i-lucide-play-circle";
|
|
272
|
+
}
|
|
273
|
+
};
|
|
188
274
|
</script>
|
|
@@ -5,6 +5,9 @@ type __VLS_Props = {
|
|
|
5
5
|
steps: any[];
|
|
6
6
|
flowName?: string;
|
|
7
7
|
runId?: string;
|
|
8
|
+
triggerName?: string;
|
|
9
|
+
triggerType?: 'manual' | 'event' | 'webhook' | 'schedule';
|
|
10
|
+
flowDef?: any;
|
|
8
11
|
};
|
|
9
12
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
13
|
"select-step": (stepKey: string | null) => any;
|
package/dist/runtime/app/components/{FlowRunStatusBadge.d.vue.ts → flow/RunStatusBadge.d.vue.ts}
RENAMED
|
@@ -4,15 +4,9 @@ interface Props {
|
|
|
4
4
|
isFailed?: boolean;
|
|
5
5
|
isCanceled?: boolean;
|
|
6
6
|
isStalled?: boolean;
|
|
7
|
+
isAwaiting?: boolean;
|
|
7
8
|
isReconnecting?: boolean;
|
|
8
9
|
}
|
|
9
|
-
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
10
|
-
isRunning: boolean;
|
|
11
|
-
isCompleted: boolean;
|
|
12
|
-
isFailed: boolean;
|
|
13
|
-
isCanceled: boolean;
|
|
14
|
-
isStalled: boolean;
|
|
15
|
-
isReconnecting: boolean;
|
|
16
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
11
|
declare const _default: typeof __VLS_export;
|
|
18
12
|
export default _default;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
'bg-emerald-50 dark:bg-emerald-950/30 border-emerald-200 dark:border-emerald-800': isCompleted,
|
|
6
6
|
'bg-red-50 dark:bg-red-950/30 border-red-200 dark:border-red-800': isFailed,
|
|
7
7
|
'bg-blue-50 dark:bg-blue-950/30 border-blue-200 dark:border-blue-800': isRunning,
|
|
8
|
+
'bg-purple-50 dark:bg-purple-950/30 border-purple-200 dark:border-purple-800': isAwaiting,
|
|
8
9
|
'bg-orange-50 dark:bg-orange-950/30 border-orange-200 dark:border-orange-800': isCanceled,
|
|
9
10
|
'bg-amber-50 dark:bg-amber-950/30 border-amber-200 dark:border-amber-800': isStalled,
|
|
10
11
|
'bg-gray-50 dark:bg-gray-900/30 border-gray-200 dark:border-gray-800': isIdle
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
'bg-emerald-500': isCompleted,
|
|
17
18
|
'bg-red-500': isFailed,
|
|
18
19
|
'bg-blue-500 animate-pulse': isRunning && !isReconnecting,
|
|
20
|
+
'bg-purple-500 animate-pulse': isAwaiting,
|
|
19
21
|
'bg-amber-500 animate-pulse': isReconnecting,
|
|
20
22
|
'bg-orange-500': isCanceled,
|
|
21
23
|
'bg-amber-600': isStalled,
|
|
@@ -28,6 +30,7 @@
|
|
|
28
30
|
'text-emerald-700 dark:text-emerald-400': isCompleted,
|
|
29
31
|
'text-red-700 dark:text-red-400': isFailed,
|
|
30
32
|
'text-blue-700 dark:text-blue-400': isRunning,
|
|
33
|
+
'text-purple-700 dark:text-purple-400': isAwaiting,
|
|
31
34
|
'text-orange-700 dark:text-orange-400': isCanceled,
|
|
32
35
|
'text-amber-700 dark:text-amber-400': isStalled,
|
|
33
36
|
'text-gray-600 dark:text-gray-400': isIdle
|
|
@@ -39,6 +42,9 @@
|
|
|
39
42
|
<template v-else-if="isRunning">
|
|
40
43
|
Running
|
|
41
44
|
</template>
|
|
45
|
+
<template v-else-if="isAwaiting">
|
|
46
|
+
Awaiting
|
|
47
|
+
</template>
|
|
42
48
|
<template v-else-if="isCompleted">
|
|
43
49
|
Done
|
|
44
50
|
</template>
|
|
@@ -66,9 +72,10 @@ const props = defineProps({
|
|
|
66
72
|
isFailed: { type: Boolean, required: false, default: false },
|
|
67
73
|
isCanceled: { type: Boolean, required: false, default: false },
|
|
68
74
|
isStalled: { type: Boolean, required: false, default: false },
|
|
75
|
+
isAwaiting: { type: Boolean, required: false, default: false },
|
|
69
76
|
isReconnecting: { type: Boolean, required: false, default: false }
|
|
70
77
|
});
|
|
71
78
|
const isIdle = computed(() => {
|
|
72
|
-
return !props.isRunning && !props.isCompleted && !props.isFailed && !props.isCanceled && !props.isStalled;
|
|
79
|
+
return !props.isRunning && !props.isCompleted && !props.isFailed && !props.isCanceled && !props.isStalled && !props.isAwaiting;
|
|
73
80
|
});
|
|
74
81
|
</script>
|
package/dist/runtime/app/components/{FlowRunStatusBadge.vue.d.ts → flow/RunStatusBadge.vue.d.ts}
RENAMED
|
@@ -4,15 +4,9 @@ interface Props {
|
|
|
4
4
|
isFailed?: boolean;
|
|
5
5
|
isCanceled?: boolean;
|
|
6
6
|
isStalled?: boolean;
|
|
7
|
+
isAwaiting?: boolean;
|
|
7
8
|
isReconnecting?: boolean;
|
|
8
9
|
}
|
|
9
|
-
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
10
|
-
isRunning: boolean;
|
|
11
|
-
isCompleted: boolean;
|
|
12
|
-
isFailed: boolean;
|
|
13
|
-
isCanceled: boolean;
|
|
14
|
-
isStalled: boolean;
|
|
15
|
-
isReconnecting: boolean;
|
|
16
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
11
|
declare const _default: typeof __VLS_export;
|
|
18
12
|
export default _default;
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
|
|
59
59
|
<script setup>
|
|
60
60
|
import { ref, computed } from "#imports";
|
|
61
|
-
import TimelineList from "
|
|
61
|
+
import TimelineList from "../TimelineList.vue";
|
|
62
62
|
import { UButton, UIcon, URadioGroup } from "#components";
|
|
63
63
|
const props = defineProps({
|
|
64
64
|
events: { type: Array, required: true },
|