@antelopejs/dms-automation 0.0.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.
Files changed (305) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +95 -0
  3. package/dist/cluster/bus.d.ts +17 -0
  4. package/dist/cluster/bus.js +82 -0
  5. package/dist/cluster/bus.js.map +1 -0
  6. package/dist/cluster/instance.d.ts +1 -0
  7. package/dist/cluster/instance.js +6 -0
  8. package/dist/cluster/instance.js.map +1 -0
  9. package/dist/cluster/leader.d.ts +7 -0
  10. package/dist/cluster/leader.js +123 -0
  11. package/dist/cluster/leader.js.map +1 -0
  12. package/dist/cluster/mode.d.ts +3 -0
  13. package/dist/cluster/mode.js +25 -0
  14. package/dist/cluster/mode.js.map +1 -0
  15. package/dist/data/procedures-table.d.ts +66 -0
  16. package/dist/data/procedures-table.js +271 -0
  17. package/dist/data/procedures-table.js.map +1 -0
  18. package/dist/data/runs-table.d.ts +23 -0
  19. package/dist/data/runs-table.js +125 -0
  20. package/dist/data/runs-table.js.map +1 -0
  21. package/dist/db/index.d.ts +7 -0
  22. package/dist/db/index.js +24 -0
  23. package/dist/db/index.js.map +1 -0
  24. package/dist/db/models/automation_template.model.d.ts +58 -0
  25. package/dist/db/models/automation_template.model.js +134 -0
  26. package/dist/db/models/automation_template.model.js.map +1 -0
  27. package/dist/db/models/index.d.ts +3 -0
  28. package/dist/db/models/index.js +20 -0
  29. package/dist/db/models/index.js.map +1 -0
  30. package/dist/db/models/procedure.model.d.ts +25 -0
  31. package/dist/db/models/procedure.model.js +28 -0
  32. package/dist/db/models/procedure.model.js.map +1 -0
  33. package/dist/db/models/procedure_run.model.d.ts +34 -0
  34. package/dist/db/models/procedure_run.model.js +39 -0
  35. package/dist/db/models/procedure_run.model.js.map +1 -0
  36. package/dist/db/models/stats.model.d.ts +73 -0
  37. package/dist/db/models/stats.model.js +267 -0
  38. package/dist/db/models/stats.model.js.map +1 -0
  39. package/dist/db/models/type_config.model.d.ts +47 -0
  40. package/dist/db/models/type_config.model.js +51 -0
  41. package/dist/db/models/type_config.model.js.map +1 -0
  42. package/dist/db/tables/action_type_config.table.d.ts +7 -0
  43. package/dist/db/tables/action_type_config.table.js +35 -0
  44. package/dist/db/tables/action_type_config.table.js.map +1 -0
  45. package/dist/db/tables/automation_template.table.d.ts +11 -0
  46. package/dist/db/tables/automation_template.table.js +52 -0
  47. package/dist/db/tables/automation_template.table.js.map +1 -0
  48. package/dist/db/tables/index.d.ts +5 -0
  49. package/dist/db/tables/index.js +22 -0
  50. package/dist/db/tables/index.js.map +1 -0
  51. package/dist/db/tables/procedure.table.d.ts +10 -0
  52. package/dist/db/tables/procedure.table.js +48 -0
  53. package/dist/db/tables/procedure.table.js.map +1 -0
  54. package/dist/db/tables/procedure_run.table.d.ts +13 -0
  55. package/dist/db/tables/procedure_run.table.js +57 -0
  56. package/dist/db/tables/procedure_run.table.js.map +1 -0
  57. package/dist/db/tables/trigger_type_config.table.d.ts +7 -0
  58. package/dist/db/tables/trigger_type_config.table.js +35 -0
  59. package/dist/db/tables/trigger_type_config.table.js.map +1 -0
  60. package/dist/implementations/dms-automation/index.d.ts +19 -0
  61. package/dist/implementations/dms-automation/index.js +50 -0
  62. package/dist/implementations/dms-automation/index.js.map +1 -0
  63. package/dist/index.d.ts +14 -0
  64. package/dist/index.js +121 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/pages/builder.d.ts +10 -0
  67. package/dist/pages/builder.js +28 -0
  68. package/dist/pages/builder.js.map +1 -0
  69. package/dist/pages/category.d.ts +1 -0
  70. package/dist/pages/category.js +10 -0
  71. package/dist/pages/category.js.map +1 -0
  72. package/dist/pages/index.d.ts +6 -0
  73. package/dist/pages/index.js +9 -0
  74. package/dist/pages/index.js.map +1 -0
  75. package/dist/pages/library.d.ts +10 -0
  76. package/dist/pages/library.js +28 -0
  77. package/dist/pages/library.js.map +1 -0
  78. package/dist/pages/overview.d.ts +10 -0
  79. package/dist/pages/overview.js +28 -0
  80. package/dist/pages/overview.js.map +1 -0
  81. package/dist/pages/procedures.d.ts +10 -0
  82. package/dist/pages/procedures.js +72 -0
  83. package/dist/pages/procedures.js.map +1 -0
  84. package/dist/pages/runs.d.ts +11 -0
  85. package/dist/pages/runs.js +61 -0
  86. package/dist/pages/runs.js.map +1 -0
  87. package/dist/routes/action-types.d.ts +23 -0
  88. package/dist/routes/action-types.js +80 -0
  89. package/dist/routes/action-types.js.map +1 -0
  90. package/dist/routes/data-node-types.d.ts +6 -0
  91. package/dist/routes/data-node-types.js +36 -0
  92. package/dist/routes/data-node-types.js.map +1 -0
  93. package/dist/routes/graphSchema.d.ts +92 -0
  94. package/dist/routes/graphSchema.js +60 -0
  95. package/dist/routes/graphSchema.js.map +1 -0
  96. package/dist/routes/index.d.ts +8 -0
  97. package/dist/routes/index.js +11 -0
  98. package/dist/routes/index.js.map +1 -0
  99. package/dist/routes/node-kinds.d.ts +9 -0
  100. package/dist/routes/node-kinds.js +35 -0
  101. package/dist/routes/node-kinds.js.map +1 -0
  102. package/dist/routes/procedures.d.ts +23 -0
  103. package/dist/routes/procedures.js +181 -0
  104. package/dist/routes/procedures.js.map +1 -0
  105. package/dist/routes/runs.d.ts +7 -0
  106. package/dist/routes/runs.js +81 -0
  107. package/dist/routes/runs.js.map +1 -0
  108. package/dist/routes/stats.d.ts +6 -0
  109. package/dist/routes/stats.js +35 -0
  110. package/dist/routes/stats.js.map +1 -0
  111. package/dist/routes/templates.d.ts +20 -0
  112. package/dist/routes/templates.js +243 -0
  113. package/dist/routes/templates.js.map +1 -0
  114. package/dist/routes/trigger-types.d.ts +24 -0
  115. package/dist/routes/trigger-types.js +80 -0
  116. package/dist/routes/trigger-types.js.map +1 -0
  117. package/dist/routes/typeConfigShared.d.ts +22 -0
  118. package/dist/routes/typeConfigShared.js +37 -0
  119. package/dist/routes/typeConfigShared.js.map +1 -0
  120. package/dist/runtime/builtins/actions/http.d.ts +13 -0
  121. package/dist/runtime/builtins/actions/http.js +47 -0
  122. package/dist/runtime/builtins/actions/http.js.map +1 -0
  123. package/dist/runtime/builtins/actions/index.d.ts +2 -0
  124. package/dist/runtime/builtins/actions/index.js +7 -0
  125. package/dist/runtime/builtins/actions/index.js.map +1 -0
  126. package/dist/runtime/builtins/actions/log.d.ts +13 -0
  127. package/dist/runtime/builtins/actions/log.js +49 -0
  128. package/dist/runtime/builtins/actions/log.js.map +1 -0
  129. package/dist/runtime/builtins/data/boolean.d.ts +2 -0
  130. package/dist/runtime/builtins/data/boolean.js +39 -0
  131. package/dist/runtime/builtins/data/boolean.js.map +1 -0
  132. package/dist/runtime/builtins/data/compare.d.ts +2 -0
  133. package/dist/runtime/builtins/data/compare.js +29 -0
  134. package/dist/runtime/builtins/data/compare.js.map +1 -0
  135. package/dist/runtime/builtins/data/constant.d.ts +2 -0
  136. package/dist/runtime/builtins/data/constant.js +29 -0
  137. package/dist/runtime/builtins/data/constant.js.map +1 -0
  138. package/dist/runtime/builtins/data/index.d.ts +2 -0
  139. package/dist/runtime/builtins/data/index.js +20 -0
  140. package/dist/runtime/builtins/data/index.js.map +1 -0
  141. package/dist/runtime/builtins/data/json.d.ts +2 -0
  142. package/dist/runtime/builtins/data/json.js +46 -0
  143. package/dist/runtime/builtins/data/json.js.map +1 -0
  144. package/dist/runtime/builtins/data/math.d.ts +2 -0
  145. package/dist/runtime/builtins/data/math.js +53 -0
  146. package/dist/runtime/builtins/data/math.js.map +1 -0
  147. package/dist/runtime/builtins/data/object.d.ts +2 -0
  148. package/dist/runtime/builtins/data/object.js +121 -0
  149. package/dist/runtime/builtins/data/object.js.map +1 -0
  150. package/dist/runtime/builtins/data/string.d.ts +2 -0
  151. package/dist/runtime/builtins/data/string.js +143 -0
  152. package/dist/runtime/builtins/data/string.js.map +1 -0
  153. package/dist/runtime/builtins/index.d.ts +17 -0
  154. package/dist/runtime/builtins/index.js +24 -0
  155. package/dist/runtime/builtins/index.js.map +1 -0
  156. package/dist/runtime/builtins/nodes/action.d.ts +1 -0
  157. package/dist/runtime/builtins/nodes/action.js +36 -0
  158. package/dist/runtime/builtins/nodes/action.js.map +1 -0
  159. package/dist/runtime/builtins/nodes/data.d.ts +1 -0
  160. package/dist/runtime/builtins/nodes/data.js +28 -0
  161. package/dist/runtime/builtins/nodes/data.js.map +1 -0
  162. package/dist/runtime/builtins/nodes/delay.d.ts +1 -0
  163. package/dist/runtime/builtins/nodes/delay.js +41 -0
  164. package/dist/runtime/builtins/nodes/delay.js.map +1 -0
  165. package/dist/runtime/builtins/nodes/forRange.d.ts +1 -0
  166. package/dist/runtime/builtins/nodes/forRange.js +52 -0
  167. package/dist/runtime/builtins/nodes/forRange.js.map +1 -0
  168. package/dist/runtime/builtins/nodes/foreach.d.ts +1 -0
  169. package/dist/runtime/builtins/nodes/foreach.js +31 -0
  170. package/dist/runtime/builtins/nodes/foreach.js.map +1 -0
  171. package/dist/runtime/builtins/nodes/groupInput.d.ts +1 -0
  172. package/dist/runtime/builtins/nodes/groupInput.js +11 -0
  173. package/dist/runtime/builtins/nodes/groupInput.js.map +1 -0
  174. package/dist/runtime/builtins/nodes/groupOutput.d.ts +1 -0
  175. package/dist/runtime/builtins/nodes/groupOutput.js +11 -0
  176. package/dist/runtime/builtins/nodes/groupOutput.js.map +1 -0
  177. package/dist/runtime/builtins/nodes/if.d.ts +1 -0
  178. package/dist/runtime/builtins/nodes/if.js +23 -0
  179. package/dist/runtime/builtins/nodes/if.js.map +1 -0
  180. package/dist/runtime/builtins/nodes/parallel.d.ts +1 -0
  181. package/dist/runtime/builtins/nodes/parallel.js +34 -0
  182. package/dist/runtime/builtins/nodes/parallel.js.map +1 -0
  183. package/dist/runtime/builtins/nodes/retry.d.ts +1 -0
  184. package/dist/runtime/builtins/nodes/retry.js +46 -0
  185. package/dist/runtime/builtins/nodes/retry.js.map +1 -0
  186. package/dist/runtime/builtins/nodes/setVariable.d.ts +1 -0
  187. package/dist/runtime/builtins/nodes/setVariable.js +31 -0
  188. package/dist/runtime/builtins/nodes/setVariable.js.map +1 -0
  189. package/dist/runtime/builtins/nodes/switch.d.ts +1 -0
  190. package/dist/runtime/builtins/nodes/switch.js +33 -0
  191. package/dist/runtime/builtins/nodes/switch.js.map +1 -0
  192. package/dist/runtime/builtins/nodes/trigger.d.ts +1 -0
  193. package/dist/runtime/builtins/nodes/trigger.js +25 -0
  194. package/dist/runtime/builtins/nodes/trigger.js.map +1 -0
  195. package/dist/runtime/builtins/nodes/tryCatch.d.ts +1 -0
  196. package/dist/runtime/builtins/nodes/tryCatch.js +35 -0
  197. package/dist/runtime/builtins/nodes/tryCatch.js.map +1 -0
  198. package/dist/runtime/builtins/triggers/cron.d.ts +9 -0
  199. package/dist/runtime/builtins/triggers/cron.js +52 -0
  200. package/dist/runtime/builtins/triggers/cron.js.map +1 -0
  201. package/dist/runtime/builtins/triggers/index.d.ts +2 -0
  202. package/dist/runtime/builtins/triggers/index.js +12 -0
  203. package/dist/runtime/builtins/triggers/index.js.map +1 -0
  204. package/dist/runtime/builtins/triggers/manual.d.ts +3 -0
  205. package/dist/runtime/builtins/triggers/manual.js +20 -0
  206. package/dist/runtime/builtins/triggers/manual.js.map +1 -0
  207. package/dist/runtime/builtins/triggers/webhook.d.ts +14 -0
  208. package/dist/runtime/builtins/triggers/webhook.js +90 -0
  209. package/dist/runtime/builtins/triggers/webhook.js.map +1 -0
  210. package/dist/runtime/executionResult.d.ts +6 -0
  211. package/dist/runtime/executionResult.js +3 -0
  212. package/dist/runtime/executionResult.js.map +1 -0
  213. package/dist/runtime/executor.d.ts +9 -0
  214. package/dist/runtime/executor.js +300 -0
  215. package/dist/runtime/executor.js.map +1 -0
  216. package/dist/runtime/flatten.d.ts +3 -0
  217. package/dist/runtime/flatten.js +188 -0
  218. package/dist/runtime/flatten.js.map +1 -0
  219. package/dist/runtime/nodeKinds.d.ts +64 -0
  220. package/dist/runtime/nodeKinds.js +43 -0
  221. package/dist/runtime/nodeKinds.js.map +1 -0
  222. package/dist/runtime/reconcileDiff.d.ts +9 -0
  223. package/dist/runtime/reconcileDiff.js +26 -0
  224. package/dist/runtime/reconcileDiff.js.map +1 -0
  225. package/dist/runtime/registry.d.ts +19 -0
  226. package/dist/runtime/registry.js +47 -0
  227. package/dist/runtime/registry.js.map +1 -0
  228. package/dist/runtime/resolveInputs.d.ts +14 -0
  229. package/dist/runtime/resolveInputs.js +64 -0
  230. package/dist/runtime/resolveInputs.js.map +1 -0
  231. package/dist/runtime/resolveSubgraph.d.ts +7 -0
  232. package/dist/runtime/resolveSubgraph.js +15 -0
  233. package/dist/runtime/resolveSubgraph.js.map +1 -0
  234. package/dist/runtime/subscriptions.d.ts +16 -0
  235. package/dist/runtime/subscriptions.js +419 -0
  236. package/dist/runtime/subscriptions.js.map +1 -0
  237. package/dist/runtime/subwalk.d.ts +17 -0
  238. package/dist/runtime/subwalk.js +74 -0
  239. package/dist/runtime/subwalk.js.map +1 -0
  240. package/dist/runtime/topo.d.ts +3 -0
  241. package/dist/runtime/topo.js +75 -0
  242. package/dist/runtime/topo.js.map +1 -0
  243. package/dist/runtime/typeOrigin.d.ts +7 -0
  244. package/dist/runtime/typeOrigin.js +24 -0
  245. package/dist/runtime/typeOrigin.js.map +1 -0
  246. package/dist/runtime/validate.d.ts +10 -0
  247. package/dist/runtime/validate.js +185 -0
  248. package/dist/runtime/validate.js.map +1 -0
  249. package/dist/runtime/validateTemplate.d.ts +3 -0
  250. package/dist/runtime/validateTemplate.js +54 -0
  251. package/dist/runtime/validateTemplate.js.map +1 -0
  252. package/dist/types/constants.d.ts +6 -0
  253. package/dist/types/constants.js +10 -0
  254. package/dist/types/constants.js.map +1 -0
  255. package/dist/types/graph.d.ts +51 -0
  256. package/dist/types/graph.js +23 -0
  257. package/dist/types/graph.js.map +1 -0
  258. package/dist/types/pagination.d.ts +8 -0
  259. package/dist/types/pagination.js +3 -0
  260. package/dist/types/pagination.js.map +1 -0
  261. package/dist/types/runLog.d.ts +26 -0
  262. package/dist/types/runLog.js +3 -0
  263. package/dist/types/runLog.js.map +1 -0
  264. package/frontend-vue/.prettierignore +4 -0
  265. package/frontend-vue/app/components/Actions.vue +141 -0
  266. package/frontend-vue/app/components/Catalog/TypeConfigForm.vue +166 -0
  267. package/frontend-vue/app/components/Catalog/TypeList.vue +198 -0
  268. package/frontend-vue/app/components/DataNodes.vue +259 -0
  269. package/frontend-vue/app/components/Editor/BuilderPalette.vue +234 -0
  270. package/frontend-vue/app/components/Editor/GraphCanvas.vue +994 -0
  271. package/frontend-vue/app/components/Editor/GroupPortEditor.vue +289 -0
  272. package/frontend-vue/app/components/Editor/JsonField.vue +63 -0
  273. package/frontend-vue/app/components/Editor/NodeInspector.vue +356 -0
  274. package/frontend-vue/app/components/Editor/ProcedureList.vue +156 -0
  275. package/frontend-vue/app/components/Editor/RunsDrawer.vue +312 -0
  276. package/frontend-vue/app/components/Editor/WiredField.vue +42 -0
  277. package/frontend-vue/app/components/Editor/nodes/GenericNode.vue +161 -0
  278. package/frontend-vue/app/components/Editor/nodes/GroupInputNode.vue +19 -0
  279. package/frontend-vue/app/components/Editor/nodes/GroupNode.vue +200 -0
  280. package/frontend-vue/app/components/Editor/nodes/GroupOutputNode.vue +19 -0
  281. package/frontend-vue/app/components/Editor/nodes/GroupSentinel.vue +161 -0
  282. package/frontend-vue/app/components/Editor/nodes/styles.ts +53 -0
  283. package/frontend-vue/app/components/Editor.vue +2504 -0
  284. package/frontend-vue/app/components/Library.vue +67 -0
  285. package/frontend-vue/app/components/Overview.vue +503 -0
  286. package/frontend-vue/app/components/RunDetailDrawer.vue +165 -0
  287. package/frontend-vue/app/components/RunFireTree.vue +170 -0
  288. package/frontend-vue/app/components/RunTraceDrawer.vue +59 -0
  289. package/frontend-vue/app/components/RunsStats.vue +126 -0
  290. package/frontend-vue/app/components/RunsTimelineDisplay.vue +287 -0
  291. package/frontend-vue/app/components/Templates.vue +663 -0
  292. package/frontend-vue/app/components/Triggers.vue +137 -0
  293. package/frontend-vue/app/composables/useAutomationNodeKinds.ts +48 -0
  294. package/frontend-vue/app/composables/useAutomationRuns.ts +75 -0
  295. package/frontend-vue/app/composables/useGraphConnect.ts +542 -0
  296. package/frontend-vue/app/plugins/runs-timeline-display.client.ts +16 -0
  297. package/frontend-vue/app/utils/automation.ts +51 -0
  298. package/frontend-vue/dms.frontend.ts +26 -0
  299. package/frontend-vue/eslint.config.mjs +24 -0
  300. package/frontend-vue/i18n/locales/dms-automation-en-GB.json +369 -0
  301. package/frontend-vue/i18n/locales/dms-automation-fr-FR.json +369 -0
  302. package/frontend-vue/package.json +33 -0
  303. package/frontend-vue/pnpm-lock.yaml +6483 -0
  304. package/frontend-vue/pnpm-workspace.yaml +2 -0
  305. package/package.json +81 -0
@@ -0,0 +1,156 @@
1
+ <script setup lang="ts">
2
+ import { ref, watch } from 'vue'
3
+
4
+ interface ProcedureListItem {
5
+ _id: string
6
+ name: string
7
+ enabled: boolean
8
+ }
9
+
10
+ const props = defineProps<{
11
+ procedures: ProcedureListItem[]
12
+ modelValue: string | null
13
+ }>()
14
+
15
+ const emit = defineEmits(['update:modelValue', 'create', 'delete'])
16
+
17
+ const confirmOpen = ref(false)
18
+ const pendingDeleteId = ref<string | null>(null)
19
+ const pendingDeleteName = ref<string>('')
20
+
21
+ function select(id: string) {
22
+ const next = props.modelValue === id ? null : id
23
+ emit('update:modelValue', next)
24
+ }
25
+
26
+ function askDelete(p: ProcedureListItem) {
27
+ pendingDeleteId.value = p._id
28
+ pendingDeleteName.value = p.name
29
+ confirmOpen.value = true
30
+ }
31
+
32
+ function confirmDelete() {
33
+ const id = pendingDeleteId.value
34
+ if (id) {
35
+ emit('delete', id)
36
+ }
37
+ confirmOpen.value = false
38
+ }
39
+
40
+ function cancelDelete() {
41
+ confirmOpen.value = false
42
+ }
43
+
44
+ // Reset pending state whenever the modal closes (via any means).
45
+ watch(confirmOpen, (open) => {
46
+ if (!open) {
47
+ pendingDeleteId.value = null
48
+ pendingDeleteName.value = ''
49
+ }
50
+ })
51
+
52
+ const isSelected = (id: string) => props.modelValue === id
53
+ </script>
54
+
55
+ <template>
56
+ <div class="flex flex-col gap-2">
57
+ <div class="flex flex-wrap items-center justify-between gap-2">
58
+ <div class="text-sm font-semibold text-highlighted">
59
+ {{ $t('dms_automation.editor.procedureList.title') }}
60
+ </div>
61
+ <UButton
62
+ size="xs"
63
+ icon="i-ph-plus"
64
+ color="primary"
65
+ variant="soft"
66
+ class="shrink-0"
67
+ @click="emit('create')"
68
+ >
69
+ {{ $t('dms_automation.editor.procedureList.new') }}
70
+ </UButton>
71
+ </div>
72
+
73
+ <div
74
+ v-if="!procedures || procedures.length === 0"
75
+ class="px-2 py-6 text-center text-sm text-dimmed"
76
+ >
77
+ {{ $t('dms_automation.editor.procedureList.empty') }}
78
+ </div>
79
+ <ul v-else class="flex flex-col gap-1">
80
+ <li v-for="p in procedures" :key="p._id">
81
+ <div
82
+ class="flex w-full items-center gap-2 rounded-lg px-2 py-1.5 transition-colors"
83
+ :class="
84
+ isSelected(p._id)
85
+ ? 'bg-primary/10 ring-1 ring-primary/20'
86
+ : 'hover:bg-elevated/60'
87
+ "
88
+ >
89
+ <button
90
+ type="button"
91
+ class="flex min-w-0 flex-1 items-center gap-2 text-left"
92
+ @click="select(p._id)"
93
+ >
94
+ <div class="min-w-0 flex-1">
95
+ <div
96
+ class="truncate text-sm font-medium"
97
+ :class="isSelected(p._id) ? 'text-primary' : 'text-highlighted'"
98
+ >
99
+ {{ p.name }}
100
+ </div>
101
+ </div>
102
+ <UBadge
103
+ :color="p.enabled ? 'success' : 'neutral'"
104
+ variant="subtle"
105
+ size="xs"
106
+ >
107
+ {{
108
+ p.enabled
109
+ ? $t('dms_automation.editor.procedureList.enabled')
110
+ : $t('dms_automation.editor.procedureList.disabled')
111
+ }}
112
+ </UBadge>
113
+ </button>
114
+ <UButton
115
+ size="xs"
116
+ icon="i-ph-trash"
117
+ color="error"
118
+ variant="ghost"
119
+ :aria-label="$t('dms_automation.editor.procedureList.deleteAria')"
120
+ @click.stop="askDelete(p)"
121
+ />
122
+ </div>
123
+ </li>
124
+ </ul>
125
+
126
+ <UModal
127
+ v-model:open="confirmOpen"
128
+ :title="$t('dms_automation.editor.procedureList.deleteTitle')"
129
+ >
130
+ <template #body>
131
+ <p class="text-muted">
132
+ {{
133
+ $t('dms_automation.editor.procedureList.deleteConfirm', {
134
+ name: pendingDeleteName,
135
+ })
136
+ }}
137
+ </p>
138
+ </template>
139
+ <template #footer>
140
+ <div class="flex w-full justify-end gap-2">
141
+ <UButton
142
+ :label="$t('dms_automation.editor.procedureList.cancel')"
143
+ variant="outline"
144
+ color="neutral"
145
+ @click="cancelDelete"
146
+ />
147
+ <UButton
148
+ :label="$t('dms_automation.editor.procedureList.delete')"
149
+ color="error"
150
+ @click="confirmDelete"
151
+ />
152
+ </div>
153
+ </template>
154
+ </UModal>
155
+ </div>
156
+ </template>
@@ -0,0 +1,312 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref, watch } from 'vue'
3
+ import RunDetailDrawer from '../RunDetailDrawer.vue'
4
+ import { useAutomationRuns } from '../../composables/useAutomationRuns'
5
+ import { type ListEnvelope, unwrapList } from '../../utils/automation'
6
+
7
+ interface RunRecord {
8
+ _id: string
9
+ procedureId: string
10
+ startedAt: string | Date
11
+ endedAt?: string | Date | null
12
+ status: string
13
+ errorMessage?: string | null
14
+ triggerNodeId?: string
15
+ triggerPayload?: string
16
+ }
17
+
18
+ const props = defineProps<{
19
+ procedureId: string | null
20
+ procedureName?: string
21
+ }>()
22
+
23
+ const { $authFetch } = useAuthFetch()
24
+ // DMS-themed drawer from the dms layer (dms ≥0.0.26, public API replacing the
25
+ // removed useSheets/addSheet). Opens the run-detail view sliding in from the
26
+ // right; `open` marks the body component raw and generates a containerId.
27
+ const { open: openRunDrawer } = useDrawer()
28
+ const { getRun } = useAutomationRuns()
29
+ const { t } = useI18n()
30
+
31
+ const PAGE_SIZE = 10
32
+
33
+ const runs = ref<RunRecord[]>([])
34
+ const loading = ref(false)
35
+ const open = ref(false)
36
+ const error = ref<string | null>(null)
37
+ const loadingDetailId = ref<string | null>(null)
38
+ const detailError = ref<string | null>(null)
39
+ const page = ref(0)
40
+ const hasMore = ref(false)
41
+
42
+ async function load(target = 0) {
43
+ if (!props.procedureId) {
44
+ runs.value = []
45
+ hasMore.value = false
46
+ page.value = 0
47
+ return
48
+ }
49
+ const p = Math.max(0, target)
50
+ loading.value = true
51
+ error.value = null
52
+ try {
53
+ const data = await $authFetch<RunRecord[] | ListEnvelope<RunRecord>>(
54
+ `/api/automation/procedures/${props.procedureId}/runs?page=${p}&limit=${PAGE_SIZE}`,
55
+ )
56
+ // The API over-fetches one row beyond PAGE_SIZE as a next-page probe;
57
+ // trim it for display and use its presence for `hasMore`, so an
58
+ // exactly-full final page never enables a dead "Next".
59
+ const list = unwrapList<RunRecord>(data)
60
+ runs.value = list.slice(0, PAGE_SIZE)
61
+ page.value = p
62
+ hasMore.value = list.length > PAGE_SIZE
63
+ } catch (e) {
64
+ error.value = (e as Error).message ?? 'Failed to load runs'
65
+ runs.value = []
66
+ hasMore.value = false
67
+ } finally {
68
+ loading.value = false
69
+ }
70
+ }
71
+
72
+ watch(
73
+ () => props.procedureId,
74
+ () => {
75
+ void load(0)
76
+ },
77
+ { immediate: true },
78
+ )
79
+
80
+ // Reset to the first page when the panel closes so the trigger badge always
81
+ // reflects the most recent runs, not whatever page was left open.
82
+ watch(open, (isOpen) => {
83
+ if (!isOpen && page.value !== 0) void load(0)
84
+ })
85
+
86
+ // Let the editor refresh the list (and the trigger badge) after "Run now".
87
+ defineExpose({ reload: () => load(0) })
88
+
89
+ function fmtStarted(v: string | Date | null | undefined): string {
90
+ if (!v) return '—'
91
+ try {
92
+ return new Date(v).toLocaleString()
93
+ } catch {
94
+ return String(v)
95
+ }
96
+ }
97
+
98
+ function fmtDuration(
99
+ startedAt: string | Date | null | undefined,
100
+ endedAt: string | Date | null | undefined,
101
+ ): string {
102
+ if (!endedAt || !startedAt) return '—'
103
+ try {
104
+ const s = new Date(startedAt).getTime()
105
+ const e = new Date(endedAt).getTime()
106
+ if (Number.isNaN(s) || Number.isNaN(e)) return '—'
107
+ return `${e - s} ms`
108
+ } catch {
109
+ return '—'
110
+ }
111
+ }
112
+
113
+ function statusIcon(status: string): { name: string; color: string } {
114
+ if (status === 'ok')
115
+ return { name: 'i-ph-check-circle', color: 'text-success' }
116
+ if (status === 'failed')
117
+ return { name: 'i-ph-x-circle', color: 'text-error' }
118
+ return { name: 'i-ph-spinner', color: 'text-warning' }
119
+ }
120
+
121
+ function truncate(s: string | null | undefined, n: number): string {
122
+ if (!s) return '—'
123
+ if (s.length <= n) return s
124
+ return `${s.slice(0, n)}…`
125
+ }
126
+
127
+ const headerText = computed(() => {
128
+ if (!props.procedureId) return t('dms_automation.editor.runsDrawer.title')
129
+ if (loading.value) return t('dms_automation.editor.runsDrawer.loading')
130
+ return t('dms_automation.editor.runsDrawer.count', { n: runs.value.length })
131
+ })
132
+
133
+ async function onRefresh() {
134
+ await load()
135
+ }
136
+
137
+ async function openDetail(r: RunRecord) {
138
+ if (loadingDetailId.value === r._id) return
139
+ loadingDetailId.value = r._id
140
+ detailError.value = null
141
+ try {
142
+ // Bubble fetch errors up to the drawer (instead of pretending the
143
+ // summary is the detail — the fire tree would just render empty).
144
+ const full = await getRun(r._id)
145
+ openRunDrawer({
146
+ containerId: `dms-automation-run-${r._id}`,
147
+ title: `${r.status.toUpperCase()} · ${props.procedureName ?? r.procedureId}`,
148
+ description: new Date(r.startedAt).toLocaleString(),
149
+ direction: 'right',
150
+ component: RunDetailDrawer,
151
+ componentOptions: {
152
+ run: full,
153
+ procedureName: props.procedureName,
154
+ },
155
+ })
156
+ // Intentionally keep the runs list open BEHIND the detail. Closing it
157
+ // here (open.value = false) made the just-opened detail vanish ~a tick
158
+ // later — tearing down the runs USlideover cascades into the detail
159
+ // overlay. The detail is a separate dms `useDrawer` (a dismissible:false
160
+ // UDrawer) closed only via its own control, so leaving the list mounted
161
+ // lets you inspect runs back to back. Trade-off: while a detail is open
162
+ // the drawer stacks above the still-mounted list.
163
+ } catch (e) {
164
+ const msg = (e as Error).message ?? 'Failed to load run'
165
+ detailError.value = msg
166
+ console.error('[dms-automation] failed to open run detail', e)
167
+ } finally {
168
+ loadingDetailId.value = null
169
+ }
170
+ }
171
+ </script>
172
+
173
+ <template>
174
+ <UButton
175
+ icon="i-ph-clock-counter-clockwise"
176
+ variant="outline"
177
+ color="neutral"
178
+ :disabled="!procedureId"
179
+ @click="open = true"
180
+ >
181
+ {{ $t('dms_automation.editor.runsDrawer.title') }}
182
+ <UBadge
183
+ v-if="runs.length"
184
+ :label="hasMore ? `${runs.length}+` : String(runs.length)"
185
+ color="neutral"
186
+ variant="subtle"
187
+ size="sm"
188
+ />
189
+ </UButton>
190
+
191
+ <USlideover v-model:open="open" side="right" :title="headerText">
192
+ <template #body>
193
+ <div class="flex flex-col gap-2">
194
+ <div class="flex items-center justify-between">
195
+ <div class="text-xs text-dimmed">
196
+ <span v-if="error" class="text-error">{{ error }}</span>
197
+ <span v-else-if="detailError" class="text-error">{{ detailError }}</span>
198
+ <span v-else-if="!procedureId">
199
+ {{ $t('dms_automation.editor.runsDrawer.selectProcedure') }}
200
+ </span>
201
+ <span v-else-if="loading">
202
+ {{ $t('dms_automation.editor.runsDrawer.loadingShort') }}
203
+ </span>
204
+ <span v-else>
205
+ {{ $t('dms_automation.editor.runsDrawer.runCount', { n: runs.length }) }}
206
+ </span>
207
+ </div>
208
+ <UButton
209
+ size="xs"
210
+ variant="ghost"
211
+ color="neutral"
212
+ icon="i-ph-arrows-clockwise"
213
+ :loading="loading"
214
+ :disabled="!procedureId"
215
+ @click="onRefresh"
216
+ >
217
+ {{ $t('dms_automation.editor.runsDrawer.refresh') }}
218
+ </UButton>
219
+ </div>
220
+
221
+ <div
222
+ v-if="runs.length > 0"
223
+ class="overflow-hidden rounded-lg border border-default"
224
+ >
225
+ <table class="w-full text-xs">
226
+ <thead>
227
+ <tr class="border-b border-default bg-muted">
228
+ <th class="w-12 px-3 py-2 text-left font-semibold text-dimmed">
229
+ {{ $t('dms_automation.editor.runsDrawer.cols.status') }}
230
+ </th>
231
+ <th class="px-3 py-2 text-left font-semibold text-dimmed">
232
+ {{ $t('dms_automation.editor.runsDrawer.cols.started') }}
233
+ </th>
234
+ <th class="px-3 py-2 text-left font-semibold text-dimmed">
235
+ {{ $t('dms_automation.editor.runsDrawer.cols.duration') }}
236
+ </th>
237
+ <th class="px-3 py-2 text-left font-semibold text-dimmed">
238
+ {{ $t('dms_automation.editor.runsDrawer.cols.error') }}
239
+ </th>
240
+ </tr>
241
+ </thead>
242
+ <tbody>
243
+ <tr
244
+ v-for="r in runs"
245
+ :key="r._id"
246
+ class="cursor-pointer border-b border-default/60 transition-colors last:border-0 hover:bg-elevated/40"
247
+ :class="{ 'opacity-60': loadingDetailId === r._id }"
248
+ @click="openDetail(r)"
249
+ >
250
+ <td class="px-3 py-2">
251
+ <UIcon
252
+ v-if="loadingDetailId === r._id"
253
+ name="i-ph-spinner"
254
+ class="animate-spin text-dimmed"
255
+ />
256
+ <UIcon
257
+ v-else
258
+ :name="statusIcon(r.status).name"
259
+ :class="statusIcon(r.status).color"
260
+ />
261
+ </td>
262
+ <td class="whitespace-nowrap px-3 py-2 tabular-nums text-toned">
263
+ {{ fmtStarted(r.startedAt) }}
264
+ </td>
265
+ <td class="whitespace-nowrap px-3 py-2 tabular-nums text-toned">
266
+ {{ fmtDuration(r.startedAt, r.endedAt) }}
267
+ </td>
268
+ <td class="px-3 py-2 text-error">
269
+ {{ truncate(r.errorMessage, 60) }}
270
+ </td>
271
+ </tr>
272
+ </tbody>
273
+ </table>
274
+ </div>
275
+
276
+ <div
277
+ v-else-if="!loading && procedureId && !error"
278
+ class="p-2 text-xs text-dimmed"
279
+ >
280
+ {{ $t('dms_automation.editor.runsDrawer.empty') }}
281
+ </div>
282
+
283
+ <div
284
+ v-if="runs.length > 0"
285
+ class="flex items-center justify-between gap-3 pt-1"
286
+ >
287
+ <UButton
288
+ size="xs"
289
+ color="neutral"
290
+ variant="ghost"
291
+ icon="i-ph-caret-left"
292
+ :label="$t('dms_automation.common.previous')"
293
+ :disabled="page === 0 || loading"
294
+ @click="load(page - 1)"
295
+ />
296
+ <span class="text-xs tabular-nums text-dimmed">
297
+ {{ $t('dms_automation.runs.pageLabel', { n: page + 1 }) }}
298
+ </span>
299
+ <UButton
300
+ size="xs"
301
+ color="neutral"
302
+ variant="ghost"
303
+ trailing-icon="i-ph-caret-right"
304
+ :label="$t('dms_automation.common.next')"
305
+ :disabled="!hasMore || loading"
306
+ @click="load(page + 1)"
307
+ />
308
+ </div>
309
+ </div>
310
+ </template>
311
+ </USlideover>
312
+ </template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ interface Source {
3
+ node: string
4
+ port: string
5
+ }
6
+
7
+ defineProps<{
8
+ field: string
9
+ source: Source
10
+ sourceLabel?: string
11
+ }>()
12
+
13
+ const emit = defineEmits<{
14
+ (e: 'unwire'): void
15
+ }>()
16
+
17
+ function onUnwire() {
18
+ emit('unwire')
19
+ }
20
+ </script>
21
+
22
+ <template>
23
+ <div
24
+ class="flex items-center gap-2 rounded-lg border border-default bg-elevated px-2 py-1.5"
25
+ >
26
+ <UIcon name="i-ph-plugs-connected" class="size-4 text-success" />
27
+ <span class="min-w-0 flex-1 truncate text-xs text-toned">
28
+ {{ $t('dms_automation.editor.wiredField.wiredFrom') }}
29
+ <span class="font-mono font-medium text-highlighted">{{ sourceLabel ?? source.node }}.{{ source.port }}</span>
30
+ </span>
31
+ <UButton
32
+ size="xs"
33
+ variant="ghost"
34
+ color="error"
35
+ icon="i-ph-x"
36
+ :aria-label="$t('dms_automation.editor.wiredField.unwire')"
37
+ @click="onUnwire"
38
+ >
39
+ {{ $t('dms_automation.editor.wiredField.unwire') }}
40
+ </UButton>
41
+ </div>
42
+ </template>
@@ -0,0 +1,161 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import { Handle, Position } from '@vue-flow/core'
4
+
5
+ interface PortRef {
6
+ name: string
7
+ type?: string
8
+ }
9
+
10
+ interface NodeData {
11
+ label?: string
12
+ icon?: string
13
+ /** Small uppercase badge in the top-right of the header (data nodes). */
14
+ category?: string
15
+ /** Render the trigger-in handle on the header's left. Default true. */
16
+ hasTriggerIn?: boolean
17
+ /** Render the trigger-out `main` handle on the header's right. Default true. */
18
+ hasMainTriggerOut?: boolean
19
+ /**
20
+ * Non-main trigger-out ports. Rendered as body rows top-to-bottom,
21
+ * paired with `dataIns` left-to-right (per the asserted port
22
+ * convention: trigger ports first, no gap from data-ins on same row).
23
+ */
24
+ triggerOuts?: string[]
25
+ /** Data inputs. Left-aligned. Paired with trigger-outs / data-outs. */
26
+ dataIns?: PortRef[]
27
+ /** Data outputs. Right-aligned. Render below all trigger-outs. */
28
+ dataOuts?: PortRef[]
29
+ }
30
+
31
+ const props = defineProps<{
32
+ id: string
33
+ data: NodeData
34
+ selected?: boolean
35
+ }>()
36
+
37
+ const hasTriggerIn = computed(() => props.data?.hasTriggerIn !== false)
38
+ const hasMainTriggerOut = computed(() => props.data?.hasMainTriggerOut !== false)
39
+ const triggerOuts = computed<string[]>(() => props.data?.triggerOuts ?? [])
40
+ const dataIns = computed<PortRef[]>(() => props.data?.dataIns ?? [])
41
+ const dataOuts = computed<PortRef[]>(() => props.data?.dataOuts ?? [])
42
+
43
+ import { dataStyle, triggerStyle } from './styles'
44
+
45
+ interface BodyRow {
46
+ leftDataIn?: PortRef
47
+ rightTriggerOut?: string
48
+ rightDataOut?: PortRef
49
+ }
50
+
51
+ // Body layout (per the convention):
52
+ // Phase 1: each trigger-out, top-to-bottom, paired with the next available
53
+ // data-in on the same row (left-aligned). No gap.
54
+ // Phase 2: data-outs (and any leftover data-ins) row-by-row, action-style
55
+ // (input[i] left, output[i] right), filling remaining space.
56
+ const rows = computed<BodyRow[]>(() => {
57
+ const r: BodyRow[] = []
58
+ const ti = [...triggerOuts.value]
59
+ const di = [...dataIns.value]
60
+ const dout = [...dataOuts.value]
61
+
62
+ // Phase 1
63
+ while (ti.length > 0) {
64
+ r.push({
65
+ leftDataIn: di.shift(),
66
+ rightTriggerOut: ti.shift(),
67
+ })
68
+ }
69
+
70
+ // Phase 2 — pair any leftover data-ins with data-outs.
71
+ const remaining = Math.max(di.length, dout.length)
72
+ for (let i = 0; i < remaining; i++) {
73
+ r.push({ leftDataIn: di[i], rightDataOut: dout[i] })
74
+ }
75
+
76
+ return r
77
+ })
78
+ </script>
79
+
80
+ <template>
81
+ <div
82
+ class="dms-automation-node generic-node relative min-w-[180px] rounded-lg border bg-default shadow-sm"
83
+ :class="
84
+ selected
85
+ ? 'border-primary ring-1 ring-primary'
86
+ : 'border-default'
87
+ "
88
+ >
89
+ <div
90
+ class="relative flex items-center gap-2 rounded-t-lg border-b border-default bg-elevated px-3 py-2"
91
+ >
92
+ <Handle
93
+ v-if="hasTriggerIn"
94
+ id="trigger-in"
95
+ type="target"
96
+ :position="Position.Left"
97
+ :style="triggerStyle"
98
+ />
99
+ <UIcon
100
+ :name="data.icon || 'i-ph-circle'"
101
+ class="size-4 text-primary"
102
+ />
103
+ <div class="truncate text-sm font-medium text-highlighted">
104
+ {{ data.label || 'Node' }}
105
+ </div>
106
+ <div
107
+ v-if="data.category"
108
+ class="ml-auto text-[10px] uppercase text-dimmed"
109
+ >
110
+ {{ data.category }}
111
+ </div>
112
+ <Handle
113
+ v-if="hasMainTriggerOut"
114
+ id="trigger-out-main"
115
+ type="source"
116
+ :position="Position.Right"
117
+ :style="triggerStyle"
118
+ />
119
+ </div>
120
+
121
+ <div v-if="rows.length > 0" class="py-2 text-xs text-dimmed">
122
+ <div
123
+ v-for="(row, i) in rows"
124
+ :key="i"
125
+ class="relative flex items-stretch py-1"
126
+ >
127
+ <div class="flex-1 flex items-center gap-1 pl-3">
128
+ <template v-if="row.leftDataIn">
129
+ <Handle
130
+ :id="`data-in-${row.leftDataIn.name}`"
131
+ type="target"
132
+ :position="Position.Left"
133
+ :style="dataStyle"
134
+ />
135
+ <span>{{ row.leftDataIn.name }}</span>
136
+ </template>
137
+ </div>
138
+ <div class="flex-1 flex items-center justify-end gap-1 pr-3">
139
+ <template v-if="row.rightTriggerOut">
140
+ <span>{{ row.rightTriggerOut }}</span>
141
+ <Handle
142
+ :id="`trigger-out-${row.rightTriggerOut}`"
143
+ type="source"
144
+ :position="Position.Right"
145
+ :style="triggerStyle"
146
+ />
147
+ </template>
148
+ <template v-else-if="row.rightDataOut">
149
+ <span>{{ row.rightDataOut.name }}</span>
150
+ <Handle
151
+ :id="`data-out-${row.rightDataOut.name}`"
152
+ type="source"
153
+ :position="Position.Right"
154
+ :style="dataStyle"
155
+ />
156
+ </template>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { GroupPort } from '../../../composables/useGraphConnect'
3
+ import GroupSentinel from './GroupSentinel.vue'
4
+
5
+ const props = defineProps<{
6
+ id: string
7
+ data: { ports?: GroupPort[] }
8
+ selected?: boolean
9
+ }>()
10
+ </script>
11
+
12
+ <template>
13
+ <GroupSentinel
14
+ :id="props.id"
15
+ side="in"
16
+ :data="props.data"
17
+ :selected="props.selected"
18
+ />
19
+ </template>