@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.
Files changed (30) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +9 -1
  3. package/dist/runtime/app/components/ComponentShell.d.vue.ts +1 -0
  4. package/dist/runtime/app/components/ComponentShell.vue +13 -3
  5. package/dist/runtime/app/components/ComponentShell.vue.d.ts +1 -0
  6. package/dist/runtime/app/components/DashboardCard.d.vue.ts +15 -0
  7. package/dist/runtime/app/components/DashboardCard.vue +76 -0
  8. package/dist/runtime/app/components/DashboardCard.vue.d.ts +15 -0
  9. package/dist/runtime/app/components/TimelineList.vue +222 -31
  10. package/dist/runtime/app/components/flow/AwaitNode.d.vue.ts +19 -2
  11. package/dist/runtime/app/components/flow/AwaitNode.vue +317 -29
  12. package/dist/runtime/app/components/flow/AwaitNode.vue.d.ts +19 -2
  13. package/dist/runtime/app/components/flow/Diagram.d.vue.ts +2 -1
  14. package/dist/runtime/app/components/flow/Diagram.vue +138 -74
  15. package/dist/runtime/app/components/flow/Diagram.vue.d.ts +2 -1
  16. package/dist/runtime/app/components/flow/NodeCard.d.vue.ts +14 -11
  17. package/dist/runtime/app/components/flow/NodeCard.vue +119 -35
  18. package/dist/runtime/app/components/flow/NodeCard.vue.d.ts +14 -11
  19. package/dist/runtime/app/components/flow/RunOverview.d.vue.ts +1 -0
  20. package/dist/runtime/app/components/flow/RunOverview.vue +85 -86
  21. package/dist/runtime/app/components/flow/RunOverview.vue.d.ts +1 -0
  22. package/dist/runtime/app/components/flow/RunTimeline.vue +51 -22
  23. package/dist/runtime/app/components/flow/StepSelector.vue +124 -46
  24. package/dist/runtime/app/composables/useFlowRunTimeline.d.ts +6 -0
  25. package/dist/runtime/app/composables/useFlowState.d.ts +8 -1
  26. package/dist/runtime/app/composables/useFlowState.js +34 -59
  27. package/dist/runtime/app/pages/dashboard.vue +51 -103
  28. package/dist/runtime/app/pages/flows/[name].vue +26 -3
  29. package/dist/runtime/app/pages/triggers/[name]/edit.vue +1 -1
  30. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nventapp",
3
- "version": "0.1",
3
+ "version": "0.5.6",
4
4
  "configKey": "nventapp",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
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: "0.1",
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"));
@@ -3,6 +3,7 @@ type __VLS_Props = {
3
3
  orientation?: 'horizontal' | 'vertical';
4
4
  items?: NavigationMenuItem[][];
5
5
  activeMatch?: 'exact' | 'prefix';
6
+ fullPage?: boolean;
6
7
  };
7
8
  declare var __VLS_7: {};
8
9
  type __VLS_Slots = {} & {
@@ -5,7 +5,7 @@
5
5
  :class="
6
6
  orientation === 'vertical' ? 'flex h-full' : 'flex flex-col w-full'
7
7
  "
8
- style="height: calc(100vh - 4rem)"
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) => {
@@ -3,6 +3,7 @@ type __VLS_Props = {
3
3
  orientation?: 'horizontal' | 'vertical';
4
4
  items?: NavigationMenuItem[][];
5
5
  activeMatch?: 'exact' | 'prefix';
6
+ fullPage?: boolean;
6
7
  };
7
8
  declare var __VLS_7: {};
8
9
  type __VLS_Slots = {} & {
@@ -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="font-mono text-xs px-2 py-0.5 rounded bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 flex-shrink-0"
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-500 dark:text-gray-400 truncate"
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="space-y-2 mt-2"
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="subtle"
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-sm text-gray-900 dark:text-gray-100 flex-1 break-words">
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
- <div
58
- v-if="item?.eventData?.progress"
59
- class="mt-2"
60
- >
61
- <pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-40 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(item.eventData) }}</pre>
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 font-medium min-w-[60px] flex-shrink-0">Type:</span>
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 font-medium min-w-[60px] flex-shrink-0">Position:</span>
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-500 dark:text-gray-400 font-medium min-w-[60px] flex-shrink-0">Trigger:</span>
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="flex items-start gap-2"
128
+ class="mt-1"
112
129
  >
113
- <span class="text-xs text-gray-500 dark:text-gray-400 font-medium min-w-[60px] flex-shrink-0">Data:</span>
114
- <pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded px-2 py-1 overflow-y-auto max-h-20 text-gray-700 dark:text-gray-300 font-mono flex-1 min-w-0 whitespace-pre-wrap break-words">{{ pretty(item.eventData.triggerData) }}</pre>
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-500 dark:text-gray-400 font-medium min-w-[60px] flex-shrink-0">Duration:</span>
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="flex items-start gap-2"
170
+ class="mt-1"
138
171
  >
139
- <span class="text-xs text-gray-500 dark:text-gray-400 font-medium min-w-[60px] flex-shrink-0">Input:</span>
140
- <pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded px-2 py-1 overflow-y-auto max-h-20 text-gray-700 dark:text-gray-300 font-mono flex-1 min-w-0 whitespace-pre-wrap break-words">{{ pretty(item.eventData.input) }}</pre>
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="flex items-start gap-2"
193
+ class="mt-1"
145
194
  >
146
- <span class="text-xs text-gray-500 dark:text-gray-400 font-medium min-w-[60px] flex-shrink-0">Output:</span>
147
- <pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded px-2 py-1 overflow-y-auto max-h-20 text-gray-700 dark:text-gray-300 font-mono flex-1 min-w-0 whitespace-pre-wrap break-words">{{ pretty(item.eventData.output) }}</pre>
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="flex items-start gap-2"
216
+ class="mt-1"
152
217
  >
153
- <span class="text-xs text-red-500 dark:text-red-400 font-medium min-w-[60px] flex-shrink-0">Error:</span>
154
- <pre class="text-xs bg-red-50 dark:bg-red-900/20 rounded px-2 py-1 overflow-y-auto max-h-20 text-red-700 dark:text-red-300 font-mono flex-1 min-w-0 whitespace-pre-wrap break-words">{{ pretty(item.eventData.error) }}</pre>
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
- <pre class="text-xs bg-gray-50 dark:bg-gray-800 rounded p-2 overflow-y-auto max-h-40 text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words">{{ pretty(item.eventData) }}</pre>
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>;