@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,469 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import {
3
+ Button,
4
+ Card,
5
+ Descriptions,
6
+ Input,
7
+ message,
8
+ Modal,
9
+ Select,
10
+ Space,
11
+ Spin,
12
+ Tag,
13
+ Typography,
14
+ } from 'antd';
15
+ import {
16
+ ArrowLeftOutlined,
17
+ DiffOutlined,
18
+ EditOutlined,
19
+ HistoryOutlined,
20
+ RobotOutlined,
21
+ SendOutlined,
22
+ } from '@ant-design/icons';
23
+ import { useNavigate, useParams } from 'react-router-dom';
24
+ import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer-continued';
25
+ import { customRequest } from 'helpers/http';
26
+ import { FlowRenderer } from './components/FlowRenderer';
27
+ import { RunWorkflowModal } from './components/RunWorkflowModal';
28
+ import type {
29
+ Workflow,
30
+ WorkflowDSL,
31
+ WorkflowNodeType,
32
+ WorkflowVersion,
33
+ } from './types';
34
+
35
+ const { Title } = Typography;
36
+
37
+ const STATUS_COLOR: Record<string, string> = {
38
+ DRAFT: 'default',
39
+ PUBLISHED: 'success',
40
+ };
41
+
42
+ const isDev = import.meta.env.DEV;
43
+
44
+ export default function WorkflowShowPage() {
45
+ const { id } = useParams<{ id: string }>();
46
+ const navigate = useNavigate();
47
+
48
+ const [workflow, setWorkflow] = useState<Workflow | null>(null);
49
+ const [versions, setVersions] = useState<WorkflowVersion[]>([]);
50
+ const [nodeTypes, setNodeTypes] = useState<WorkflowNodeType[]>([]);
51
+ const [loading, setLoading] = useState(true);
52
+
53
+ const [dsl, setDsl] = useState<WorkflowDSL | null>(null);
54
+ const [currentVersion, setCurrentVersion] = useState<number | null>(null);
55
+
56
+ // Publish modal state
57
+ const [publishModalOpen, setPublishModalOpen] = useState(false);
58
+ const [publishSummary, setPublishSummary] = useState('');
59
+ const [publishLoading, setPublishLoading] = useState(false);
60
+
61
+ // Diff modal state
62
+ const [diffModalOpen, setDiffModalOpen] = useState(false);
63
+ const [diffLeft, setDiffLeft] = useState<number | null>(null);
64
+ const [diffRight, setDiffRight] = useState<number | null>(null);
65
+ const [diffLeftDsl, setDiffLeftDsl] = useState<string>('');
66
+ const [diffRightDsl, setDiffRightDsl] = useState<string>('');
67
+ const [diffLoading, setDiffLoading] = useState(false);
68
+
69
+ // Node detail panel
70
+ const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
71
+
72
+ const nodeTypeMap = useMemo(() => {
73
+ const map: Record<string, { category: string; icon: string }> = {};
74
+ for (const nt of nodeTypes) {
75
+ map[nt.type] = { category: nt.category, icon: nt.icon };
76
+ }
77
+ return map;
78
+ }, [nodeTypes]);
79
+
80
+ const selectedNode = useMemo(() => {
81
+ if (!selectedNodeId || !dsl) return null;
82
+ return dsl.nodes.find((n) => n.id === selectedNodeId) || null;
83
+ }, [selectedNodeId, dsl]);
84
+
85
+ useEffect(() => {
86
+ customRequest<WorkflowNodeType[]>('workflow-node-types', 'GET')
87
+ .then(setNodeTypes)
88
+ .catch(() => {});
89
+ }, []);
90
+
91
+ useEffect(() => {
92
+ if (!id) return;
93
+ setLoading(true);
94
+ Promise.all([
95
+ customRequest<Workflow>(`workflow/${id}`, 'GET'),
96
+ customRequest<WorkflowVersion[]>(`workflow/${id}/versions`, 'GET'),
97
+ ])
98
+ .then(([wf, vers]) => {
99
+ setWorkflow(wf);
100
+ setVersions(vers);
101
+ const latestVersion = (wf as any).versions?.[0];
102
+ if (latestVersion?.dsl) {
103
+ setDsl(latestVersion.dsl);
104
+ setCurrentVersion(latestVersion.version);
105
+ }
106
+ })
107
+ .catch((e) => {
108
+ message.error(e?.message ?? 'Failed to load workflow');
109
+ })
110
+ .finally(() => {
111
+ setLoading(false);
112
+ });
113
+ }, [id]);
114
+
115
+ const handleSelectVersion = useCallback(
116
+ async (version: number) => {
117
+ if (!id) return;
118
+ try {
119
+ const v = await customRequest<WorkflowVersion>(
120
+ `workflow/${id}/versions/${version}`,
121
+ 'GET',
122
+ );
123
+ setDsl(v.dsl);
124
+ setCurrentVersion(v.version);
125
+ } catch (e: any) {
126
+ message.error(e?.message ?? 'Failed to load version');
127
+ }
128
+ },
129
+ [id],
130
+ );
131
+
132
+ const handleOpenDiff = useCallback(() => {
133
+ if (versions.length < 2) {
134
+ message.warning('至少需要两个版本才能对比');
135
+ return;
136
+ }
137
+ // Default: compare latest two versions
138
+ setDiffLeft(versions[1]?.version ?? null);
139
+ setDiffRight(versions[0]?.version ?? null);
140
+ setDiffLeftDsl('');
141
+ setDiffRightDsl('');
142
+ setDiffModalOpen(true);
143
+ }, [versions]);
144
+
145
+ const handleLoadDiff = useCallback(async () => {
146
+ if (!id || diffLeft === null || diffRight === null) return;
147
+ setDiffLoading(true);
148
+ try {
149
+ const [leftVer, rightVer] = await Promise.all([
150
+ customRequest<WorkflowVersion>(
151
+ `workflow/${id}/versions/${diffLeft}`,
152
+ 'GET',
153
+ ),
154
+ customRequest<WorkflowVersion>(
155
+ `workflow/${id}/versions/${diffRight}`,
156
+ 'GET',
157
+ ),
158
+ ]);
159
+ setDiffLeftDsl(JSON.stringify(leftVer.dsl, null, 2));
160
+ setDiffRightDsl(JSON.stringify(rightVer.dsl, null, 2));
161
+ } catch (e: any) {
162
+ message.error(e?.message ?? 'Failed to load versions');
163
+ } finally {
164
+ setDiffLoading(false);
165
+ }
166
+ }, [id, diffLeft, diffRight]);
167
+
168
+ useEffect(() => {
169
+ if (diffModalOpen && diffLeft !== null && diffRight !== null) {
170
+ handleLoadDiff();
171
+ }
172
+ }, [diffModalOpen, diffLeft, diffRight, handleLoadDiff]);
173
+
174
+ const handlePublish = useCallback(async () => {
175
+ if (!id) return;
176
+ setPublishLoading(true);
177
+ try {
178
+ await customRequest(`workflow/${id}/publish`, 'POST', {
179
+ changeSummary: publishSummary,
180
+ });
181
+ message.success('Workflow published successfully');
182
+ setPublishModalOpen(false);
183
+ setPublishSummary('');
184
+ // Refresh data
185
+ const [wf, vers] = await Promise.all([
186
+ customRequest<Workflow>(`workflow/${id}`, 'GET'),
187
+ customRequest<WorkflowVersion[]>(`workflow/${id}/versions`, 'GET'),
188
+ ]);
189
+ setWorkflow(wf);
190
+ setVersions(vers);
191
+ } catch (e: any) {
192
+ message.error(e?.message ?? 'Failed to publish workflow');
193
+ } finally {
194
+ setPublishLoading(false);
195
+ }
196
+ }, [id, publishSummary]);
197
+
198
+ const handleAiExplainDiff = useCallback(() => {
199
+ if (!diffLeftDsl || !diffRightDsl) {
200
+ message.warning('请先选择两个版本');
201
+ return;
202
+ }
203
+ const prompt = `请对比以下两个版本的 Workflow DSL JSON,用中文解读主要变更内容(新增/删除/修改了哪些节点、连线、配置等)。
204
+
205
+ 版本 v${diffLeft}(旧):
206
+ \`\`\`json
207
+ ${diffLeftDsl}
208
+ \`\`\`
209
+
210
+ 版本 v${diffRight}(新):
211
+ \`\`\`json
212
+ ${diffRightDsl}
213
+ \`\`\`
214
+
215
+ 请简洁地总结变更要点。`;
216
+ const requestId = `diff_${Date.now()}_${Math.random().toString(36).slice(2)}`;
217
+ window.parent.postMessage(
218
+ { type: 'WORKFLOW_AGENT_REQUEST', requestId, prompt },
219
+ '*',
220
+ );
221
+ message.success('已发送给 AI,请到右侧的Coding Agent对话窗口查看结果');
222
+ }, [diffLeftDsl, diffRightDsl, diffLeft, diffRight]);
223
+
224
+ if (loading) {
225
+ return (
226
+ <div
227
+ style={{
228
+ display: 'flex',
229
+ justifyContent: 'center',
230
+ alignItems: 'center',
231
+ height: '100vh',
232
+ }}
233
+ >
234
+ <Spin size="large" />
235
+ </div>
236
+ );
237
+ }
238
+
239
+ return (
240
+ <div
241
+ style={{
242
+ height: 'calc(100vh - 96px)',
243
+ display: 'flex',
244
+ flexDirection: 'column',
245
+ background: '#f0f2f5',
246
+ overflow: 'hidden',
247
+ }}
248
+ >
249
+ {/* Header */}
250
+ <Card style={{ marginBottom: 16, flexShrink: 0 }}>
251
+ <div
252
+ style={{
253
+ display: 'flex',
254
+ justifyContent: 'space-between',
255
+ alignItems: 'center',
256
+ }}
257
+ >
258
+ <Space>
259
+ <Button
260
+ type="text"
261
+ icon={<ArrowLeftOutlined />}
262
+ onClick={() => navigate('/admin/workflow')}
263
+ >
264
+ Back
265
+ </Button>
266
+ <Title level={4} style={{ margin: 0 }}>
267
+ {workflow?.name || 'Workflow'}
268
+ </Title>
269
+ {workflow?.status && (
270
+ <Tag color={STATUS_COLOR[workflow.status]}>{workflow.status}</Tag>
271
+ )}
272
+ </Space>
273
+ <Space>
274
+ {versions.length > 0 && (
275
+ <Select
276
+ value={currentVersion}
277
+ onChange={handleSelectVersion}
278
+ style={{ width: 200 }}
279
+ placeholder="选择版本"
280
+ options={versions.map((v) => ({
281
+ label: `v${v.version} - ${v.changeSummary?.slice(0, 20) || 'Saved'}`,
282
+ value: v.version,
283
+ }))}
284
+ />
285
+ )}
286
+ <Button
287
+ icon={<DiffOutlined />}
288
+ onClick={handleOpenDiff}
289
+ disabled={versions.length < 2}
290
+ >
291
+ Diff
292
+ </Button>
293
+ {workflow?.status === 'DRAFT' && (
294
+ <Button
295
+ icon={<SendOutlined />}
296
+ onClick={() => setPublishModalOpen(true)}
297
+ >
298
+ Publish
299
+ </Button>
300
+ )}
301
+ {workflow?.status === 'PUBLISHED' && workflow?.isEnabled && (
302
+ <RunWorkflowModal
303
+ workflowId={id!}
304
+ workflowName={workflow.name}
305
+ onSuccess={(instanceId) =>
306
+ navigate(`/admin/workflow/instance/show/${instanceId}`)
307
+ }
308
+ />
309
+ )}
310
+ <Button
311
+ icon={<HistoryOutlined />}
312
+ onClick={() => navigate(`/admin/workflow/instances/show/${id}`)}
313
+ >
314
+ History
315
+ </Button>
316
+ <Button
317
+ type="primary"
318
+ icon={<EditOutlined />}
319
+ onClick={() => navigate(`/admin/workflow/edit/${id}`)}
320
+ >
321
+ Edit
322
+ </Button>
323
+ </Space>
324
+ </div>
325
+ </Card>
326
+
327
+ {/* Canvas + Node Detail Panel */}
328
+ <div style={{ flex: 1, display: 'flex', minHeight: 0 }}>
329
+ <div style={{ flex: 1, position: 'relative' }}>
330
+ <FlowRenderer
331
+ dsl={dsl}
332
+ nodeTypeMap={nodeTypeMap}
333
+ selectedNodeId={selectedNodeId}
334
+ readonly
335
+ onNodeClick={(nodeId) => setSelectedNodeId(nodeId || null)}
336
+ />
337
+ </div>
338
+ {selectedNode && (
339
+ <div
340
+ style={{
341
+ width: 320,
342
+ flexShrink: 0,
343
+ borderLeft: '1px solid #f0f0f0',
344
+ background: '#fff',
345
+ overflowY: 'auto',
346
+ padding: 16,
347
+ }}
348
+ >
349
+ <Title level={5} style={{ marginTop: 0 }}>
350
+ {selectedNode.label}
351
+ </Title>
352
+ <Descriptions column={1} size="small" bordered>
353
+ <Descriptions.Item label="ID">
354
+ <Typography.Text copyable style={{ fontSize: 12 }}>
355
+ {selectedNode.id}
356
+ </Typography.Text>
357
+ </Descriptions.Item>
358
+ <Descriptions.Item label="类型">
359
+ {selectedNode.type}
360
+ </Descriptions.Item>
361
+ <Descriptions.Item label="分类">
362
+ <Tag>
363
+ {nodeTypeMap[selectedNode.type]?.category || 'ACTION'}
364
+ </Tag>
365
+ </Descriptions.Item>
366
+ {selectedNode.instanceRef && (
367
+ <Descriptions.Item label="节点实例">
368
+ {selectedNode.instanceRef.instanceName}
369
+ </Descriptions.Item>
370
+ )}
371
+ </Descriptions>
372
+ {selectedNode.config &&
373
+ Object.keys(selectedNode.config).length > 0 && (
374
+ <>
375
+ <Title level={5} style={{ marginTop: 16 }}>
376
+ 配置
377
+ </Title>
378
+ <Descriptions column={1} size="small" bordered>
379
+ {Object.entries(selectedNode.config).map(([key, value]) => (
380
+ <Descriptions.Item key={key} label={key}>
381
+ {typeof value === 'object'
382
+ ? JSON.stringify(value, null, 2)
383
+ : String(value ?? '')}
384
+ </Descriptions.Item>
385
+ ))}
386
+ </Descriptions>
387
+ </>
388
+ )}
389
+ </div>
390
+ )}
391
+ </div>
392
+
393
+ {/* Diff Modal */}
394
+ <Modal
395
+ title="版本对比"
396
+ open={diffModalOpen}
397
+ onCancel={() => setDiffModalOpen(false)}
398
+ footer={null}
399
+ width="90vw"
400
+ styles={{ body: { maxHeight: '70vh', overflow: 'auto' } }}
401
+ >
402
+ <Space style={{ marginBottom: 16 }}>
403
+ <Select
404
+ value={diffLeft}
405
+ onChange={(v) => setDiffLeft(v)}
406
+ style={{ width: 200 }}
407
+ placeholder="选择左侧版本"
408
+ options={versions.map((v) => ({
409
+ label: `v${v.version} - ${v.changeSummary?.slice(0, 20) || 'Saved'}`,
410
+ value: v.version,
411
+ }))}
412
+ />
413
+ <span>vs</span>
414
+ <Select
415
+ value={diffRight}
416
+ onChange={(v) => setDiffRight(v)}
417
+ style={{ width: 200 }}
418
+ placeholder="选择右侧版本"
419
+ options={versions.map((v) => ({
420
+ label: `v${v.version} - ${v.changeSummary?.slice(0, 20) || 'Saved'}`,
421
+ value: v.version,
422
+ }))}
423
+ />
424
+ {isDev && (
425
+ <Button
426
+ type="primary"
427
+ icon={<RobotOutlined />}
428
+ onClick={handleAiExplainDiff}
429
+ disabled={!diffLeftDsl || !diffRightDsl}
430
+ >
431
+ AI 解读
432
+ </Button>
433
+ )}
434
+ </Space>
435
+ {diffLoading ? (
436
+ <div style={{ textAlign: 'center', padding: 40 }}>
437
+ <Spin size="large" />
438
+ </div>
439
+ ) : (
440
+ <ReactDiffViewer
441
+ oldValue={diffLeftDsl}
442
+ newValue={diffRightDsl}
443
+ splitView
444
+ compareMethod={DiffMethod.LINES}
445
+ leftTitle={`v${diffLeft}`}
446
+ rightTitle={`v${diffRight}`}
447
+ />
448
+ )}
449
+ </Modal>
450
+
451
+ {/* Publish Modal */}
452
+ <Modal
453
+ title="Publish Workflow"
454
+ open={publishModalOpen}
455
+ onCancel={() => setPublishModalOpen(false)}
456
+ onOk={handlePublish}
457
+ confirmLoading={publishLoading}
458
+ okText="Publish"
459
+ >
460
+ <Input.TextArea
461
+ rows={3}
462
+ placeholder="Version description (changeSummary)"
463
+ value={publishSummary}
464
+ onChange={(e) => setPublishSummary(e.target.value)}
465
+ />
466
+ </Modal>
467
+ </div>
468
+ );
469
+ }
@@ -0,0 +1,92 @@
1
+ // ─── TypeScript Types ───────────────────────────────────────────────────────
2
+
3
+ export interface WorkflowNode {
4
+ id: string;
5
+ type: string;
6
+ label: string;
7
+ position: { x: number; y: number };
8
+ config: Record<string, any>;
9
+ instanceRef?: {
10
+ instanceId: string;
11
+ instanceName: string;
12
+ };
13
+ }
14
+
15
+ export interface WorkflowEdge {
16
+ id: string;
17
+ source: string;
18
+ target: string;
19
+ sourceHandle?: string;
20
+ label?: string;
21
+ }
22
+
23
+ export interface WorkflowDSL {
24
+ nodes: WorkflowNode[];
25
+ edges: WorkflowEdge[];
26
+ }
27
+
28
+ export interface AgentOutput {
29
+ dsl: WorkflowDSL;
30
+ changeSummary: string;
31
+ }
32
+
33
+ export interface Workflow {
34
+ id: string;
35
+ name: string;
36
+ description: string | null;
37
+ status: 'DRAFT' | 'PUBLISHED';
38
+ isEnabled: boolean;
39
+ dsl: WorkflowDSL | null;
40
+ creator: string;
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ versions?: { version: number }[];
44
+ _count?: { instances: number };
45
+ runs?: {
46
+ pending: number;
47
+ running: number;
48
+ completed: number;
49
+ failed: number;
50
+ };
51
+ lastRun?: string | null;
52
+ }
53
+
54
+ export interface WorkflowVersion {
55
+ id: string;
56
+ version: number;
57
+ dsl: WorkflowDSL;
58
+ prompt: string;
59
+ changeSummary: string | null;
60
+ creator: string;
61
+ createdAt: string;
62
+ }
63
+
64
+ export interface WorkflowOverview {
65
+ totalRuns: { last24h: number; total: number };
66
+ successRate: { last24h: number; total: number };
67
+ failed: { last24h: number; total: number };
68
+ duration: {
69
+ last24h: { avg: number; p95: number };
70
+ total: { avg: number; p95: number };
71
+ };
72
+ running: number;
73
+ pending: number;
74
+ }
75
+
76
+ export interface WorkflowNodeType {
77
+ id: string;
78
+ type: string;
79
+ category: string;
80
+ label: string;
81
+ icon: string;
82
+ description: string | null;
83
+ configSchema: Record<string, any>;
84
+ inputSchema: Record<string, any>;
85
+ outputSchema: Record<string, any>;
86
+ }
87
+
88
+ export interface NodeInstanceAgentOutput {
89
+ name: string;
90
+ description: string;
91
+ config: Record<string, any>;
92
+ }
@@ -0,0 +1,111 @@
1
+ import {
2
+ FieldDataType,
3
+ handleInitialValues,
4
+ handleOnFinish,
5
+ ModelType,
6
+ produceModel,
7
+ } from '@gadmin2n/react-common';
8
+ import { Create, useFileUploadState, useForm } from '@refinedev/antd';
9
+ import { Form } from 'antd';
10
+ import {
11
+ IResourceComponentsProps,
12
+ useApiUrl,
13
+ useTranslate,
14
+ } from '@refinedev/core';
15
+ import React, { useContext, useState } from 'react';
16
+ import { getFormItem, onFormValuesChange } from '../../helpers';
17
+ import { modelsMap, modelsEnum } from '../../generated/models.index';
18
+ import {
19
+ workflowEventOutboxFormConfig as formConfig,
20
+ workflowEventOutboxFormPrismaSelect as formPrismaSelect,
21
+ } from '../../generated/props/workflowEventOutbox/config';
22
+ import {
23
+ workflowEventOutboxModel,
24
+ useRelation,
25
+ } from '../../generated/props/workflowEventOutbox/model';
26
+ import { WorkflowEventOutbox } from '../../generated/types/prisma.types';
27
+ import { WorkflowEventOutboxForm as transformClass } from '../../generated/props/workflowEventOutbox/form.validator';
28
+ import { BusinessContext } from 'components/contexts/business';
29
+
30
+ export const WorkflowEventOutboxCreate: React.FC<
31
+ IResourceComponentsProps
32
+ > = () => {
33
+ const resourceName = 'workflowEventOutbox';
34
+ const t = useTranslate();
35
+
36
+ const [[fields, model]] = useState(() => {
37
+ const model: ModelType = produceModel(
38
+ workflowEventOutboxModel,
39
+ {
40
+ // all formItem attrs surport, https://ant.design/components/form#formitem
41
+ // description : { component : <MDEditor data-color-mode="light" /> },
42
+ // status : { normalize : (value: any) => value ? "1" : "0" },
43
+ // cron: {validator: { validator: runCronValidator },},
44
+ },
45
+ transformClass,
46
+ );
47
+
48
+ const fields: FieldDataType[] = formConfig.fields
49
+ .map((fieldName: string) => model[fieldName])
50
+ .filter((field: FieldDataType) => field);
51
+
52
+ return [fields, model] as const;
53
+ });
54
+
55
+ const { formProps, saveButtonProps, onFinish, form } =
56
+ useForm<WorkflowEventOutbox>({
57
+ meta: { select: formPrismaSelect },
58
+ });
59
+ if (formProps.initialValues || formConfig.initialValues) {
60
+ formProps.initialValues = handleInitialValues(
61
+ formProps.initialValues || formConfig.initialValues || {},
62
+ fields,
63
+ );
64
+ }
65
+
66
+ const apiUrl = useApiUrl();
67
+ const { isLoading, onChange } = useFileUploadState();
68
+ const relationSelectProps = useRelation(modelsMap);
69
+
70
+ return (
71
+ <Create
72
+ saveButtonProps={{
73
+ ...saveButtonProps,
74
+ disabled: isLoading,
75
+ }}
76
+ >
77
+ <Form
78
+ {...formProps}
79
+ validateTrigger="onBlur"
80
+ onFinish={(values) => {
81
+ onFinish(
82
+ handleOnFinish(
83
+ {
84
+ ...values,
85
+ },
86
+ fields,
87
+ ),
88
+ );
89
+ }}
90
+ layout="vertical"
91
+ form={form}
92
+ onValuesChange={onFormValuesChange(form, formConfig.reaction)}
93
+ >
94
+ {fields.map((field) => {
95
+ return getFormItem(
96
+ field,
97
+ resourceName,
98
+ t,
99
+ form,
100
+ formConfig.reaction,
101
+ modelsEnum,
102
+ model,
103
+ apiUrl,
104
+ relationSelectProps,
105
+ onChange,
106
+ );
107
+ })}
108
+ </Form>
109
+ </Create>
110
+ );
111
+ };