@nvent-addon/app 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -1
- package/dist/runtime/app/components/ComponentShell.d.vue.ts +1 -0
- package/dist/runtime/app/components/ComponentShell.vue +13 -3
- package/dist/runtime/app/components/ComponentShell.vue.d.ts +1 -0
- package/dist/runtime/app/components/DashboardCard.d.vue.ts +15 -0
- package/dist/runtime/app/components/DashboardCard.vue +76 -0
- package/dist/runtime/app/components/DashboardCard.vue.d.ts +15 -0
- package/dist/runtime/app/components/TimelineList.vue +222 -31
- package/dist/runtime/app/components/flow/AwaitNode.d.vue.ts +19 -2
- package/dist/runtime/app/components/flow/AwaitNode.vue +317 -29
- package/dist/runtime/app/components/flow/AwaitNode.vue.d.ts +19 -2
- package/dist/runtime/app/components/flow/Diagram.d.vue.ts +2 -1
- package/dist/runtime/app/components/flow/Diagram.vue +138 -74
- package/dist/runtime/app/components/flow/Diagram.vue.d.ts +2 -1
- package/dist/runtime/app/components/flow/NodeCard.d.vue.ts +14 -11
- package/dist/runtime/app/components/flow/NodeCard.vue +119 -35
- package/dist/runtime/app/components/flow/NodeCard.vue.d.ts +14 -11
- package/dist/runtime/app/components/flow/RunOverview.d.vue.ts +1 -0
- package/dist/runtime/app/components/flow/RunOverview.vue +85 -86
- package/dist/runtime/app/components/flow/RunOverview.vue.d.ts +1 -0
- package/dist/runtime/app/components/flow/RunTimeline.vue +51 -22
- package/dist/runtime/app/components/flow/StepSelector.vue +124 -46
- package/dist/runtime/app/composables/useFlowRunTimeline.d.ts +6 -0
- package/dist/runtime/app/composables/useFlowState.d.ts +8 -1
- package/dist/runtime/app/composables/useFlowState.js +34 -59
- package/dist/runtime/app/pages/dashboard.vue +51 -103
- package/dist/runtime/app/pages/flows/[name].vue +26 -3
- package/dist/runtime/app/pages/triggers/[name]/edit.vue +1 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { createResolver, defineNuxtModule, addImportsDir, addServerScanDir, addPlugin, addComponentsDir, addComponent, extendPages } from '@nuxt/kit';
|
|
2
2
|
import defu from 'defu';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
3
4
|
|
|
4
5
|
const resolver = createResolver(import.meta.url);
|
|
6
|
+
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
5
7
|
const module$1 = defineNuxtModule({
|
|
6
8
|
meta: {
|
|
7
9
|
name: "nventapp",
|
|
8
|
-
version:
|
|
10
|
+
version: packageJson.version,
|
|
9
11
|
configKey: "nventapp"
|
|
10
12
|
},
|
|
11
13
|
defaults: {
|
|
@@ -20,6 +22,12 @@ const module$1 = defineNuxtModule({
|
|
|
20
22
|
},
|
|
21
23
|
async setup(options, nuxt) {
|
|
22
24
|
const { resolve } = resolver;
|
|
25
|
+
nuxt.options.runtimeConfig.public.nventapp = defu(
|
|
26
|
+
nuxt.options.runtimeConfig.public.nventapp,
|
|
27
|
+
{
|
|
28
|
+
routePath: options.routePath
|
|
29
|
+
}
|
|
30
|
+
);
|
|
23
31
|
nuxt.options.css = nuxt.options.css || [];
|
|
24
32
|
nuxt.options.css.push(resolve("./runtime/app/assets/vueflow.css"));
|
|
25
33
|
addImportsDir(resolve("./runtime/shared/utils"));
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
:class="
|
|
6
6
|
orientation === 'vertical' ? 'flex h-full' : 'flex flex-col w-full'
|
|
7
7
|
"
|
|
8
|
-
style="
|
|
8
|
+
:style="containerStyle"
|
|
9
9
|
>
|
|
10
10
|
<!-- Navigation using UNavigationMenu -->
|
|
11
11
|
<div
|
|
@@ -34,13 +34,23 @@
|
|
|
34
34
|
|
|
35
35
|
<script setup>
|
|
36
36
|
import { computed } from "vue";
|
|
37
|
-
import { useComponentRouter } from "#imports";
|
|
37
|
+
import { useComponentRouter, useRoute, useRuntimeConfig } from "#imports";
|
|
38
38
|
const props = defineProps({
|
|
39
39
|
orientation: { type: String, required: false, default: "horizontal" },
|
|
40
40
|
items: { type: Array, required: false },
|
|
41
|
-
activeMatch: { type: String, required: false, default: "prefix" }
|
|
41
|
+
activeMatch: { type: String, required: false, default: "prefix" },
|
|
42
|
+
fullPage: { type: Boolean, required: false }
|
|
42
43
|
});
|
|
43
44
|
const router = useComponentRouter();
|
|
45
|
+
const nuxtRoute = useRoute();
|
|
46
|
+
const config = useRuntimeConfig();
|
|
47
|
+
const isFullPage = computed(() => {
|
|
48
|
+
const nventPath = config.public.nventapp?.routePath || "/_nvent";
|
|
49
|
+
return nuxtRoute?.path?.startsWith(nventPath) ?? false;
|
|
50
|
+
});
|
|
51
|
+
const containerStyle = computed(() => {
|
|
52
|
+
return isFullPage.value ? "height: 100vh" : "height: calc(100vh - 4rem)";
|
|
53
|
+
});
|
|
44
54
|
const navigationItems = computed(() => {
|
|
45
55
|
if (!props.items) return [];
|
|
46
56
|
const transformItem = (item) => {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Stat {
|
|
2
|
+
value: string | number;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
interface Props {
|
|
6
|
+
icon: string;
|
|
7
|
+
title: string;
|
|
8
|
+
primaryStats: Stat[];
|
|
9
|
+
secondaryStats?: Stat[];
|
|
10
|
+
color: 'blue' | 'purple' | 'amber' | 'emerald' | 'red';
|
|
11
|
+
onClick?: () => void;
|
|
12
|
+
}
|
|
13
|
+
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>;
|
|
14
|
+
declare const _default: typeof __VLS_export;
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
'rounded-xl p-6 text-white shadow-lg hover:shadow-xl transition-shadow cursor-pointer',
|
|
5
|
+
gradientClass
|
|
6
|
+
]"
|
|
7
|
+
@click="onClick"
|
|
8
|
+
>
|
|
9
|
+
<div class="flex items-center justify-between mb-4">
|
|
10
|
+
<div class="flex items-center gap-3">
|
|
11
|
+
<div class="p-3 bg-white/20 rounded-lg backdrop-blur-sm">
|
|
12
|
+
<UIcon
|
|
13
|
+
:name="icon"
|
|
14
|
+
class="w-6 h-6"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="text-sm opacity-75">
|
|
18
|
+
{{ title }}
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<UIcon
|
|
22
|
+
name="i-lucide-arrow-right"
|
|
23
|
+
class="w-5 h-5 opacity-60"
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<!-- Primary Stats (Live Data - Large) -->
|
|
28
|
+
<div class="flex items-baseline gap-4 mb-4 flex-wrap min-h-[3rem]">
|
|
29
|
+
<div
|
|
30
|
+
v-for="stat in primaryStats"
|
|
31
|
+
:key="stat.label"
|
|
32
|
+
class="flex items-baseline gap-2"
|
|
33
|
+
>
|
|
34
|
+
<div class="text-4xl font-bold">
|
|
35
|
+
{{ stat.value }}
|
|
36
|
+
</div>
|
|
37
|
+
<div class="text-sm opacity-90">
|
|
38
|
+
{{ stat.label }}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<!-- Secondary Stats (Static/Context - Small) -->
|
|
44
|
+
<div class="flex items-center gap-3 text-xs opacity-75">
|
|
45
|
+
<div
|
|
46
|
+
v-for="stat in secondaryStats"
|
|
47
|
+
:key="stat.label"
|
|
48
|
+
>
|
|
49
|
+
<span class="font-semibold">{{ stat.value }}</span> {{ stat.label }}
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script setup>
|
|
56
|
+
import { computed } from "#imports";
|
|
57
|
+
const props = defineProps({
|
|
58
|
+
icon: { type: String, required: true },
|
|
59
|
+
title: { type: String, required: true },
|
|
60
|
+
primaryStats: { type: Array, required: true },
|
|
61
|
+
secondaryStats: { type: Array, required: false, default: () => [] },
|
|
62
|
+
color: { type: String, required: true },
|
|
63
|
+
onClick: { type: Function, required: false, default: () => {
|
|
64
|
+
} }
|
|
65
|
+
});
|
|
66
|
+
const gradientClass = computed(() => {
|
|
67
|
+
const colors = {
|
|
68
|
+
blue: "bg-gradient-to-br from-blue-500 to-blue-600 dark:from-blue-600 dark:to-blue-700",
|
|
69
|
+
purple: "bg-gradient-to-br from-purple-500 to-purple-600 dark:from-purple-600 dark:to-purple-700",
|
|
70
|
+
amber: "bg-gradient-to-br from-amber-500 to-amber-600 dark:from-amber-600 dark:to-amber-700",
|
|
71
|
+
emerald: "bg-gradient-to-br from-emerald-500 to-emerald-600 dark:from-emerald-600 dark:to-emerald-700",
|
|
72
|
+
red: "bg-gradient-to-br from-red-500 to-red-600 dark:from-red-600 dark:to-red-700"
|
|
73
|
+
};
|
|
74
|
+
return colors[props.color];
|
|
75
|
+
});
|
|
76
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Stat {
|
|
2
|
+
value: string | number;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
interface Props {
|
|
6
|
+
icon: string;
|
|
7
|
+
title: string;
|
|
8
|
+
primaryStats: Stat[];
|
|
9
|
+
secondaryStats?: Stat[];
|
|
10
|
+
color: 'blue' | 'purple' | 'amber' | 'emerald' | 'red';
|
|
11
|
+
onClick?: () => void;
|
|
12
|
+
}
|
|
13
|
+
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>;
|
|
14
|
+
declare const _default: typeof __VLS_export;
|
|
15
|
+
export default _default;
|
|
@@ -21,13 +21,14 @@
|
|
|
21
21
|
<template #title="{ item }">
|
|
22
22
|
<div class="flex items-center gap-2 min-w-0">
|
|
23
23
|
<span
|
|
24
|
-
class="
|
|
24
|
+
:class="eventTypeColor(item.eventType)"
|
|
25
|
+
class="font-mono text-xs px-2 py-1 rounded font-medium flex-shrink-0"
|
|
25
26
|
>
|
|
26
27
|
{{ item.eventType }}
|
|
27
28
|
</span>
|
|
28
29
|
<span
|
|
29
30
|
v-if="item.stepName"
|
|
30
|
-
class="text-xs text-gray-
|
|
31
|
+
class="text-xs text-gray-600 dark:text-gray-300 truncate"
|
|
31
32
|
>
|
|
32
33
|
{{ item.stepName }}
|
|
33
34
|
</span>
|
|
@@ -39,26 +40,42 @@
|
|
|
39
40
|
<!-- Special rendering for log events -->
|
|
40
41
|
<div
|
|
41
42
|
v-if="item.eventType === 'log'"
|
|
42
|
-
class="
|
|
43
|
+
:class="hasMetadata(item.eventData) ? 'p-3 rounded-lg border bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700 mt-2' : 'mt-1'"
|
|
44
|
+
class="space-y-2"
|
|
43
45
|
>
|
|
44
46
|
<div class="flex items-start gap-2">
|
|
45
47
|
<UBadge
|
|
46
48
|
:color="levelColor(item?.eventData?.level)"
|
|
47
|
-
variant="
|
|
49
|
+
variant="solid"
|
|
48
50
|
size="xs"
|
|
49
51
|
class="capitalize mt-0.5 flex-shrink-0"
|
|
50
52
|
>
|
|
51
53
|
{{ item?.eventData?.level || "info" }}
|
|
52
54
|
</UBadge>
|
|
53
|
-
<span class="text-
|
|
55
|
+
<span class="text-xs text-gray-900 dark:text-gray-100 flex-1 break-words line-clamp-3">
|
|
54
56
|
{{ item?.eventData?.message || "" }}
|
|
55
57
|
</span>
|
|
56
58
|
</div>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
<!-- Show metadata in accordion if exists -->
|
|
60
|
+
<div v-if="hasMetadata(item.eventData)">
|
|
61
|
+
<UAccordion
|
|
62
|
+
:items="[{
|
|
63
|
+
label: 'Metadata',
|
|
64
|
+
icon: 'i-lucide-info',
|
|
65
|
+
defaultOpen: false,
|
|
66
|
+
content: item.eventData
|
|
67
|
+
}]"
|
|
68
|
+
:ui="{
|
|
69
|
+
trigger: 'text-[10px] py-1',
|
|
70
|
+
leadingIcon: 'size-3 text-blue-500 dark:text-blue-400',
|
|
71
|
+
label: 'text-[10px]',
|
|
72
|
+
item: 'border-0 mt-1'
|
|
73
|
+
}"
|
|
74
|
+
>
|
|
75
|
+
<template #content="{ item: accordionItem }">
|
|
76
|
+
<pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-60 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ prettyMetadata(accordionItem.content) }}</pre>
|
|
77
|
+
</template>
|
|
78
|
+
</UAccordion>
|
|
62
79
|
</div>
|
|
63
80
|
</div>
|
|
64
81
|
|
|
@@ -69,13 +86,13 @@
|
|
|
69
86
|
>
|
|
70
87
|
<div
|
|
71
88
|
v-if="item.eventData"
|
|
72
|
-
class="space-y-1"
|
|
89
|
+
class="space-y-1 p-2 rounded border bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700"
|
|
73
90
|
>
|
|
74
91
|
<div
|
|
75
92
|
v-if="item.eventData.awaitType"
|
|
76
93
|
class="flex items-start gap-2"
|
|
77
94
|
>
|
|
78
|
-
<span class="text-xs text-gray-500 dark:text-gray-400
|
|
95
|
+
<span class="text-xs text-gray-500 dark:text-gray-400 min-w-[60px] flex-shrink-0">Type:</span>
|
|
79
96
|
<UBadge
|
|
80
97
|
color="blue"
|
|
81
98
|
variant="subtle"
|
|
@@ -89,7 +106,7 @@
|
|
|
89
106
|
v-if="item.eventData.position"
|
|
90
107
|
class="flex items-start gap-2"
|
|
91
108
|
>
|
|
92
|
-
<span class="text-xs text-gray-500 dark:text-gray-400
|
|
109
|
+
<span class="text-xs text-gray-500 dark:text-gray-400 min-w-[60px] flex-shrink-0">Position:</span>
|
|
93
110
|
<UBadge
|
|
94
111
|
color="neutral"
|
|
95
112
|
variant="subtle"
|
|
@@ -103,21 +120,37 @@
|
|
|
103
120
|
v-if="item.eventData.triggerName"
|
|
104
121
|
class="flex items-start gap-2"
|
|
105
122
|
>
|
|
106
|
-
<span class="text-xs text-gray-
|
|
123
|
+
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold min-w-[60px] flex-shrink-0">Trigger:</span>
|
|
107
124
|
<span class="text-xs text-gray-700 dark:text-gray-300 font-mono">{{ item.eventData.triggerName }}</span>
|
|
108
125
|
</div>
|
|
109
126
|
<div
|
|
110
127
|
v-if="item.eventData.triggerData"
|
|
111
|
-
class="
|
|
128
|
+
class="mt-1"
|
|
112
129
|
>
|
|
113
|
-
<
|
|
114
|
-
|
|
130
|
+
<UAccordion
|
|
131
|
+
:items="[{
|
|
132
|
+
label: 'Trigger Data',
|
|
133
|
+
icon: 'i-lucide-braces',
|
|
134
|
+
defaultOpen: false,
|
|
135
|
+
content: item.eventData.triggerData
|
|
136
|
+
}]"
|
|
137
|
+
:ui="{
|
|
138
|
+
trigger: 'text-[10px] py-1',
|
|
139
|
+
leadingIcon: 'size-3 text-purple-500 dark:text-purple-400',
|
|
140
|
+
label: 'text-[10px]',
|
|
141
|
+
item: 'border-0 mt-0'
|
|
142
|
+
}"
|
|
143
|
+
>
|
|
144
|
+
<template #content="{ item: accordionItem }">
|
|
145
|
+
<pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-60 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(accordionItem.content) }}</pre>
|
|
146
|
+
</template>
|
|
147
|
+
</UAccordion>
|
|
115
148
|
</div>
|
|
116
149
|
<div
|
|
117
150
|
v-if="item.eventData.duration"
|
|
118
151
|
class="flex items-start gap-2"
|
|
119
152
|
>
|
|
120
|
-
<span class="text-xs text-gray-
|
|
153
|
+
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold min-w-[60px] flex-shrink-0">Duration:</span>
|
|
121
154
|
<span class="text-xs text-gray-700 dark:text-gray-300">{{ item.eventData.duration }}ms</span>
|
|
122
155
|
</div>
|
|
123
156
|
</div>
|
|
@@ -129,39 +162,158 @@
|
|
|
129
162
|
class="text-sm mt-2"
|
|
130
163
|
>
|
|
131
164
|
<div
|
|
132
|
-
v-if="item.eventData"
|
|
133
|
-
class="space-y-1"
|
|
165
|
+
v-if="item.eventData && (item.eventData.input || item.eventData.output || item.eventData.error)"
|
|
166
|
+
class="space-y-1 p-2 rounded border bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700"
|
|
134
167
|
>
|
|
135
168
|
<div
|
|
136
169
|
v-if="item.eventData.input"
|
|
137
|
-
class="
|
|
170
|
+
class="mt-1"
|
|
138
171
|
>
|
|
139
|
-
<
|
|
140
|
-
|
|
172
|
+
<UAccordion
|
|
173
|
+
:items="[{
|
|
174
|
+
label: 'Input',
|
|
175
|
+
icon: 'i-lucide-arrow-down-to-line',
|
|
176
|
+
defaultOpen: false,
|
|
177
|
+
content: item.eventData.input
|
|
178
|
+
}]"
|
|
179
|
+
:ui="{
|
|
180
|
+
trigger: 'text-[10px] py-1',
|
|
181
|
+
leadingIcon: 'size-3 text-green-500 dark:text-green-400',
|
|
182
|
+
label: 'text-[10px]',
|
|
183
|
+
item: 'border-0 mt-0'
|
|
184
|
+
}"
|
|
185
|
+
>
|
|
186
|
+
<template #content="{ item: accordionItem }">
|
|
187
|
+
<pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-60 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(accordionItem.content) }}</pre>
|
|
188
|
+
</template>
|
|
189
|
+
</UAccordion>
|
|
141
190
|
</div>
|
|
142
191
|
<div
|
|
143
192
|
v-if="item.eventData.output"
|
|
144
|
-
class="
|
|
193
|
+
class="mt-1"
|
|
145
194
|
>
|
|
146
|
-
<
|
|
147
|
-
|
|
195
|
+
<UAccordion
|
|
196
|
+
:items="[{
|
|
197
|
+
label: 'Output',
|
|
198
|
+
icon: 'i-lucide-arrow-up-from-line',
|
|
199
|
+
defaultOpen: false,
|
|
200
|
+
content: item.eventData.output
|
|
201
|
+
}]"
|
|
202
|
+
:ui="{
|
|
203
|
+
trigger: 'text-[10px] py-1',
|
|
204
|
+
leadingIcon: 'size-3 text-blue-500 dark:text-blue-400',
|
|
205
|
+
label: 'text-[10px]',
|
|
206
|
+
item: 'border-0 mt-0'
|
|
207
|
+
}"
|
|
208
|
+
>
|
|
209
|
+
<template #content="{ item: accordionItem }">
|
|
210
|
+
<pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-60 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(accordionItem.content) }}</pre>
|
|
211
|
+
</template>
|
|
212
|
+
</UAccordion>
|
|
148
213
|
</div>
|
|
149
214
|
<div
|
|
150
215
|
v-if="item.eventData.error"
|
|
151
|
-
class="
|
|
216
|
+
class="mt-1"
|
|
152
217
|
>
|
|
153
|
-
<
|
|
154
|
-
|
|
218
|
+
<UAccordion
|
|
219
|
+
:items="[{
|
|
220
|
+
label: 'Error Details',
|
|
221
|
+
icon: 'i-lucide-alert-circle',
|
|
222
|
+
defaultOpen: true,
|
|
223
|
+
content: item.eventData.error
|
|
224
|
+
}]"
|
|
225
|
+
:ui="{
|
|
226
|
+
trigger: 'text-[10px] py-1 text-red-600 dark:text-red-400',
|
|
227
|
+
leadingIcon: 'size-3 text-red-500 dark:text-red-400',
|
|
228
|
+
label: 'text-[10px]',
|
|
229
|
+
item: 'border-0 mt-0'
|
|
230
|
+
}"
|
|
231
|
+
>
|
|
232
|
+
<template #content="{ item: accordionItem }">
|
|
233
|
+
<pre class="text-xs bg-red-50 dark:bg-red-900/20 rounded p-2 overflow-y-auto max-h-60 text-red-700 dark:text-red-300 font-mono whitespace-pre-wrap break-words">{{ pretty(accordionItem.content) }}</pre>
|
|
234
|
+
</template>
|
|
235
|
+
</UAccordion>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<!-- Special rendering for emit events -->
|
|
241
|
+
<div
|
|
242
|
+
v-else-if="isEmitEvent(item.eventType)"
|
|
243
|
+
class="mt-2"
|
|
244
|
+
>
|
|
245
|
+
<div
|
|
246
|
+
v-if="item.eventData && item.eventData.payload"
|
|
247
|
+
class="p-2 rounded border bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700"
|
|
248
|
+
>
|
|
249
|
+
<div class="flex items-center gap-2 mb-1">
|
|
250
|
+
<span class="text-xs text-gray-500 dark:text-gray-400">Event:</span>
|
|
251
|
+
<UBadge
|
|
252
|
+
color="primary"
|
|
253
|
+
variant="solid"
|
|
254
|
+
size="xs"
|
|
255
|
+
>
|
|
256
|
+
{{ item.eventData.name || "unknown" }}
|
|
257
|
+
</UBadge>
|
|
155
258
|
</div>
|
|
259
|
+
<UAccordion
|
|
260
|
+
v-if="item.eventData.payload"
|
|
261
|
+
:items="[{
|
|
262
|
+
label: 'Payload',
|
|
263
|
+
icon: 'i-lucide-package',
|
|
264
|
+
defaultOpen: false,
|
|
265
|
+
content: item.eventData.payload
|
|
266
|
+
}]"
|
|
267
|
+
:ui="{
|
|
268
|
+
trigger: 'text-[10px] py-1',
|
|
269
|
+
leadingIcon: 'size-3 text-emerald-500 dark:text-emerald-400',
|
|
270
|
+
label: 'text-[10px]',
|
|
271
|
+
item: 'border-0 mt-0'
|
|
272
|
+
}"
|
|
273
|
+
>
|
|
274
|
+
<template #content="{ item: accordionItem }">
|
|
275
|
+
<pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-60 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(accordionItem.content) }}</pre>
|
|
276
|
+
</template>
|
|
277
|
+
</UAccordion>
|
|
278
|
+
</div>
|
|
279
|
+
<div
|
|
280
|
+
v-else-if="item.eventData"
|
|
281
|
+
class="flex items-center gap-2 mt-1"
|
|
282
|
+
>
|
|
283
|
+
<span class="text-xs text-gray-500 dark:text-gray-400">Event:</span>
|
|
284
|
+
<UBadge
|
|
285
|
+
color="primary"
|
|
286
|
+
variant="solid"
|
|
287
|
+
size="xs"
|
|
288
|
+
>
|
|
289
|
+
{{ item.eventData.name || "unknown" }}
|
|
290
|
+
</UBadge>
|
|
156
291
|
</div>
|
|
157
292
|
</div>
|
|
158
293
|
|
|
159
|
-
<!-- Default rendering -->
|
|
294
|
+
<!-- Default rendering with accordion -->
|
|
160
295
|
<div
|
|
161
296
|
v-else-if="item.eventData && Object.keys(item.eventData).length > 0"
|
|
162
297
|
class="mt-2"
|
|
163
298
|
>
|
|
164
|
-
<
|
|
299
|
+
<UAccordion
|
|
300
|
+
:items="[{
|
|
301
|
+
label: 'Event Data',
|
|
302
|
+
icon: 'i-lucide-braces',
|
|
303
|
+
defaultOpen: false,
|
|
304
|
+
content: item.eventData
|
|
305
|
+
}]"
|
|
306
|
+
:ui="{
|
|
307
|
+
trigger: 'text-[10px] py-1',
|
|
308
|
+
leadingIcon: 'size-3 text-gray-500 dark:text-gray-400',
|
|
309
|
+
label: 'text-[10px]',
|
|
310
|
+
item: 'border-0 mt-1'
|
|
311
|
+
}"
|
|
312
|
+
>
|
|
313
|
+
<template #content="{ item: accordionItem }">
|
|
314
|
+
<pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-60 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(accordionItem.content) }}</pre>
|
|
315
|
+
</template>
|
|
316
|
+
</UAccordion>
|
|
165
317
|
</div>
|
|
166
318
|
</template>
|
|
167
319
|
</UTimeline>
|
|
@@ -268,10 +420,49 @@ function levelColor(level) {
|
|
|
268
420
|
return "neutral";
|
|
269
421
|
}
|
|
270
422
|
}
|
|
423
|
+
function eventTypeColor(type) {
|
|
424
|
+
if (!type) return "bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300";
|
|
425
|
+
if (type.startsWith("flow.")) {
|
|
426
|
+
if (type === "flow.start") return "bg-purple-100 dark:bg-purple-900/50 text-purple-700 dark:text-purple-300";
|
|
427
|
+
if (type === "flow.completed") return "bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300";
|
|
428
|
+
if (type === "flow.failed") return "bg-red-100 dark:bg-red-900/50 text-red-700 dark:text-red-300";
|
|
429
|
+
return "bg-purple-100 dark:bg-purple-900/50 text-purple-700 dark:text-purple-300";
|
|
430
|
+
}
|
|
431
|
+
if (type.startsWith("step.")) {
|
|
432
|
+
if (type === "step.completed") return "bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300";
|
|
433
|
+
if (type === "step.failed") return "bg-red-100 dark:bg-red-900/50 text-red-700 dark:text-red-300";
|
|
434
|
+
return "bg-indigo-100 dark:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300";
|
|
435
|
+
}
|
|
436
|
+
if (type.startsWith("await.")) {
|
|
437
|
+
if (type === "await.resolved") return "bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300";
|
|
438
|
+
if (type === "await.timeout") return "bg-orange-100 dark:bg-orange-900/50 text-orange-700 dark:text-orange-300";
|
|
439
|
+
return "bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300";
|
|
440
|
+
}
|
|
441
|
+
if (type === "log") return "bg-yellow-100 dark:bg-yellow-900/50 text-yellow-700 dark:text-yellow-300";
|
|
442
|
+
if (type === "emit") return "bg-emerald-100 dark:bg-emerald-900/50 text-emerald-700 dark:text-emerald-300";
|
|
443
|
+
return "bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300";
|
|
444
|
+
}
|
|
271
445
|
function isFlowEvent(type) {
|
|
272
446
|
return type?.startsWith("flow.") || type?.startsWith("step.");
|
|
273
447
|
}
|
|
274
448
|
function isAwaitEvent(type) {
|
|
275
449
|
return type?.startsWith("await.");
|
|
276
450
|
}
|
|
451
|
+
function isEmitEvent(type) {
|
|
452
|
+
return type === "emit";
|
|
453
|
+
}
|
|
454
|
+
function hasMetadata(eventData) {
|
|
455
|
+
if (!eventData || typeof eventData !== "object") return false;
|
|
456
|
+
const autoInjectedKeys = ["message", "level", "msg", "stepName", "stepId", "stepRunId", "attempt", "flowName"];
|
|
457
|
+
const keys = Object.keys(eventData).filter((k) => !autoInjectedKeys.includes(k));
|
|
458
|
+
return keys.length > 0;
|
|
459
|
+
}
|
|
460
|
+
function prettyMetadata(eventData) {
|
|
461
|
+
if (!eventData || typeof eventData !== "object") return "";
|
|
462
|
+
const { message, level, msg, stepName, stepId, stepRunId, attempt, flowName, ...metadata } = eventData;
|
|
463
|
+
if (Object.keys(metadata).length === 1 && "value" in metadata) {
|
|
464
|
+
return pretty(metadata.value);
|
|
465
|
+
}
|
|
466
|
+
return pretty(metadata);
|
|
467
|
+
}
|
|
277
468
|
</script>
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
interface AwaitConfig {
|
|
2
|
-
type?: 'time' | 'event' | 'webhook';
|
|
2
|
+
type?: 'time' | 'event' | 'webhook' | 'schedule';
|
|
3
3
|
delay?: number;
|
|
4
4
|
event?: string;
|
|
5
|
+
filterKey?: string;
|
|
5
6
|
method?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
cron?: string;
|
|
9
|
+
timezone?: string;
|
|
6
10
|
timeout?: number;
|
|
11
|
+
timeoutAction?: 'fail' | 'continue' | 'retry';
|
|
12
|
+
}
|
|
13
|
+
interface AwaitData {
|
|
14
|
+
method?: string;
|
|
15
|
+
webhookUrl?: string;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
timeoutAction?: string;
|
|
18
|
+
eventName?: string;
|
|
19
|
+
filterKey?: string;
|
|
20
|
+
[key: string]: any;
|
|
7
21
|
}
|
|
8
22
|
type __VLS_Props = {
|
|
9
23
|
data: {
|
|
10
24
|
label: string;
|
|
11
|
-
awaitType?: 'time' | 'event' | 'webhook';
|
|
25
|
+
awaitType?: 'time' | 'event' | 'webhook' | 'schedule';
|
|
12
26
|
awaitConfig?: AwaitConfig;
|
|
27
|
+
awaitData?: AwaitData;
|
|
13
28
|
status?: 'idle' | 'waiting' | 'resolved' | 'timeout';
|
|
29
|
+
startedAt?: string | Date;
|
|
30
|
+
scheduledTriggerAt?: string | Date;
|
|
14
31
|
};
|
|
15
32
|
};
|
|
16
33
|
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>;
|