@gadmin2n/schematics 0.0.147 → 0.0.149

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 (106) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +2 -1
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permission.seed.ts +67 -15
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +83 -53
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/config/index.ts +5 -0
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/structured-all-exceptions.filter.spec.ts +24 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/structured-all-exceptions.filter.ts +15 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +4 -0
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.service.ts +31 -4
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.spec.ts +2 -6
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.spec.ts +28 -29
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.ts +16 -34
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +3 -3
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.spec.ts +61 -6
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.spec.ts +2 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.controller.ts +11 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.spec.ts +126 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.ts +136 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.controller.ts +24 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.dto.ts +8 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.service.spec.ts +62 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.service.ts +94 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.types.ts +6 -0
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staffDirectory.module.ts +10 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/providers/user.provider.ts +6 -2
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +20 -12
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +21 -19
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.ts +11 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.spec.ts +97 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.ts +150 -2
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.controller.ts +13 -1
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.dto.ts +13 -1
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.errors.ts +1 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.service.spec.ts +125 -0
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.service.ts +118 -5
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-cancellation.spec.ts +20 -3
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +6 -9
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-event-catalog.spec.ts +166 -17
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-event-trigger.pg.spec.ts +82 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-runtime.facade.ts +2 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.spec.ts +4 -1
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +5 -1
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +7 -2
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +44 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +106 -37
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.spec.ts +59 -3
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.spec.ts +33 -22
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.ts +10 -23
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/StaffSelect.test.tsx +69 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/StaffSelect.tsx +145 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/index.ts +2 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/staff-directory.api.ts +16 -0
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +1 -0
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.test.ts +10 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +20 -2
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +6 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +60 -14
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +60 -14
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +41 -1
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/people-groups/PeopleGroupModal.tsx +181 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/people-groups/index.tsx +203 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/people-groups/people-groups.api.ts +145 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/person-directory/PersonModal.tsx +112 -0
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/person-directory/index.tsx +214 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/person-directory/person-directory.api.ts +79 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/form-modal.tsx +7 -11
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +7 -7
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/RegisterBusinessEventModal.test.tsx +46 -5
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/RegisterBusinessEventModal.tsx +14 -10
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/detail.test.tsx +1 -1
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/detail.tsx +2 -1
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/index.test.tsx +1 -1
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/index.tsx +2 -2
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.test.tsx +20 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +97 -28
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +87 -119
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.test.tsx +22 -1
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.tsx +8 -2
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connections.css +8 -46
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connectionsApi.ts +7 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.test.tsx +32 -3
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.tsx +163 -106
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +8 -1
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.test.tsx +26 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +34 -6
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-config.css +13 -16
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-instance-show.css +185 -0
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +224 -105
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.test.tsx +1 -1
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DbExecuteConfigEditor.tsx +21 -12
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerConfigEditor.test.tsx +140 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerConfigEditor.tsx +124 -62
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +160 -8
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +125 -55
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SimplifiedNodeEditors.test.tsx +78 -17
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.test.tsx +33 -1
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.tsx +28 -46
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/event-catalog.api.ts +4 -2
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/human-approval-config.css +16 -0
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/subject-provider.api.ts +0 -6
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.test.tsx +24 -0
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +14 -17
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +1 -0
  104. package/package.json +1 -1
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CreateNodeInstanceDrawer.tsx +0 -162
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupCreateModal.tsx +0 -72
@@ -0,0 +1,185 @@
1
+ .node-instance-show__header,
2
+ .node-instance-show__header-main,
3
+ .node-instance-show__title-row,
4
+ .node-instance-show__section-heading {
5
+ display: flex;
6
+ align-items: center;
7
+ }
8
+
9
+ .node-instance-show__header {
10
+ justify-content: space-between;
11
+ flex-wrap: wrap;
12
+ gap: 16px;
13
+ }
14
+
15
+ .node-instance-show__header-main {
16
+ min-width: 0;
17
+ gap: 8px;
18
+ }
19
+
20
+ .node-instance-show__heading {
21
+ min-width: 0;
22
+ }
23
+
24
+ .node-instance-show__title-row {
25
+ flex-wrap: wrap;
26
+ gap: 8px;
27
+ }
28
+
29
+ .node-instance-show__title-row .ant-typography {
30
+ margin: 0;
31
+ }
32
+
33
+ .node-instance-show__section-heading {
34
+ justify-content: space-between;
35
+ gap: 16px;
36
+ margin-bottom: 20px;
37
+ }
38
+
39
+ .node-instance-show__section-heading .ant-typography {
40
+ margin: 0;
41
+ }
42
+
43
+ .node-instance-show__section-heading h5.ant-typography {
44
+ font-size: var(--workflow-content-title-size, 18px);
45
+ line-height: 28px;
46
+ }
47
+
48
+ .node-instance-show__summary-grid {
49
+ display: grid;
50
+ grid-template-columns: repeat(3, minmax(0, 1fr));
51
+ overflow: hidden;
52
+ border: 1px solid var(--ant-color-border-secondary);
53
+ border-radius: 10px;
54
+ background: var(--ant-color-fill-quaternary);
55
+ }
56
+
57
+ .node-instance-show__summary-item {
58
+ min-width: 0;
59
+ padding: 16px 18px;
60
+ border-right: 1px solid var(--ant-color-border-secondary);
61
+ border-bottom: 1px solid var(--ant-color-border-secondary);
62
+ }
63
+
64
+ .node-instance-show__summary-item:nth-child(3n) {
65
+ border-right: 0;
66
+ }
67
+
68
+ .node-instance-show__summary-item:nth-last-child(-n + 3) {
69
+ border-bottom: 0;
70
+ }
71
+
72
+ .node-instance-show__summary-item > .ant-typography:first-child {
73
+ display: block;
74
+ margin-bottom: 6px;
75
+ font-size: 12px;
76
+ }
77
+
78
+ .node-instance-show__summary-item > div {
79
+ min-height: 24px;
80
+ overflow-wrap: anywhere;
81
+ }
82
+
83
+ .node-instance-show__description {
84
+ display: grid;
85
+ grid-template-columns: 120px minmax(0, 1fr);
86
+ gap: 16px;
87
+ margin-top: 16px;
88
+ padding: 16px 18px;
89
+ border: 1px solid var(--ant-color-border-secondary);
90
+ border-radius: 10px;
91
+ }
92
+
93
+ .node-instance-show__configuration {
94
+ max-width: 960px;
95
+ padding: 20px;
96
+ border: 1px solid var(--ant-color-border-secondary);
97
+ border-radius: 10px;
98
+ background: var(--ant-color-fill-quaternary);
99
+ }
100
+
101
+ .node-instance-show__empty {
102
+ margin: 0;
103
+ padding: 28px 0;
104
+ border: 1px dashed var(--ant-color-border-secondary);
105
+ border-radius: 10px;
106
+ background: var(--ant-color-fill-quaternary);
107
+ }
108
+
109
+ .node-instance-show__references-loading {
110
+ display: flex;
111
+ min-height: 112px;
112
+ align-items: center;
113
+ justify-content: center;
114
+ }
115
+
116
+ .node-instance-show__workflow-link.ant-btn {
117
+ height: auto;
118
+ padding: 0;
119
+ white-space: normal;
120
+ text-align: left;
121
+ }
122
+
123
+ .node-instance-show__loading,
124
+ .node-instance-show__not-found {
125
+ min-height: calc(100vh - 160px);
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ }
130
+
131
+ .node-instance-show__not-found {
132
+ flex-direction: column;
133
+ gap: 16px;
134
+ }
135
+
136
+ @media (max-width: 900px) {
137
+ .node-instance-show__summary-grid {
138
+ grid-template-columns: repeat(2, minmax(0, 1fr));
139
+ }
140
+
141
+ .node-instance-show__summary-item,
142
+ .node-instance-show__summary-item:nth-child(3n) {
143
+ border-right: 1px solid var(--ant-color-border-secondary);
144
+ border-bottom: 1px solid var(--ant-color-border-secondary);
145
+ }
146
+
147
+ .node-instance-show__summary-item:nth-child(2n) {
148
+ border-right: 0;
149
+ }
150
+
151
+ .node-instance-show__summary-item:nth-last-child(-n + 2) {
152
+ border-bottom: 0;
153
+ }
154
+ }
155
+
156
+ @media (max-width: 600px) {
157
+ .node-instance-show__header,
158
+ .node-instance-show__section-heading {
159
+ align-items: flex-start;
160
+ }
161
+
162
+ .node-instance-show__summary-grid {
163
+ grid-template-columns: 1fr;
164
+ }
165
+
166
+ .node-instance-show__summary-item,
167
+ .node-instance-show__summary-item:nth-child(2n),
168
+ .node-instance-show__summary-item:nth-child(3n) {
169
+ border-right: 0;
170
+ border-bottom: 1px solid var(--ant-color-border-secondary);
171
+ }
172
+
173
+ .node-instance-show__summary-item:last-child {
174
+ border-bottom: 0;
175
+ }
176
+
177
+ .node-instance-show__description {
178
+ grid-template-columns: 1fr;
179
+ gap: 6px;
180
+ }
181
+
182
+ .node-instance-show__configuration {
183
+ padding: 16px;
184
+ }
185
+ }
@@ -1,24 +1,48 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import {
3
3
  Button,
4
4
  Card,
5
- Descriptions,
5
+ Empty,
6
+ Form,
6
7
  Popconfirm,
7
8
  Space,
8
9
  Spin,
9
- Switch,
10
10
  Table,
11
11
  Tag,
12
+ Typography,
12
13
  message,
13
14
  } from 'antd';
14
- import { DeleteOutlined, EditOutlined, LinkOutlined } from '@ant-design/icons';
15
+ import {
16
+ ArrowLeftOutlined,
17
+ DeleteOutlined,
18
+ EditOutlined,
19
+ LinkOutlined,
20
+ } from '@ant-design/icons';
15
21
  import { useNavigate, useParams } from 'react-router-dom';
16
22
  import { customRequest } from 'helpers/http';
17
- import { PageHeader } from 'components';
18
- import { PAGE_WRAPPER_STYLE } from 'constants/layout';
23
+ import {
24
+ CARD_GAP_STYLE,
25
+ HEADER_CARD_PROPS,
26
+ PAGE_WRAPPER_STYLE,
27
+ } from 'constants/layout';
19
28
  import { useTranslation } from 'react-i18next';
29
+ import type { JsonSchema, UiSchema } from './schema-form/schema.types';
30
+ import { SchemaForm } from './schema-form/SchemaForm';
20
31
  import { formatWorkflowUtcDateTime } from '../utils/workflowDateTime';
21
32
  import '../workflow-ui.css';
33
+ import './node-config.css';
34
+ import './node-instance-show.css';
35
+
36
+ const { Text, Title } = Typography;
37
+
38
+ const CATEGORY_COLORS: Record<string, string> = {
39
+ TRIGGER: 'blue',
40
+ ACTION: 'green',
41
+ CONDITION: 'orange',
42
+ FLOW_CONTROL: 'purple',
43
+ APPROVAL: 'red',
44
+ SUB_WORKFLOW: 'geekblue',
45
+ };
22
46
 
23
47
  interface NodeInstance {
24
48
  id: string;
@@ -31,27 +55,29 @@ interface NodeInstance {
31
55
  createdAt: string;
32
56
  updatedAt: string;
33
57
  nodeType?: {
58
+ type: string;
34
59
  label: string;
35
60
  category: string;
36
- configSchema: Record<string, any>;
61
+ configSchema: JsonSchema;
62
+ uiSchema: UiSchema;
37
63
  };
38
64
  }
39
65
 
66
+ interface NodeInstanceReference {
67
+ workflowId: string;
68
+ workflowName: string;
69
+ version: number;
70
+ nodeId: string;
71
+ nodeLabel: string;
72
+ }
73
+
40
74
  export default function NodeInstanceShowPage() {
41
75
  const { t } = useTranslation('workflow');
42
76
  const { id } = useParams<{ id: string }>();
43
77
  const navigate = useNavigate();
44
78
  const [record, setRecord] = useState<NodeInstance | null>(null);
45
79
  const [loading, setLoading] = useState(true);
46
- const [references, setReferences] = useState<
47
- {
48
- workflowId: string;
49
- workflowName: string;
50
- version: number;
51
- nodeId: string;
52
- nodeLabel: string;
53
- }[]
54
- >([]);
80
+ const [references, setReferences] = useState<NodeInstanceReference[]>([]);
55
81
  const [refsLoading, setRefsLoading] = useState(false);
56
82
 
57
83
  const fetchRecord = useCallback(async () => {
@@ -71,7 +97,13 @@ export default function NodeInstanceShowPage() {
71
97
  createdAt: true,
72
98
  updatedAt: true,
73
99
  nodeType: {
74
- select: { label: true, category: true, configSchema: true },
100
+ select: {
101
+ type: true,
102
+ label: true,
103
+ category: true,
104
+ configSchema: true,
105
+ uiSchema: true,
106
+ },
75
107
  },
76
108
  },
77
109
  );
@@ -90,7 +122,10 @@ export default function NodeInstanceShowPage() {
90
122
  useEffect(() => {
91
123
  if (!id) return;
92
124
  setRefsLoading(true);
93
- customRequest<any[]>(`workflowNodeInstance/${id}/references`, 'POST')
125
+ customRequest<NodeInstanceReference[]>(
126
+ `workflowNodeInstance/${id}/references`,
127
+ 'POST',
128
+ )
94
129
  .then((res) => setReferences(Array.isArray(res) ? res : []))
95
130
  .catch(() => {
96
131
  setReferences([]);
@@ -109,11 +144,16 @@ export default function NodeInstanceShowPage() {
109
144
  }
110
145
  }
111
146
 
147
+ const nodeTypeLabel = useMemo(() => {
148
+ if (!record?.nodeType) return '—';
149
+ return t(`nodeTypes.${record.nodeType.type}`, {
150
+ defaultValue: record.nodeType.label,
151
+ });
152
+ }, [record?.nodeType, t]);
153
+
112
154
  if (loading) {
113
155
  return (
114
- <div
115
- style={{ display: 'flex', justifyContent: 'center', paddingTop: 120 }}
116
- >
156
+ <div className="node-instance-show__loading">
117
157
  <Spin size="large" />
118
158
  </div>
119
159
  );
@@ -121,25 +161,52 @@ export default function NodeInstanceShowPage() {
121
161
 
122
162
  if (!record) {
123
163
  return (
124
- <div style={{ padding: 24 }}>{t('nodeInstance.recordNotFound')}</div>
164
+ <div className="node-instance-show__not-found">
165
+ <Empty description={t('nodeInstance.recordNotFound')} />
166
+ <Button onClick={() => navigate('/admin/workflow/node-instances')}>
167
+ {t('common.back')}
168
+ </Button>
169
+ </div>
125
170
  );
126
171
  }
127
172
 
128
- const configSchema = record.nodeType?.configSchema as any;
129
- const configProperties = configSchema?.properties ?? {};
130
- const configData = record.config;
173
+ const hasConfiguration = Object.keys(record.config).length > 0;
174
+ const categoryLabel = record.nodeType?.category
175
+ ? t(`nodeCategories.${record.nodeType.category}`, {
176
+ defaultValue: record.nodeType.category,
177
+ })
178
+ : '—';
131
179
 
132
180
  return (
133
- <div className="workflow-page-stack" style={PAGE_WRAPPER_STYLE}>
134
- <PageHeader
135
- title={record.name}
136
- subtitle={t('nodeInstance.detailDescription')}
137
- extra={
138
- <Space>
139
- <Button onClick={() => navigate('/admin/workflow/node-instances')}>
140
- {t('common.back')}
141
- </Button>
181
+ <div
182
+ className="workflow-node-config node-instance-show"
183
+ style={PAGE_WRAPPER_STYLE}
184
+ >
185
+ <Card {...HEADER_CARD_PROPS}>
186
+ <div className="node-instance-show__header">
187
+ <div className="node-instance-show__header-main">
142
188
  <Button
189
+ type="text"
190
+ icon={<ArrowLeftOutlined />}
191
+ aria-label={t('common.back')}
192
+ onClick={() => navigate('/admin/workflow/node-instances')}
193
+ />
194
+ <div className="node-instance-show__heading">
195
+ <div className="node-instance-show__title-row">
196
+ <Title level={4}>{record.name}</Title>
197
+ <Tag color={record.isEnabled ? 'success' : 'default'}>
198
+ {t(record.isEnabled ? 'common.enabled' : 'common.disabled')}
199
+ </Tag>
200
+ </div>
201
+ <Text type="secondary">
202
+ {t('nodeInstance.detailDescription')}
203
+ </Text>
204
+ </div>
205
+ </div>
206
+
207
+ <Space wrap>
208
+ <Button
209
+ type="primary"
143
210
  icon={<EditOutlined />}
144
211
  onClick={() =>
145
212
  navigate(`/admin/workflow/node-instances/edit/${id}`)
@@ -160,105 +227,142 @@ export default function NodeInstanceShowPage() {
160
227
  </Button>
161
228
  </Popconfirm>
162
229
  </Space>
163
- }
164
- />
230
+ </div>
231
+ </Card>
165
232
 
166
- <Card title={t('nodeInstance.basicInfo')}>
167
- <Descriptions column={2}>
168
- <Descriptions.Item label={t('common.name')}>
169
- {record.name}
170
- </Descriptions.Item>
171
- <Descriptions.Item label={t('nodeInstance.nodeType')}>
172
- <Space>
173
- <span>{record.nodeType?.label ?? '—'}</span>
233
+ <Card style={CARD_GAP_STYLE}>
234
+ <div className="node-instance-show__section-heading">
235
+ <div>
236
+ <Title level={5}>{t('nodeInstance.basicInfo')}</Title>
237
+ <Text type="secondary">
238
+ {t('nodeInstance.detailSummaryDescription')}
239
+ </Text>
240
+ </div>
241
+ </div>
242
+
243
+ <div className="node-instance-show__summary-grid">
244
+ <SummaryItem label={t('nodeInstance.nodeType')}>
245
+ <Space size={6} wrap>
246
+ <Text strong>{nodeTypeLabel}</Text>
174
247
  {record.nodeType?.category && (
175
- <Tag color="blue">
176
- {t(`nodeCategories.${record.nodeType.category}`, {
177
- defaultValue: record.nodeType.category,
178
- })}
248
+ <Tag color={CATEGORY_COLORS[record.nodeType.category]}>
249
+ {categoryLabel}
179
250
  </Tag>
180
251
  )}
181
252
  </Space>
182
- </Descriptions.Item>
183
- <Descriptions.Item label={t('common.description')}>
184
- {record.description || '—'}
185
- </Descriptions.Item>
186
- <Descriptions.Item label={t('common.enabled')}>
187
- <Switch size="small" checked={record.isEnabled} disabled />
188
- </Descriptions.Item>
189
- <Descriptions.Item label={t('instances.creator')}>
190
- {record.creator || '—'}
191
- </Descriptions.Item>
192
- <Descriptions.Item label={t('nodeInstance.createdAt')}>
193
- {formatWorkflowUtcDateTime(record.createdAt)}
194
- </Descriptions.Item>
195
- <Descriptions.Item label={t('list.updatedAt')}>
196
- {formatWorkflowUtcDateTime(record.updatedAt)}
197
- </Descriptions.Item>
198
- </Descriptions>
253
+ </SummaryItem>
254
+ <SummaryItem label={t('nodeInstance.referenceCount')}>
255
+ <Text strong>{refsLoading ? '—' : references.length}</Text>
256
+ </SummaryItem>
257
+ <SummaryItem label={t('instances.creator')}>
258
+ <Text strong>{record.creator || '—'}</Text>
259
+ </SummaryItem>
260
+ <SummaryItem label={t('nodeInstance.createdAt')}>
261
+ <Text strong>{formatWorkflowUtcDateTime(record.createdAt)}</Text>
262
+ </SummaryItem>
263
+ <SummaryItem label={t('list.updatedAt')}>
264
+ <Text strong>{formatWorkflowUtcDateTime(record.updatedAt)}</Text>
265
+ </SummaryItem>
266
+ <SummaryItem label={t('nodeInstance.instanceId')}>
267
+ <Text code>{record.id}</Text>
268
+ </SummaryItem>
269
+ </div>
270
+
271
+ <div className="node-instance-show__description">
272
+ <Text type="secondary">{t('common.description')}</Text>
273
+ <Text>{record.description || t('nodeInstance.noDescription')}</Text>
274
+ </div>
199
275
  </Card>
200
276
 
201
- <Card title={t('common.configuration')}>
202
- {Object.keys(configData).length === 0 ? (
203
- <span style={{ color: '#999' }}>
204
- {t('nodeInstance.noConfiguration')}
205
- </span>
206
- ) : (
207
- <Descriptions column={1} bordered size="small">
208
- {Object.entries(configData).map(([key, value]) => {
209
- const prop = configProperties[key];
210
- const label = prop?.title || key;
211
- const displayValue =
212
- typeof value === 'boolean'
213
- ? value
214
- ? 'Yes'
215
- : 'No'
216
- : Array.isArray(value)
217
- ? value.join(', ')
218
- : String(value ?? '—');
219
- return (
220
- <Descriptions.Item key={key} label={label}>
221
- {displayValue}
222
- </Descriptions.Item>
223
- );
224
- })}
225
- </Descriptions>
226
- )}
277
+ <Card style={CARD_GAP_STYLE}>
278
+ <div className="node-instance-show__section-heading">
279
+ <div>
280
+ <Title level={5}>{t('editor.parameters')}</Title>
281
+ <Text type="secondary">
282
+ {t('nodeInstance.configurationDescription', {
283
+ name: nodeTypeLabel,
284
+ })}
285
+ </Text>
286
+ </div>
287
+ </div>
288
+
289
+ {!hasConfiguration ? (
290
+ <Empty
291
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
292
+ className="node-instance-show__empty"
293
+ description={t('nodeInstance.noConfiguration')}
294
+ />
295
+ ) : record.nodeType?.configSchema ? (
296
+ <Form
297
+ key={record.id}
298
+ layout="vertical"
299
+ disabled
300
+ initialValues={{ config: record.config }}
301
+ >
302
+ <div className="node-instance-show__configuration">
303
+ <SchemaForm
304
+ schema={record.nodeType.configSchema}
305
+ uiSchema={record.nodeType.uiSchema}
306
+ disabled
307
+ validate={false}
308
+ />
309
+ </div>
310
+ </Form>
311
+ ) : null}
227
312
  </Card>
228
313
 
229
- <Card title={t('nodeInstance.referencedBy')}>
314
+ <Card>
315
+ <div className="node-instance-show__section-heading">
316
+ <div>
317
+ <Title level={5}>{t('nodeInstance.referencedBy')}</Title>
318
+ <Text type="secondary">
319
+ {t('nodeInstance.referencesDescription')}
320
+ </Text>
321
+ </div>
322
+ {!refsLoading && <Tag>{references.length}</Tag>}
323
+ </div>
324
+
230
325
  {refsLoading ? (
231
- <Spin size="small" />
326
+ <div className="node-instance-show__references-loading">
327
+ <Spin size="small" />
328
+ </div>
232
329
  ) : references.length === 0 ? (
233
- <span style={{ color: '#999' }}>
234
- {t('nodeInstance.noReferences')}
235
- </span>
330
+ <Empty
331
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
332
+ className="node-instance-show__empty"
333
+ description={t('nodeInstance.noReferences')}
334
+ />
236
335
  ) : (
237
- <Table
336
+ <Table<NodeInstanceReference>
238
337
  dataSource={references}
239
- rowKey={(r) => `${r.workflowId}-${r.nodeId}`}
338
+ rowKey={(reference) =>
339
+ `${reference.workflowId}-${reference.nodeId}`
340
+ }
240
341
  pagination={false}
241
342
  size="small"
343
+ scroll={{ x: 560 }}
242
344
  columns={[
243
345
  {
244
346
  title: 'Workflow',
245
347
  dataIndex: 'workflowName',
246
- render: (name: string, record: any) => (
247
- <a
348
+ render: (name: string, reference) => (
349
+ <Button
350
+ type="link"
351
+ className="node-instance-show__workflow-link"
352
+ icon={<LinkOutlined />}
248
353
  onClick={() =>
249
- navigate(`/admin/workflow/show/${record.workflowId}`)
354
+ navigate(`/admin/workflow/show/${reference.workflowId}`)
250
355
  }
251
356
  >
252
- <LinkOutlined style={{ marginRight: 4 }} />
253
357
  {name}
254
- </a>
358
+ </Button>
255
359
  ),
256
360
  },
257
361
  {
258
362
  title: t('list.version'),
259
363
  dataIndex: 'version',
260
- width: 80,
261
- render: (v: number) => `v${v}`,
364
+ width: 100,
365
+ render: (version: number) => <Tag>{`v${version}`}</Tag>,
262
366
  },
263
367
  {
264
368
  title: t('nodeInstance.node'),
@@ -271,3 +375,18 @@ export default function NodeInstanceShowPage() {
271
375
  </div>
272
376
  );
273
377
  }
378
+
379
+ function SummaryItem({
380
+ label,
381
+ children,
382
+ }: {
383
+ label: React.ReactNode;
384
+ children: React.ReactNode;
385
+ }) {
386
+ return (
387
+ <div className="node-instance-show__summary-item">
388
+ <Text type="secondary">{label}</Text>
389
+ <div>{children}</div>
390
+ </div>
391
+ );
392
+ }
@@ -25,7 +25,7 @@ describe('CodeConfigEditor context guidance', () => {
25
25
  [
26
26
  'approverLookup',
27
27
  '查询审批人接口返回的 { status, data, headers }。',
28
- '返回 { subjects: [{ provider, refs }] },用于确定本次审批人。',
28
+ "返回人员 ID 数组,例如 ['zhangsan', 'lisi']。",
29
29
  ],
30
30
  [
31
31
  'approvalCreation',
@@ -1,5 +1,6 @@
1
- import { Input, InputNumber, Space, Switch, Typography } from 'antd';
1
+ import { InputNumber, Space, Switch, Tag, Typography } from 'antd';
2
2
  import { useTranslation } from 'react-i18next';
3
+ import { WorkflowCodeEditor } from '../../components/WorkflowCodeEditor';
3
4
  import type { ParameterBinding } from '../../types/parameter-binding';
4
5
  import type { WidgetProps } from '../schema-form/widget-registry';
5
6
  import { ParameterBindingListEditor } from './ParameterBindingListEditor';
@@ -82,18 +83,26 @@ export function DbExecuteConfigEditor({
82
83
  </div>
83
84
 
84
85
  <Space direction="vertical" size={6} style={{ width: '100%' }}>
85
- <Typography.Text>{t('nodeEditors.database.sql')}</Typography.Text>
86
- <Input.TextArea
87
- aria-label={t('nodeEditors.database.sql')}
86
+ <div className="db-execute-config__sql-head">
87
+ <Typography.Text strong>
88
+ {t('nodeEditors.database.sql')}
89
+ </Typography.Text>
90
+ <Tag bordered={false} color={allowWrite ? 'orange' : 'green'}>
91
+ {t(
92
+ allowWrite
93
+ ? 'nodeEditors.database.writeEnabled'
94
+ : 'nodeEditors.database.readOnly',
95
+ )}
96
+ </Tag>
97
+ </div>
98
+ <WorkflowCodeEditor
99
+ language="sql"
88
100
  value={config.sql ?? ''}
89
- disabled={disabled}
90
- rows={7}
91
- placeholder={
92
- allowWrite
93
- ? 'UPDATE users SET active = $1 WHERE id = $2'
94
- : 'SELECT id, name FROM users WHERE id = $1'
95
- }
96
- onChange={(event) => onChange({ ...config, sql: event.target.value })}
101
+ readOnly={disabled}
102
+ height={280}
103
+ wordWrap="off"
104
+ ariaLabel={t('nodeEditors.database.sql')}
105
+ onChange={(sql) => onChange({ ...config, sql })}
97
106
  />
98
107
  </Space>
99
108