@gadmin2n/schematics 0.0.72 → 0.0.74

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,524 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import {
3
+ Button,
4
+ Card,
5
+ Input,
6
+ Modal,
7
+ Popconfirm,
8
+ Select,
9
+ Space,
10
+ Switch,
11
+ Table,
12
+ Tag,
13
+ Tooltip,
14
+ Typography,
15
+ message,
16
+ } from 'antd';
17
+ import {
18
+ DeleteOutlined,
19
+ EditOutlined,
20
+ ExportOutlined,
21
+ EyeOutlined,
22
+ HistoryOutlined,
23
+ ImportOutlined,
24
+ PlusOutlined,
25
+ ReloadOutlined,
26
+ SendOutlined,
27
+ } from '@ant-design/icons';
28
+ import { useSearchParams, useNavigate } from 'react-router-dom';
29
+ import { customRequest } from 'helpers/http';
30
+ import { StatusCards } from './components/StatusCards';
31
+ import { ExportModal } from './components/ExportModal';
32
+ import { ImportModal } from './components/ImportModal';
33
+ import type { Workflow, WorkflowOverview } from './types';
34
+
35
+ const { Title } = Typography;
36
+ const PAGE_SIZE = 20;
37
+
38
+ function RunDot({
39
+ count,
40
+ color,
41
+ label,
42
+ onClick,
43
+ }: {
44
+ count: number;
45
+ color: string;
46
+ label: string;
47
+ onClick?: () => void;
48
+ }) {
49
+ const size = 28;
50
+ const hasCount = count > 0;
51
+ return (
52
+ <Tooltip title={`${label}: ${count}`}>
53
+ <span
54
+ onClick={hasCount ? onClick : undefined}
55
+ style={{
56
+ display: 'inline-flex',
57
+ alignItems: 'center',
58
+ justifyContent: 'center',
59
+ width: size,
60
+ height: size,
61
+ borderRadius: '50%',
62
+ border: `2.5px solid ${hasCount ? color : '#d9d9d9'}`,
63
+ fontSize: 11,
64
+ fontWeight: 600,
65
+ color: hasCount ? color : '#d9d9d9',
66
+ cursor: hasCount && onClick ? 'pointer' : 'default',
67
+ lineHeight: 1,
68
+ }}
69
+ >
70
+ {hasCount ? count : ''}
71
+ </span>
72
+ </Tooltip>
73
+ );
74
+ }
75
+
76
+ const STATUS_COLOR: Record<string, string> = {
77
+ DRAFT: 'default',
78
+ PUBLISHED: 'success',
79
+ };
80
+
81
+ export default function WorkflowListPage() {
82
+ console.log('[WorkflowList] MOUNTED, pathname:', window.location.pathname);
83
+ const navigate = useNavigate();
84
+ const [workflows, setWorkflows] = useState<Workflow[]>([]);
85
+ const [overview, setOverview] = useState<WorkflowOverview | null>(null);
86
+ const [total, setTotal] = useState(0);
87
+ const [loading, setLoading] = useState(false);
88
+
89
+ const [searchParams, setSearchParams] = useSearchParams();
90
+ const filterStatus = searchParams.get('status') || undefined;
91
+ const filterInstanceStatus = searchParams.get('instanceStatus') || undefined;
92
+ const filterName = searchParams.get('name') || undefined;
93
+ const page = Number(searchParams.get('page')) || 1;
94
+
95
+ const [publishModalOpen, setPublishModalOpen] = useState(false);
96
+ const [publishId, setPublishId] = useState<string | null>(null);
97
+ const [publishSummary, setPublishSummary] = useState('');
98
+ const [publishLoading, setPublishLoading] = useState(false);
99
+
100
+ const [exportModalOpen, setExportModalOpen] = useState(false);
101
+ const [exportWorkflowId, setExportWorkflowId] = useState<string | null>(null);
102
+ const [importModalOpen, setImportModalOpen] = useState(false);
103
+
104
+ const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
105
+
106
+ const updateParams = useCallback(
107
+ (updates: Record<string, string | undefined>) => {
108
+ setSearchParams(
109
+ (prev) => {
110
+ const next = new URLSearchParams(prev);
111
+ for (const [k, v] of Object.entries(updates)) {
112
+ if (v) next.set(k, v);
113
+ else next.delete(k);
114
+ }
115
+ return next;
116
+ },
117
+ { replace: true },
118
+ );
119
+ },
120
+ [setSearchParams],
121
+ );
122
+
123
+ const setFilterStatus = useCallback(
124
+ (v: string | undefined) => updateParams({ status: v, page: undefined }),
125
+ [updateParams],
126
+ );
127
+ const setFilterInstanceStatus = useCallback(
128
+ (v: string | undefined) =>
129
+ updateParams({ instanceStatus: v, page: undefined }),
130
+ [updateParams],
131
+ );
132
+ const setFilterName = useCallback(
133
+ (v: string | undefined) => updateParams({ name: v, page: undefined }),
134
+ [updateParams],
135
+ );
136
+ const setPage = useCallback(
137
+ (p: number) => updateParams({ page: p > 1 ? String(p) : undefined }),
138
+ [updateParams],
139
+ );
140
+
141
+ const fetchData = useCallback(async () => {
142
+ setLoading(true);
143
+ try {
144
+ const params: Record<string, any> = {
145
+ skip: (page - 1) * PAGE_SIZE,
146
+ limit: PAGE_SIZE,
147
+ };
148
+ if (filterStatus) params.status = filterStatus.toUpperCase();
149
+ if (filterInstanceStatus) params.instanceStatus = filterInstanceStatus;
150
+ if (filterName) params.name = filterName;
151
+
152
+ const [listRes, overviewRes] = await Promise.all([
153
+ customRequest<{ items: Workflow[]; total: number }>(
154
+ 'workflow',
155
+ 'GET',
156
+ params,
157
+ ),
158
+ customRequest<WorkflowOverview>('workflow/overview', 'GET'),
159
+ ]);
160
+ setWorkflows(listRes.items);
161
+ setTotal(listRes.total);
162
+ setOverview(overviewRes);
163
+ } catch (e: any) {
164
+ message.error(e?.message ?? 'Failed to fetch workflows');
165
+ } finally {
166
+ setLoading(false);
167
+ }
168
+ }, [page, filterStatus, filterInstanceStatus, filterName]);
169
+
170
+ useEffect(() => {
171
+ fetchData();
172
+ }, [fetchData]);
173
+
174
+ async function handleDelete(id: string) {
175
+ try {
176
+ await customRequest(`workflow/${id}`, 'DELETE');
177
+ message.success('Workflow deleted');
178
+ fetchData();
179
+ } catch (e: any) {
180
+ message.error(e?.message ?? 'Delete failed');
181
+ }
182
+ }
183
+
184
+ async function handlePublish() {
185
+ if (!publishId) return;
186
+ setPublishLoading(true);
187
+ try {
188
+ await customRequest(`workflow/${publishId}/publish`, 'POST', {
189
+ changeSummary: publishSummary,
190
+ });
191
+ message.success('Workflow published!');
192
+ setPublishModalOpen(false);
193
+ setPublishId(null);
194
+ setPublishSummary('');
195
+ fetchData();
196
+ } catch (e: any) {
197
+ message.error(e?.message ?? 'Publish failed');
198
+ } finally {
199
+ setPublishLoading(false);
200
+ }
201
+ }
202
+
203
+ async function handleToggleEnabled(id: string, currentValue: boolean) {
204
+ try {
205
+ await customRequest(`workflow/${id}/toggle`, 'PATCH', {
206
+ enabled: !currentValue,
207
+ });
208
+ message.success(`Workflow ${currentValue ? '禁用' : '启用'}成功`);
209
+ fetchData();
210
+ } catch (e: any) {
211
+ message.error(e?.message ?? 'Toggle failed');
212
+ }
213
+ }
214
+
215
+ const columns = [
216
+ {
217
+ title: '',
218
+ dataIndex: 'isEnabled',
219
+ key: 'isEnabled',
220
+ width: 50,
221
+ render: (isEnabled: boolean, record: Workflow) => (
222
+ <Popconfirm
223
+ title={`确定要${isEnabled ? '禁用' : '启用'}此工作流?`}
224
+ okText="确定"
225
+ cancelText="取消"
226
+ onConfirm={() => handleToggleEnabled(record.id, isEnabled)}
227
+ >
228
+ <Switch checked={isEnabled} size="small" />
229
+ </Popconfirm>
230
+ ),
231
+ },
232
+ {
233
+ title: 'Name',
234
+ dataIndex: 'name',
235
+ key: 'name',
236
+ render: (name: string, record: Workflow) => (
237
+ <a onClick={() => navigate(`/admin/workflow/show/${record.id}`)}>
238
+ {name}
239
+ </a>
240
+ ),
241
+ },
242
+ {
243
+ title: 'Status',
244
+ dataIndex: 'status',
245
+ key: 'status',
246
+ width: 100,
247
+ render: (status: string) => (
248
+ <Tag color={STATUS_COLOR[status]}>{status}</Tag>
249
+ ),
250
+ },
251
+ {
252
+ title: 'Version',
253
+ key: 'version',
254
+ width: 200,
255
+ render: (_: any, record: Workflow) => {
256
+ const ver = record.versions?.[0];
257
+ if (!ver) return '—';
258
+ const summary = ver.changeSummary?.slice(0, 20) || '';
259
+ return summary ? `v${ver.version} - ${summary}` : `v${ver.version}`;
260
+ },
261
+ },
262
+ {
263
+ title: 'Runs',
264
+ key: 'runs',
265
+ width: 160,
266
+ render: (_: any, record: Workflow) => {
267
+ const runs = record.runs || {
268
+ pending: 0,
269
+ running: 0,
270
+ completed: 0,
271
+ failed: 0,
272
+ };
273
+ const go = (status: string) =>
274
+ navigate(
275
+ `/admin/workflow/instances/show/${record.id}?status=${status}`,
276
+ );
277
+ return (
278
+ <Space size={4}>
279
+ <RunDot
280
+ count={runs.pending}
281
+ color="#faad14"
282
+ label="Pending"
283
+ onClick={() => go('PENDING')}
284
+ />
285
+ <RunDot
286
+ count={runs.completed}
287
+ color="#006d32"
288
+ label="Completed"
289
+ onClick={() => go('COMPLETED')}
290
+ />
291
+ <RunDot
292
+ count={runs.running}
293
+ color="#52c41a"
294
+ label="Running"
295
+ onClick={() => go('RUNNING')}
296
+ />
297
+ <RunDot
298
+ count={runs.failed}
299
+ color="#ff4d4f"
300
+ label="Failed"
301
+ onClick={() => go('FAILED')}
302
+ />
303
+ </Space>
304
+ );
305
+ },
306
+ },
307
+ {
308
+ title: 'Last Run',
309
+ key: 'lastRun',
310
+ width: 150,
311
+ render: (_: any, record: Workflow) => {
312
+ if (!record.lastRun) return <span style={{ color: '#d9d9d9' }}>—</span>;
313
+ return (
314
+ <Tooltip title={new Date(record.lastRun).toLocaleString()}>
315
+ <span>{new Date(record.lastRun).toLocaleDateString()}</span>
316
+ </Tooltip>
317
+ );
318
+ },
319
+ },
320
+ {
321
+ title: 'Updated',
322
+ dataIndex: 'updatedAt',
323
+ key: 'updatedAt',
324
+ width: 150,
325
+ render: (v: string) => (
326
+ <Tooltip title={new Date(v).toLocaleString()}>
327
+ <span>{new Date(v).toLocaleDateString()}</span>
328
+ </Tooltip>
329
+ ),
330
+ },
331
+ {
332
+ title: 'Actions',
333
+ key: 'actions',
334
+ width: 180,
335
+ render: (_: any, record: Workflow) => (
336
+ <Space>
337
+ <Tooltip title="View">
338
+ <Button
339
+ size="small"
340
+ icon={<EyeOutlined />}
341
+ onClick={() => navigate(`/admin/workflow/show/${record.id}`)}
342
+ />
343
+ </Tooltip>
344
+ <Tooltip title="Edit">
345
+ <Button
346
+ size="small"
347
+ icon={<EditOutlined />}
348
+ onClick={() => navigate(`/admin/workflow/edit/${record.id}`)}
349
+ />
350
+ </Tooltip>
351
+ <Tooltip title="Run History">
352
+ <Button
353
+ size="small"
354
+ icon={<HistoryOutlined />}
355
+ onClick={() =>
356
+ navigate(`/admin/workflow/instances/show/${record.id}`)
357
+ }
358
+ />
359
+ </Tooltip>
360
+ <Tooltip title="Export">
361
+ <Button
362
+ size="small"
363
+ icon={<ExportOutlined />}
364
+ onClick={() => {
365
+ setExportWorkflowId(record.id);
366
+ setExportModalOpen(true);
367
+ }}
368
+ />
369
+ </Tooltip>
370
+ {record.status === 'DRAFT' && (
371
+ <Tooltip title="Publish">
372
+ <Button
373
+ size="small"
374
+ type="primary"
375
+ icon={<SendOutlined />}
376
+ onClick={() => {
377
+ setPublishId(record.id);
378
+ setPublishSummary('');
379
+ setPublishModalOpen(true);
380
+ }}
381
+ />
382
+ </Tooltip>
383
+ )}
384
+ <Popconfirm
385
+ title="Delete this workflow?"
386
+ description="All versions and instances will be deleted."
387
+ okText="Delete"
388
+ cancelText="Cancel"
389
+ okButtonProps={{ danger: true }}
390
+ onConfirm={() => handleDelete(record.id)}
391
+ >
392
+ <Tooltip title="Delete">
393
+ <Button size="small" danger icon={<DeleteOutlined />} />
394
+ </Tooltip>
395
+ </Popconfirm>
396
+ </Space>
397
+ ),
398
+ },
399
+ ];
400
+
401
+ return (
402
+ <div style={{ background: '#f0f2f5', minHeight: 'calc(100vh - 64px)' }}>
403
+ <Card style={{ marginBottom: 16 }}>
404
+ <div
405
+ style={{
406
+ display: 'flex',
407
+ justifyContent: 'space-between',
408
+ alignItems: 'center',
409
+ }}
410
+ >
411
+ <Title level={4} style={{ margin: 0 }}>
412
+ Workflows
413
+ </Title>
414
+ <Space>
415
+ <Button icon={<ReloadOutlined />} onClick={fetchData} />
416
+ <Button
417
+ icon={<ImportOutlined />}
418
+ onClick={() => setImportModalOpen(true)}
419
+ >
420
+ Import
421
+ </Button>
422
+ <Button
423
+ type="primary"
424
+ icon={<PlusOutlined />}
425
+ onClick={() => navigate('/admin/workflow/create')}
426
+ >
427
+ New Workflow
428
+ </Button>
429
+ </Space>
430
+ </div>
431
+ </Card>
432
+
433
+ <StatusCards
434
+ overview={overview}
435
+ activeFilter={filterInstanceStatus}
436
+ onFilter={setFilterInstanceStatus}
437
+ />
438
+
439
+ <Card style={{ marginBottom: 16 }}>
440
+ <Space wrap>
441
+ <Select
442
+ placeholder="Status"
443
+ allowClear
444
+ value={filterStatus}
445
+ onChange={(v) => setFilterStatus(v)}
446
+ style={{ width: 120 }}
447
+ options={[
448
+ { value: 'draft', label: 'Draft' },
449
+ { value: 'published', label: 'Published' },
450
+ ]}
451
+ />
452
+ <Input
453
+ placeholder="Search by name"
454
+ allowClear
455
+ defaultValue={filterName}
456
+ onChange={(e) => {
457
+ const v = e.target.value;
458
+ if (debounceRef.current) clearTimeout(debounceRef.current);
459
+ debounceRef.current = setTimeout(
460
+ () => setFilterName(v || undefined),
461
+ 300,
462
+ );
463
+ }}
464
+ style={{ width: 220 }}
465
+ />
466
+ </Space>
467
+ </Card>
468
+
469
+ <Card>
470
+ <Table
471
+ rowKey="id"
472
+ loading={loading}
473
+ columns={columns}
474
+ dataSource={workflows}
475
+ pagination={{
476
+ current: page,
477
+ pageSize: PAGE_SIZE,
478
+ total,
479
+ onChange: (p) => setPage(p),
480
+ showTotal: (t) => `Total ${t}`,
481
+ }}
482
+ size="small"
483
+ />
484
+ </Card>
485
+
486
+ <Modal
487
+ title="Publish Workflow"
488
+ open={publishModalOpen}
489
+ onOk={handlePublish}
490
+ onCancel={() => {
491
+ setPublishModalOpen(false);
492
+ setPublishId(null);
493
+ setPublishSummary('');
494
+ }}
495
+ okText="Publish"
496
+ cancelText="Cancel"
497
+ confirmLoading={publishLoading}
498
+ >
499
+ <p>Please enter a version description:</p>
500
+ <Input.TextArea
501
+ rows={3}
502
+ placeholder="Describe what changed in this version..."
503
+ value={publishSummary}
504
+ onChange={(e) => setPublishSummary(e.target.value)}
505
+ />
506
+ </Modal>
507
+
508
+ <ExportModal
509
+ open={exportModalOpen}
510
+ workflowId={exportWorkflowId}
511
+ onClose={() => {
512
+ setExportModalOpen(false);
513
+ setExportWorkflowId(null);
514
+ }}
515
+ />
516
+
517
+ <ImportModal
518
+ open={importModalOpen}
519
+ onClose={() => setImportModalOpen(false)}
520
+ onSuccess={fetchData}
521
+ />
522
+ </div>
523
+ );
524
+ }