@gadmin2n/schematics 0.0.72 → 0.0.75

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 (173) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +2 -0
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/job.prisma +62 -0
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +0 -21
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +171 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/AgendaJob.ts +60 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +1 -1
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +62 -0
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeInstance.ts +62 -0
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeType.ts +62 -0
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +5 -0
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -4
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +14 -7
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +4 -0
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +49 -3
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +746 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +786 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +6 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.service.ts +79 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.spec.ts +20 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.ts +145 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.module.ts +10 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/{canvas/canvas.service.spec.ts → agendaJob/agendaJob.service.spec.ts} +71 -65
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.service.ts +83 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -1
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.module.ts +9 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +100 -0
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +43 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +317 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.controller.ts +16 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.service.ts +13 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +220 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +82 -0
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +16 -0
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +505 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +22 -0
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +147 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +10 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +356 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +110 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.spec.ts +22 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.ts +216 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.module.ts +10 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +356 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +168 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.spec.ts +22 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.ts +199 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.module.ts +10 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.spec.ts +348 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.ts +106 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +579 -1082
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +278 -0
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +5 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +25 -0
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +13 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/sql/create-event-trigger.sql +87 -0
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +7 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +122 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +4285 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +28 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/code-execute.test.ts +44 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/http-request.test.ts +87 -0
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/helpers.test.ts +225 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/node-type-consistency.test.ts +101 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +51 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +85 -0
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +35 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +54 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +6 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +62 -0
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +47 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +13 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +101 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +58 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +184 -0
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +133 -0
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +57 -0
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +77 -0
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +36 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +226 -0
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +411 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +19 -0
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +8 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +1905 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package-lock.json +17555 -0
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +5 -2
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +5 -1
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +1 -1
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +63 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +91 -2
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +48 -2
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +43 -2
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +14 -9
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +14 -9
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +309 -56
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/show.tsx +1 -3
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/create.tsx +108 -0
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/edit.tsx +124 -0
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/index.tsx +4 -0
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +245 -0
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/show.tsx +70 -0
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +0 -1
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +160 -2
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +120 -148
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +74 -181
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +15 -13
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +2 -2
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +338 -3
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +18 -17
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +10 -4
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +10 -4
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/{ChartViewerConfigModal.tsx → MultiChartConfigModal.tsx} +30 -18
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartDataSourceModal.tsx +427 -0
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +10 -4
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +6 -14
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +10 -4
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +10 -4
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/canvasModalProps.ts +24 -0
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +45 -63
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +99 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExportModal.tsx +87 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +322 -0
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ImportModal.tsx +175 -0
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeEditModal.tsx +60 -0
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +1150 -0
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +101 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +198 -0
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +81 -0
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +566 -0
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +224 -0
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +524 -0
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +343 -0
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +243 -0
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +363 -0
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/DynamicConfigForm.tsx +154 -0
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +176 -0
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +77 -0
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +112 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +305 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +282 -0
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +469 -0
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +92 -0
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +111 -0
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +127 -0
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +4 -0
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +254 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +74 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +1501 -1199
  151. package/package.json +1 -1
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.spec.ts +0 -22
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +0 -896
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +0 -219
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +0 -159
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +0 -192
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +0 -1034
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +0 -8
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +0 -509
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +0 -66
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +0 -552
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +0 -263
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +0 -35
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +0 -207
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +0 -382
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +0 -135
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +0 -53
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +0 -8
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +0 -1
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +0 -31
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +0 -9
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +0 -39349
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +0 -19
@@ -0,0 +1,343 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import {
3
+ Button,
4
+ Card,
5
+ Descriptions,
6
+ message,
7
+ Popconfirm,
8
+ Space,
9
+ Spin,
10
+ Steps,
11
+ Tag,
12
+ Tooltip,
13
+ Typography,
14
+ } from 'antd';
15
+ import {
16
+ ArrowLeftOutlined,
17
+ CheckCircleOutlined,
18
+ ClockCircleOutlined,
19
+ CloseCircleOutlined,
20
+ LoadingOutlined,
21
+ ReloadOutlined,
22
+ StopOutlined,
23
+ } from '@ant-design/icons';
24
+ import { useNavigate, useParams } from 'react-router-dom';
25
+ import { customRequest } from 'helpers/http';
26
+
27
+ const { Title, Text } = Typography;
28
+
29
+ const STATUS_TAG: Record<
30
+ string,
31
+ { color: string; label: string; icon: React.ReactNode }
32
+ > = {
33
+ PENDING: { color: 'gold', label: 'Pending', icon: <ClockCircleOutlined /> },
34
+ RUNNING: { color: 'blue', label: 'Running', icon: <LoadingOutlined /> },
35
+ COMPLETED: {
36
+ color: 'green',
37
+ label: 'Completed',
38
+ icon: <CheckCircleOutlined />,
39
+ },
40
+ FAILED: { color: 'red', label: 'Failed', icon: <CloseCircleOutlined /> },
41
+ CANCELLED: { color: 'default', label: 'Cancelled', icon: <StopOutlined /> },
42
+ };
43
+
44
+ interface NodeExecution {
45
+ id: string;
46
+ nodeId: string;
47
+ nodeType: string;
48
+ nodeLabel: string | null;
49
+ status: string;
50
+ input: any;
51
+ output: any;
52
+ error: any;
53
+ startedAt: string | null;
54
+ finishedAt: string | null;
55
+ }
56
+
57
+ interface InstanceDetail {
58
+ id: string;
59
+ workflowId: string;
60
+ status: string;
61
+ context: any;
62
+ result: any;
63
+ temporalRunId: string | null;
64
+ startedAt: string | null;
65
+ finishedAt: string | null;
66
+ creator: string;
67
+ createdAt: string;
68
+ workflow: { name: string };
69
+ nodeExecutions: NodeExecution[];
70
+ }
71
+
72
+ function formatDuration(start: string | null, end: string | null): string {
73
+ if (!start) return '—';
74
+ const endTime = end ? new Date(end).getTime() : Date.now();
75
+ const ms = endTime - new Date(start).getTime();
76
+ if (ms < 1000) return `${ms}ms`;
77
+ const s = Math.floor(ms / 1000);
78
+ if (s < 60) return `${s}s`;
79
+ const m = Math.floor(s / 60);
80
+ const rem = s % 60;
81
+ return rem > 0 ? `${m}m ${rem}s` : `${m}m`;
82
+ }
83
+
84
+ function getStepStatus(
85
+ status: string,
86
+ ): 'wait' | 'process' | 'finish' | 'error' {
87
+ switch (status) {
88
+ case 'COMPLETED':
89
+ return 'finish';
90
+ case 'RUNNING':
91
+ return 'process';
92
+ case 'FAILED':
93
+ return 'error';
94
+ default:
95
+ return 'wait';
96
+ }
97
+ }
98
+
99
+ export default function WorkflowInstanceDetailPage() {
100
+ const { instanceId } = useParams<{ instanceId: string }>();
101
+ const navigate = useNavigate();
102
+ const [data, setData] = useState<InstanceDetail | null>(null);
103
+ const [loading, setLoading] = useState(true);
104
+ const [actionLoading, setActionLoading] = useState(false);
105
+
106
+ const fetchData = useCallback(async () => {
107
+ if (!instanceId) return;
108
+ try {
109
+ const res = await customRequest<InstanceDetail>(
110
+ `workflow/instance/${instanceId}`,
111
+ 'GET',
112
+ );
113
+ setData(res);
114
+ } catch (e: any) {
115
+ message.error(e?.message || 'Failed to load instance');
116
+ } finally {
117
+ setLoading(false);
118
+ }
119
+ }, [instanceId]);
120
+
121
+ useEffect(() => {
122
+ fetchData();
123
+ }, [fetchData]);
124
+
125
+ // Auto-refresh for running instances
126
+ useEffect(() => {
127
+ if (data?.status === 'RUNNING' || data?.status === 'PENDING') {
128
+ const interval = setInterval(fetchData, 3000);
129
+ return () => clearInterval(interval);
130
+ }
131
+ }, [data?.status, fetchData]);
132
+
133
+ const handleCancel = async () => {
134
+ setActionLoading(true);
135
+ try {
136
+ await customRequest(`workflow/instance/${instanceId}/cancel`, 'POST');
137
+ message.success('Instance cancelled');
138
+ fetchData();
139
+ } catch (e: any) {
140
+ message.error(e?.message || 'Failed to cancel');
141
+ } finally {
142
+ setActionLoading(false);
143
+ }
144
+ };
145
+
146
+ const handleRetry = async () => {
147
+ setActionLoading(true);
148
+ try {
149
+ const res = await customRequest<{ instanceId: string }>(
150
+ `workflow/instance/${instanceId}/retry`,
151
+ 'POST',
152
+ );
153
+ message.success('Retry started');
154
+ navigate(`/admin/workflow/instance/show/${res.instanceId}`);
155
+ } catch (e: any) {
156
+ message.error(e?.message || 'Failed to retry');
157
+ } finally {
158
+ setActionLoading(false);
159
+ }
160
+ };
161
+
162
+ const handleApprove = async (nodeId: string, approved: boolean) => {
163
+ setActionLoading(true);
164
+ try {
165
+ await customRequest(`workflow/instance/${instanceId}/signal`, 'POST', {
166
+ signalName: 'approval',
167
+ payload: { nodeId, approved, approvedBy: 'current_user', comment: '' },
168
+ });
169
+ message.success(approved ? 'Approved' : 'Rejected');
170
+ fetchData();
171
+ } catch (e: any) {
172
+ message.error(e?.message || 'Failed to send signal');
173
+ } finally {
174
+ setActionLoading(false);
175
+ }
176
+ };
177
+
178
+ if (loading) {
179
+ return (
180
+ <div
181
+ style={{
182
+ display: 'flex',
183
+ justifyContent: 'center',
184
+ alignItems: 'center',
185
+ height: '100vh',
186
+ }}
187
+ >
188
+ <Spin size="large" />
189
+ </div>
190
+ );
191
+ }
192
+
193
+ if (!data) return null;
194
+
195
+ const statusCfg = STATUS_TAG[data.status] || STATUS_TAG.PENDING;
196
+
197
+ return (
198
+ <div
199
+ style={{
200
+ background: '#f0f2f5',
201
+ minHeight: 'calc(100vh - 64px)',
202
+ padding: 0,
203
+ }}
204
+ >
205
+ {/* Header */}
206
+ <Card style={{ marginBottom: 16 }}>
207
+ <div
208
+ style={{
209
+ display: 'flex',
210
+ justifyContent: 'space-between',
211
+ alignItems: 'center',
212
+ }}
213
+ >
214
+ <Space>
215
+ <Button
216
+ type="text"
217
+ icon={<ArrowLeftOutlined />}
218
+ onClick={() => navigate(-1)}
219
+ >
220
+ Back
221
+ </Button>
222
+ <Title level={4} style={{ margin: 0 }}>
223
+ {data.workflow.name} — Instance #{data.id}
224
+ </Title>
225
+ <Tag color={statusCfg.color} icon={statusCfg.icon}>
226
+ {statusCfg.label}
227
+ </Tag>
228
+ </Space>
229
+ <Space>
230
+ <Button icon={<ReloadOutlined />} onClick={fetchData}>
231
+ Refresh
232
+ </Button>
233
+ {(data.status === 'RUNNING' || data.status === 'PENDING') && (
234
+ <Popconfirm
235
+ title="Cancel this workflow execution?"
236
+ onConfirm={handleCancel}
237
+ okText="Yes"
238
+ cancelText="No"
239
+ >
240
+ <Button danger loading={actionLoading} icon={<StopOutlined />}>
241
+ Cancel
242
+ </Button>
243
+ </Popconfirm>
244
+ )}
245
+ {data.status === 'FAILED' && (
246
+ <Button
247
+ type="primary"
248
+ loading={actionLoading}
249
+ onClick={handleRetry}
250
+ >
251
+ Retry
252
+ </Button>
253
+ )}
254
+ </Space>
255
+ </div>
256
+ </Card>
257
+
258
+ {/* Instance Info */}
259
+ <Card style={{ marginBottom: 16 }} title="Execution Details">
260
+ <Descriptions column={3} size="small">
261
+ <Descriptions.Item label="Instance ID">{data.id}</Descriptions.Item>
262
+ <Descriptions.Item label="Temporal Run ID">
263
+ <Text copyable style={{ fontSize: 12 }}>
264
+ {data.temporalRunId || '—'}
265
+ </Text>
266
+ </Descriptions.Item>
267
+ <Descriptions.Item label="Creator">{data.creator}</Descriptions.Item>
268
+ <Descriptions.Item label="Started">
269
+ {data.startedAt ? new Date(data.startedAt).toLocaleString() : '—'}
270
+ </Descriptions.Item>
271
+ <Descriptions.Item label="Finished">
272
+ {data.finishedAt ? new Date(data.finishedAt).toLocaleString() : '—'}
273
+ </Descriptions.Item>
274
+ <Descriptions.Item label="Duration">
275
+ {formatDuration(data.startedAt, data.finishedAt)}
276
+ </Descriptions.Item>
277
+ </Descriptions>
278
+ </Card>
279
+
280
+ {/* Node Execution Timeline */}
281
+ <Card title="Node Execution Timeline">
282
+ {data.nodeExecutions.length === 0 ? (
283
+ <Text type="secondary">No node executions recorded yet.</Text>
284
+ ) : (
285
+ <Steps
286
+ direction="vertical"
287
+ size="small"
288
+ current={-1}
289
+ items={data.nodeExecutions.map((ne) => {
290
+ const isApprovalPending =
291
+ ne.nodeType === 'approval' && ne.status === 'RUNNING';
292
+ return {
293
+ title: (
294
+ <Space>
295
+ <span>{ne.nodeLabel || ne.nodeId}</span>
296
+ <Tag style={{ fontSize: 11 }}>{ne.nodeType}</Tag>
297
+ {isApprovalPending && (
298
+ <Space size={4}>
299
+ <Button
300
+ size="small"
301
+ type="primary"
302
+ onClick={() => handleApprove(ne.nodeId, true)}
303
+ loading={actionLoading}
304
+ >
305
+ Approve
306
+ </Button>
307
+ <Button
308
+ size="small"
309
+ danger
310
+ onClick={() => handleApprove(ne.nodeId, false)}
311
+ loading={actionLoading}
312
+ >
313
+ Reject
314
+ </Button>
315
+ </Space>
316
+ )}
317
+ </Space>
318
+ ),
319
+ description: (
320
+ <div style={{ fontSize: 12, color: '#666' }}>
321
+ <span>
322
+ Duration: {formatDuration(ne.startedAt, ne.finishedAt)}
323
+ </span>
324
+ {ne.error && (
325
+ <div style={{ color: '#ff4d4f', marginTop: 4 }}>
326
+ Error:{' '}
327
+ {typeof ne.error === 'object'
328
+ ? JSON.stringify(ne.error)
329
+ : String(ne.error)}
330
+ </div>
331
+ )}
332
+ </div>
333
+ ),
334
+ status: getStepStatus(ne.status),
335
+ icon: ne.status === 'RUNNING' ? <LoadingOutlined /> : undefined,
336
+ };
337
+ })}
338
+ />
339
+ )}
340
+ </Card>
341
+ </div>
342
+ );
343
+ }
@@ -0,0 +1,243 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import {
3
+ Button,
4
+ Card,
5
+ Select,
6
+ Space,
7
+ Table,
8
+ Tag,
9
+ Tooltip,
10
+ Typography,
11
+ } from 'antd';
12
+ import { ArrowLeftOutlined } from '@ant-design/icons';
13
+ import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
14
+ import { customRequest } from 'helpers/http';
15
+
16
+ const { Title } = Typography;
17
+ const PAGE_SIZE = 20;
18
+
19
+ const STATUS_TAG: Record<string, { color: string; label: string }> = {
20
+ PENDING: { color: 'gold', label: 'Pending' },
21
+ RUNNING: { color: 'blue', label: 'Running' },
22
+ COMPLETED: { color: 'green', label: 'Completed' },
23
+ FAILED: { color: 'red', label: 'Failed' },
24
+ CANCELLED: { color: 'default', label: 'Cancelled' },
25
+ };
26
+
27
+ interface WorkflowInstanceItem {
28
+ id: string;
29
+ status: string;
30
+ startedAt: string | null;
31
+ finishedAt: string | null;
32
+ creator: string;
33
+ createdAt: string;
34
+ }
35
+
36
+ function formatDuration(start: string | null, end: string | null): string {
37
+ if (!start || !end) return '—';
38
+ const ms = new Date(end).getTime() - new Date(start).getTime();
39
+ if (ms < 1000) return `${ms}ms`;
40
+ const s = Math.floor(ms / 1000);
41
+ if (s < 60) return `${s}s`;
42
+ const m = Math.floor(s / 60);
43
+ const rem = s % 60;
44
+ return rem > 0 ? `${m}m ${rem}s` : `${m}m`;
45
+ }
46
+
47
+ export default function WorkflowInstancesPage() {
48
+ const { workflowId } = useParams<{ workflowId: string }>();
49
+ const navigate = useNavigate();
50
+ const [searchParams, setSearchParams] = useSearchParams();
51
+
52
+ const filterStatus = searchParams.get('status') || undefined;
53
+ const page = Number(searchParams.get('page')) || 1;
54
+
55
+ const [items, setItems] = useState<WorkflowInstanceItem[]>([]);
56
+ const [total, setTotal] = useState(0);
57
+ const [loading, setLoading] = useState(false);
58
+ const [workflowName, setWorkflowName] = useState('');
59
+
60
+ const updateParams = useCallback(
61
+ (updates: Record<string, string | undefined>) => {
62
+ setSearchParams(
63
+ (prev) => {
64
+ const next = new URLSearchParams(prev);
65
+ for (const [k, v] of Object.entries(updates)) {
66
+ if (v) next.set(k, v);
67
+ else next.delete(k);
68
+ }
69
+ return next;
70
+ },
71
+ { replace: true },
72
+ );
73
+ },
74
+ [setSearchParams],
75
+ );
76
+
77
+ useEffect(() => {
78
+ if (!workflowId) return;
79
+ customRequest<{ name: string }>(`workflow/${workflowId}`, 'GET')
80
+ .then((wf) => setWorkflowName(wf.name))
81
+ .catch(() => {});
82
+ }, [workflowId]);
83
+
84
+ const fetchData = useCallback(async () => {
85
+ if (!workflowId) return;
86
+ setLoading(true);
87
+ try {
88
+ const params: Record<string, any> = {
89
+ skip: (page - 1) * PAGE_SIZE,
90
+ limit: PAGE_SIZE,
91
+ };
92
+ if (filterStatus) params.status = filterStatus;
93
+
94
+ const res = await customRequest<{
95
+ items: WorkflowInstanceItem[];
96
+ total: number;
97
+ }>(`workflow/${workflowId}/instances`, 'GET', params);
98
+ setItems(res.items);
99
+ setTotal(res.total);
100
+ } catch {
101
+ // handled silently
102
+ } finally {
103
+ setLoading(false);
104
+ }
105
+ }, [workflowId, page, filterStatus]);
106
+
107
+ useEffect(() => {
108
+ fetchData();
109
+ }, [fetchData]);
110
+
111
+ const columns = [
112
+ {
113
+ title: 'ID',
114
+ dataIndex: 'id',
115
+ key: 'id',
116
+ width: 80,
117
+ },
118
+ {
119
+ title: 'Status',
120
+ dataIndex: 'status',
121
+ key: 'status',
122
+ width: 110,
123
+ render: (status: string) => {
124
+ const cfg = STATUS_TAG[status] || { color: 'default', label: status };
125
+ return <Tag color={cfg.color}>{cfg.label}</Tag>;
126
+ },
127
+ },
128
+ {
129
+ title: 'Started',
130
+ dataIndex: 'startedAt',
131
+ key: 'startedAt',
132
+ width: 160,
133
+ render: (v: string | null) =>
134
+ v ? (
135
+ <Tooltip title={new Date(v).toLocaleString()}>
136
+ <span>{new Date(v).toLocaleString()}</span>
137
+ </Tooltip>
138
+ ) : (
139
+ <span style={{ color: '#d9d9d9' }}>—</span>
140
+ ),
141
+ },
142
+ {
143
+ title: 'Finished',
144
+ dataIndex: 'finishedAt',
145
+ key: 'finishedAt',
146
+ width: 160,
147
+ render: (v: string | null) =>
148
+ v ? (
149
+ <Tooltip title={new Date(v).toLocaleString()}>
150
+ <span>{new Date(v).toLocaleString()}</span>
151
+ </Tooltip>
152
+ ) : (
153
+ <span style={{ color: '#d9d9d9' }}>—</span>
154
+ ),
155
+ },
156
+ {
157
+ title: 'Duration',
158
+ key: 'duration',
159
+ width: 100,
160
+ render: (_: any, record: WorkflowInstanceItem) =>
161
+ formatDuration(record.startedAt, record.finishedAt),
162
+ },
163
+ {
164
+ title: 'Creator',
165
+ dataIndex: 'creator',
166
+ key: 'creator',
167
+ width: 150,
168
+ },
169
+ {
170
+ title: 'Actions',
171
+ key: 'actions',
172
+ width: 100,
173
+ render: (_: any, record: WorkflowInstanceItem) => (
174
+ <Button
175
+ type="link"
176
+ size="small"
177
+ onClick={() => navigate(`/admin/workflow/instance/show/${record.id}`)}
178
+ >
179
+ Detail
180
+ </Button>
181
+ ),
182
+ },
183
+ ];
184
+
185
+ return (
186
+ <div style={{ background: '#f0f2f5', minHeight: 'calc(100vh - 64px)' }}>
187
+ <Card style={{ marginBottom: 16 }}>
188
+ <div
189
+ style={{
190
+ display: 'flex',
191
+ justifyContent: 'space-between',
192
+ alignItems: 'center',
193
+ }}
194
+ >
195
+ <Space>
196
+ <Button
197
+ type="text"
198
+ icon={<ArrowLeftOutlined />}
199
+ onClick={() => navigate('/admin/workflow')}
200
+ >
201
+ Back
202
+ </Button>
203
+ <Title level={4} style={{ margin: 0 }}>
204
+ {workflowName || 'Workflow'} — Execution History
205
+ </Title>
206
+ </Space>
207
+ <Select
208
+ placeholder="All Statuses"
209
+ allowClear
210
+ value={filterStatus}
211
+ onChange={(v) => updateParams({ status: v, page: undefined })}
212
+ style={{ width: 140 }}
213
+ options={[
214
+ { value: 'PENDING', label: 'Pending' },
215
+ { value: 'RUNNING', label: 'Running' },
216
+ { value: 'COMPLETED', label: 'Completed' },
217
+ { value: 'FAILED', label: 'Failed' },
218
+ { value: 'CANCELLED', label: 'Cancelled' },
219
+ ]}
220
+ />
221
+ </div>
222
+ </Card>
223
+
224
+ <Card>
225
+ <Table
226
+ rowKey="id"
227
+ loading={loading}
228
+ columns={columns}
229
+ dataSource={items}
230
+ pagination={{
231
+ current: page,
232
+ pageSize: PAGE_SIZE,
233
+ total,
234
+ onChange: (p) =>
235
+ updateParams({ page: p > 1 ? String(p) : undefined }),
236
+ showTotal: (t) => `Total ${t}`,
237
+ }}
238
+ size="small"
239
+ />
240
+ </Card>
241
+ </div>
242
+ );
243
+ }