@gadmin2n/schematics 0.0.147 → 0.0.148

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 (92) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +1 -0
  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 +17 -4
  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/codeRuntime/code-runtime.controller.spec.ts +2 -6
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.spec.ts +28 -29
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.ts +16 -34
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +3 -3
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.spec.ts +61 -6
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.spec.ts +2 -2
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -0
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.controller.ts +11 -0
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.spec.ts +126 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.ts +136 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.controller.ts +24 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.dto.ts +8 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.service.spec.ts +62 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.service.ts +94 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staff-directory.types.ts +6 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/staffDirectory/staffDirectory.module.ts +10 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/providers/user.provider.ts +6 -2
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +20 -12
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +21 -19
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.ts +11 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.spec.ts +97 -0
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.ts +150 -2
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.controller.ts +13 -1
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.dto.ts +13 -1
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.errors.ts +1 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.service.spec.ts +125 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.service.ts +118 -5
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-cancellation.spec.ts +20 -3
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +6 -9
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-runtime.facade.ts +2 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.spec.ts +4 -1
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +5 -1
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +44 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +15 -1
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.spec.ts +2 -3
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.spec.ts +33 -22
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.ts +10 -23
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/StaffSelect.test.tsx +69 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/StaffSelect.tsx +145 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/index.ts +2 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/StaffSelect/staff-directory.api.ts +16 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +1 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.test.ts +10 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +20 -2
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +6 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +49 -11
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +49 -11
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/people-groups/PeopleGroupModal.tsx +181 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/people-groups/index.tsx +203 -0
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/people-groups/people-groups.api.ts +145 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/person-directory/PersonModal.tsx +112 -0
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/person-directory/index.tsx +214 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/person-directory/person-directory.api.ts +79 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/form-modal.tsx +7 -11
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +7 -7
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.test.tsx +20 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +97 -28
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +87 -119
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.test.tsx +22 -1
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.tsx +8 -2
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connections.css +8 -46
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connectionsApi.ts +7 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.test.tsx +32 -3
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.tsx +163 -106
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +8 -1
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.test.tsx +26 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +34 -6
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-config.css +13 -16
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-instance-show.css +185 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +224 -105
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.test.tsx +1 -1
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DbExecuteConfigEditor.tsx +21 -12
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerConfigEditor.tsx +1 -2
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +160 -8
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +125 -55
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SimplifiedNodeEditors.test.tsx +47 -3
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.test.tsx +33 -1
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.tsx +28 -46
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/human-approval-config.css +16 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/subject-provider.api.ts +0 -6
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.test.tsx +24 -0
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +14 -17
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +1 -0
  90. package/package.json +1 -1
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CreateNodeInstanceDrawer.tsx +0 -162
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupCreateModal.tsx +0 -72
@@ -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
 
@@ -268,8 +268,7 @@ export function EventTriggerConfigEditor({
268
268
  className="workflow-node-config__inline-message"
269
269
  >
270
270
  <code>
271
- {selectedEvent.schemaName}.{selectedEvent.tableName} ·{' '}
272
- {selectedEvent.watchedFields.join(', ')}
271
+ {selectedEvent.schemaName}.{selectedEvent.tableName}
273
272
  </code>
274
273
  </Typography.Text>
275
274
  )}