@gadmin2n/schematics 0.0.142 → 0.0.143

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 (139) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +5 -23
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +4 -2
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/page-manage.ts +36 -1
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/agenda.seed.ts +14 -14
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/bootstrap.ts +18 -13
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/canvas.seed.ts +14 -14
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +1 -1
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +67 -404
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +16 -40
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +12 -124
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.module.ts +3 -0
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/config/index.ts +0 -21
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.ts +3 -10
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/codeRuntime.module.ts +1 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-callback.controller.spec.ts +48 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-callback.controller.ts +96 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.spec.ts +1 -59
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.ts +8 -43
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.dto.ts +0 -23
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.ts +2 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-wait.handler.ts +2 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/externalInteraction.module.ts +7 -3
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.controller.ts +2 -2
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.service.spec.ts +18 -123
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.service.ts +4 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.ts +3 -10
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/httpRequest.module.ts +1 -2
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.controller.ts +0 -10
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +12 -4
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.errors.ts +1 -1
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.external-decision.spec.ts +42 -209
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.ts +108 -225
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/humanApproval.module.ts +0 -2
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.ts +27 -22
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.dto.ts +9 -1
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/runtime-token.guard.spec.ts +30 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/runtime-token.guard.ts +8 -15
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +0 -2
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/runtime-connectivity-probe.service.spec.ts +14 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/runtime-connectivity-probe.service.ts +37 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +41 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +53 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.module.ts +7 -2
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/workflow-runtime-health.controller.ts +21 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.spec.ts +2 -2
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.spec.ts +16 -88
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.ts +23 -59
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +125 -39
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.ts +95 -28
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.ts +0 -20
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.spec.ts +23 -26
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.ts +6 -52
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +2 -2
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +24 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +26 -21
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.spec.ts +0 -1
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.ts +0 -1
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowRuntimeConfig/workflow-runtime-config.service.spec.ts +32 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowRuntimeConfig/workflow-runtime-config.service.ts +41 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowRuntimeConfig/workflowRuntimeConfig.module.ts +10 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/server/tsconfig.build.json +10 -1
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +16 -12
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/PageHeader.tsx +1 -1
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +19 -19
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +1 -1
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +15 -11
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +0 -6
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +3 -3
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +1 -1
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DeleteDataConfirm.tsx +1 -1
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/EditDataModal.tsx +1 -1
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +1 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +85 -95
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +85 -95
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +2 -2
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +21 -2
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/list.tsx +21 -2
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/inbox.tsx +14 -66
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +4 -4
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +3 -3
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +3 -3
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.test.tsx +29 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +4 -2
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/EnhancedFlowRenderer.tsx +4 -6
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.test.tsx +3 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.tsx +3 -1
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +4 -6
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NewNodeDefaults.test.tsx +23 -92
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.tsx +200 -0
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +61 -136
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +96 -195
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeTypeBadge.tsx +36 -0
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +5 -10
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +47 -22
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +7 -5
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +8 -6
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-config.css +35 -0
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/default-widgets.tsx +1 -6
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.tsx +1 -4
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.tsx +1 -1
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.tsx +1 -1
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalWaitConfigEditor.tsx +82 -259
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.tsx +1 -2
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +7 -6
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +77 -71
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.test.tsx +10 -57
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.tsx +8 -273
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.test.tsx +54 -0
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +110 -20
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/newNodeConfig.ts +4 -34
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.test.ts +3 -10
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.ts +2 -37
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +26 -2
  114. package/package.json +1 -1
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.controller.ts +0 -89
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.dto.ts +0 -68
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.service.spec.ts +0 -177
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.service.ts +0 -283
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approvalChannel.module.ts +0 -10
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/ApprovalChannelModal.test.tsx +0 -84
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/ApprovalChannelModal.tsx +0 -141
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/approval-channel.types.ts +0 -16
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/index.tsx +0 -210
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRequestTriggerConfigEditor.tsx +0 -39
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubmitApprovalResultConfigEditor.tsx +0 -104
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubmitExternalResultConfigEditor.tsx +0 -98
  127. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/AssignRolesModal.tsx +0 -0
  128. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/CreatePageModal.tsx +0 -0
  129. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/EditPageModal.tsx +0 -0
  130. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/PageDetailDrawer.tsx +0 -0
  131. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/{Components → components}/PageFormModal.tsx +0 -0
  132. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/CreateModal.tsx +0 -0
  133. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/EditModal.tsx +0 -0
  134. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/ResourceDetailDrawer.tsx +0 -0
  135. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/{Components → components}/modal.tsx +0 -0
  136. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/CreateModal.tsx +0 -0
  137. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/EditModal.tsx +0 -0
  138. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/RoleDetailDrawer.tsx +0 -0
  139. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/{Components → components}/modal.tsx +0 -0
@@ -0,0 +1,200 @@
1
+ import { Tag, Typography } from 'antd';
2
+ import { useTranslation } from 'react-i18next';
3
+ import type { WorkflowNode, WorkflowNodeType } from '../types';
4
+ import { resolveOutputs } from '../utils/resolveOutputs';
5
+
6
+ const { Text } = Typography;
7
+
8
+ interface OutputField {
9
+ path: string;
10
+ type: string;
11
+ description?: string;
12
+ required: boolean;
13
+ }
14
+
15
+ interface Props {
16
+ node: WorkflowNode;
17
+ nodeType?: WorkflowNodeType;
18
+ }
19
+
20
+ const DYNAMIC_OUTPUT_KEYS: Partial<Record<string, string>> = {
21
+ cron_trigger: 'workflowData',
22
+ manual_trigger: 'workflowData',
23
+ callable_trigger: 'workflowData',
24
+ code: 'codeReturn',
25
+ sub_workflow: 'workflowReturn',
26
+ return_result: 'returnPrevious',
27
+ };
28
+
29
+ function schemaType(schema: Record<string, any>): string {
30
+ if (Array.isArray(schema.type)) return schema.type.join(' | ');
31
+ if (typeof schema.type === 'string') return schema.type;
32
+ if (schema.enum) return 'enum';
33
+ return 'any';
34
+ }
35
+
36
+ function outputFields(schema: Record<string, any>): OutputField[] {
37
+ const properties =
38
+ schema.properties && typeof schema.properties === 'object'
39
+ ? schema.properties
40
+ : {};
41
+ const required = new Set<string>(
42
+ Array.isArray(schema.required) ? schema.required : [],
43
+ );
44
+
45
+ return Object.entries<Record<string, any>>(properties).map(
46
+ ([name, property]) => ({
47
+ path: `input.${name}`,
48
+ type: schemaType(property ?? {}),
49
+ description:
50
+ typeof property?.description === 'string'
51
+ ? property.description
52
+ : undefined,
53
+ required: required.has(name),
54
+ }),
55
+ );
56
+ }
57
+
58
+ export function NodeOutputSummary({ node, nodeType }: Props) {
59
+ const { t } = useTranslation('workflow');
60
+ const branches = resolveOutputs(node, nodeType);
61
+ const dynamicOutputKey = DYNAMIC_OUTPUT_KEYS[node.type];
62
+ const fields = dynamicOutputKey
63
+ ? []
64
+ : outputFields((nodeType?.outputSchema ?? {}) as Record<string, any>);
65
+ const schemaDescription =
66
+ typeof nodeType?.outputSchema?.description === 'string'
67
+ ? nodeType.outputSchema.description
68
+ : undefined;
69
+
70
+ const branchLabel = (branch: string) => {
71
+ if (node.type === 'external_wait') {
72
+ return branch === 'RECEIVED'
73
+ ? t('editor.output.branchLabels.received')
74
+ : t('editor.output.branchLabels.timedOut');
75
+ }
76
+ if (node.type === 'approval' || node.type === 'human_approval') {
77
+ return branch === 'true'
78
+ ? t('editor.output.branchLabels.approved')
79
+ : t('editor.output.branchLabels.rejected');
80
+ }
81
+ if (node.type === 'if_else') {
82
+ return branch === 'true'
83
+ ? t('editor.output.branchLabels.matched')
84
+ : t('editor.output.branchLabels.notMatched');
85
+ }
86
+ return branch;
87
+ };
88
+
89
+ return (
90
+ <section
91
+ aria-label={t('editor.output.title')}
92
+ style={{
93
+ border: '1px solid var(--ant-color-border-secondary)',
94
+ borderRadius: 8,
95
+ overflow: 'hidden',
96
+ background: 'var(--ant-color-fill-quaternary)',
97
+ }}
98
+ >
99
+ <div
100
+ style={{
101
+ padding: '10px 12px',
102
+ borderBottom: '1px solid var(--ant-color-border-secondary)',
103
+ background: 'var(--ant-color-bg-container)',
104
+ }}
105
+ >
106
+ <Text strong style={{ fontSize: 13 }}>
107
+ {t('editor.output.title')}
108
+ </Text>
109
+ <Text
110
+ type="secondary"
111
+ style={{ display: 'block', marginTop: 2, fontSize: 11 }}
112
+ >
113
+ {t('editor.output.hint')}
114
+ </Text>
115
+ </div>
116
+
117
+ <div style={{ padding: '10px 12px' }}>
118
+ {branches.length > 1 && (
119
+ <div style={{ marginBottom: fields.length > 0 ? 10 : 0 }}>
120
+ <Text
121
+ type="secondary"
122
+ style={{ display: 'block', marginBottom: 6, fontSize: 11 }}
123
+ >
124
+ {t('editor.output.flowBranches')}
125
+ </Text>
126
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
127
+ {branches.map((branch) => (
128
+ <Tag key={branch} color="blue" style={{ marginInlineEnd: 0 }}>
129
+ {branchLabel(branch)}
130
+ </Tag>
131
+ ))}
132
+ </div>
133
+ </div>
134
+ )}
135
+
136
+ {fields.length > 0 ? (
137
+ <div
138
+ style={{
139
+ display: 'grid',
140
+ gap: 1,
141
+ borderRadius: 6,
142
+ overflow: 'hidden',
143
+ background: 'var(--ant-color-border-secondary)',
144
+ }}
145
+ >
146
+ {fields.map((field) => (
147
+ <div
148
+ key={field.path}
149
+ style={{
150
+ display: 'grid',
151
+ gridTemplateColumns: 'minmax(0, 1fr) auto',
152
+ gap: 8,
153
+ alignItems: 'center',
154
+ padding: '7px 9px',
155
+ background: 'var(--ant-color-bg-container)',
156
+ }}
157
+ >
158
+ <div style={{ minWidth: 0 }}>
159
+ <Text
160
+ code
161
+ style={{ display: 'block', fontSize: 11, margin: 0 }}
162
+ >
163
+ {field.path}
164
+ </Text>
165
+ {field.description && (
166
+ <Text
167
+ type="secondary"
168
+ ellipsis={{ tooltip: field.description }}
169
+ style={{ display: 'block', marginTop: 2, fontSize: 11 }}
170
+ >
171
+ {field.description}
172
+ </Text>
173
+ )}
174
+ </div>
175
+ <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
176
+ {field.required && (
177
+ <Text type="secondary" style={{ fontSize: 10 }}>
178
+ {t('editor.output.required')}
179
+ </Text>
180
+ )}
181
+ <Tag bordered={false} style={{ marginInlineEnd: 0 }}>
182
+ {t(`editor.output.types.${field.type}`, {
183
+ defaultValue: field.type,
184
+ })}
185
+ </Tag>
186
+ </div>
187
+ </div>
188
+ ))}
189
+ </div>
190
+ ) : (
191
+ <Text type="secondary" style={{ fontSize: 12 }}>
192
+ {dynamicOutputKey
193
+ ? t(`editor.output.dynamic.${dynamicOutputKey}`)
194
+ : schemaDescription || t('editor.output.dynamic.anyValue')}
195
+ </Text>
196
+ )}
197
+ </div>
198
+ </section>
199
+ );
200
+ }
@@ -54,6 +54,7 @@ describe('NodePropertyPanel instance references', () => {
54
54
  it('renders a referenced node with the editable template config form', async () => {
55
55
  vi.mocked(customRequest).mockImplementation((path) => {
56
56
  if (path === 'subject-providers') return Promise.resolve([]) as never;
57
+ if (path === 'workflow/callable') return Promise.resolve([]) as never;
57
58
  return Promise.resolve({
58
59
  data: [
59
60
  {
@@ -88,8 +89,14 @@ describe('NodePropertyPanel instance references', () => {
88
89
  });
89
90
  expect(screen.getByText('Who can approve')).toBeInTheDocument();
90
91
  expect(
91
- screen.getByText('修改只会保存在当前 Workflow,不会修改 Node Template。'),
92
+ screen.getByText('Changes apply only to this Workflow.'),
92
93
  ).toBeInTheDocument();
94
+ expect(
95
+ screen.getByRole('heading', { name: 'Node configuration' }),
96
+ ).toBeInTheDocument();
97
+ expect(screen.getByText('Node type')).toBeInTheDocument();
98
+ expect(screen.getByText('Human Approval')).toBeInTheDocument();
99
+ expect(screen.queryByText('approval')).not.toBeInTheDocument();
93
100
  expect(
94
101
  screen.getByRole('button', { name: 'Save changes' }),
95
102
  ).toBeInTheDocument();
@@ -99,22 +106,19 @@ describe('NodePropertyPanel instance references', () => {
99
106
  const returnNodeType = {
100
107
  id: '9',
101
108
  type: 'return_result',
102
- label: 'Return result',
109
+ label: 'Finish and return',
103
110
  category: 'ACTION',
104
111
  instancePolicy: 'INLINE_ONLY',
105
112
  configSchema: {
106
113
  type: 'object',
107
- properties: {
108
- resultType: { type: 'string' },
109
- path: { type: 'string' },
110
- },
114
+ properties: {},
111
115
  },
112
116
  uiSchema: {},
113
117
  } as unknown as WorkflowNodeType;
114
118
  const returnNode: WorkflowNode = {
115
119
  id: 'return-1',
116
120
  type: 'return_result',
117
- label: 'Return result',
121
+ label: 'Finish and return',
118
122
  position: { x: 0, y: 0 },
119
123
  config: {},
120
124
  };
@@ -131,9 +135,57 @@ describe('NodePropertyPanel instance references', () => {
131
135
  );
132
136
 
133
137
  expect(
134
- screen.getByText('Return the previous node result'),
138
+ screen.getByText('Returns the previous node result'),
135
139
  ).toBeInTheDocument();
136
- expect(screen.queryByLabelText('Workflow data field')).toBeNull();
140
+ expect(screen.queryByText('Result type')).toBeNull();
141
+ });
142
+
143
+ it('shows the node output contract as read-only input paths', () => {
144
+ const httpNodeType = {
145
+ id: '10',
146
+ type: 'http_request',
147
+ label: 'HTTP Request',
148
+ category: 'ACTION',
149
+ instancePolicy: 'INLINE_ONLY',
150
+ configSchema: { type: 'object', properties: {} },
151
+ outputSchema: {
152
+ type: 'object',
153
+ properties: {
154
+ status: { type: 'number', description: 'HTTP status code' },
155
+ data: { description: 'Response body' },
156
+ headers: { type: 'object' },
157
+ },
158
+ },
159
+ outputs: [],
160
+ uiSchema: {},
161
+ } as unknown as WorkflowNodeType;
162
+ const httpNode: WorkflowNode = {
163
+ id: 'http-1',
164
+ type: 'http_request',
165
+ label: 'Create order',
166
+ position: { x: 0, y: 0 },
167
+ config: {},
168
+ };
169
+
170
+ render(
171
+ <NodePropertyPanel
172
+ node={httpNode}
173
+ nodeTypes={[httpNodeType]}
174
+ onSave={vi.fn()}
175
+ onLabelChange={vi.fn()}
176
+ onAiEdit={vi.fn()}
177
+ aiLoading={false}
178
+ />,
179
+ );
180
+
181
+ expect(
182
+ screen.getByRole('region', { name: 'Output (read-only)' }),
183
+ ).toBeInTheDocument();
184
+ expect(screen.getByText('input.status')).toBeInTheDocument();
185
+ expect(screen.getByText('input.data')).toBeInTheDocument();
186
+ expect(screen.getByText('input.headers')).toBeInTheDocument();
187
+ expect(screen.getByText('HTTP status code')).toBeInTheDocument();
188
+ expect(screen.getByText('Any value')).toBeInTheDocument();
137
189
  });
138
190
 
139
191
  it('uses nested UI Schema widgets for Callable Trigger parameters', async () => {
@@ -205,131 +257,4 @@ describe('NodePropertyPanel instance references', () => {
205
257
  }),
206
258
  );
207
259
  });
208
-
209
- it('does not carry Code configuration into Submit External Result when switching nodes', async () => {
210
- const user = userEvent.setup();
211
- const onSave = vi.fn();
212
- const codeNodeType = {
213
- id: 'code',
214
- type: 'code',
215
- label: 'Code',
216
- category: 'ACTION',
217
- instancePolicy: 'INLINE_ONLY',
218
- configSchema: {
219
- type: 'object',
220
- properties: {
221
- mode: { type: 'string' },
222
- script: { type: 'string' },
223
- timeout: { type: 'integer' },
224
- },
225
- },
226
- uiSchema: { widget: 'code-config' },
227
- } as unknown as WorkflowNodeType;
228
- const submitNodeType = {
229
- id: 'submit-external-result',
230
- type: 'submit_external_result',
231
- label: 'Submit external result',
232
- category: 'ACTION',
233
- instancePolicy: 'INLINE_ONLY',
234
- configSchema: {
235
- type: 'object',
236
- properties: {
237
- inputBindings: { type: 'object' },
238
- },
239
- },
240
- uiSchema: { widget: 'submit-external-result-config' },
241
- } as unknown as WorkflowNodeType;
242
- const codeNode: WorkflowNode = {
243
- id: 'code-1',
244
- type: 'code',
245
- label: 'Transform callback',
246
- position: { x: 0, y: 0 },
247
- config: {
248
- mode: 'runOnceForAll',
249
- script: 'return input;',
250
- timeout: 1000,
251
- },
252
- };
253
- const inputBindings = {
254
- callbackToken: { source: 'INPUT' as const, path: 'callbackToken' },
255
- eventId: { source: 'INPUT' as const, path: 'eventId' },
256
- outcome: { source: 'INPUT' as const, path: 'outcome' },
257
- };
258
- const submitNode: WorkflowNode = {
259
- id: 'submit-1',
260
- type: 'submit_external_result',
261
- label: 'Submit external result',
262
- position: { x: 100, y: 0 },
263
- config: { inputBindings },
264
- };
265
- const nodeTypes = [codeNodeType, submitNodeType];
266
- const commonProps = {
267
- nodeTypes,
268
- onSave,
269
- onLabelChange: vi.fn(),
270
- onAiEdit: vi.fn(),
271
- aiLoading: false,
272
- };
273
-
274
- const { rerender } = render(
275
- <NodePropertyPanel {...commonProps} node={codeNode} />,
276
- );
277
-
278
- rerender(<NodePropertyPanel {...commonProps} node={submitNode} />);
279
- await user.click(screen.getByRole('button', { name: 'Save changes' }));
280
-
281
- expect(onSave).toHaveBeenLastCalledWith('submit-1', {
282
- label: 'Submit external result',
283
- config: { inputBindings },
284
- });
285
- });
286
-
287
- it('hides legacy trigger and approval callback nodes from the palette', () => {
288
- render(
289
- <NodePropertyPanel
290
- node={null}
291
- nodeTypes={
292
- [
293
- {
294
- id: 'callable',
295
- type: 'callable_trigger',
296
- label: '接收调用',
297
- category: 'TRIGGER',
298
- },
299
- {
300
- id: 'legacy-approval',
301
- type: 'approval_request_trigger',
302
- label: '接收审批请求',
303
- category: 'TRIGGER',
304
- },
305
- {
306
- id: 'webhook',
307
- type: 'webhook_trigger',
308
- label: 'Webhook Trigger',
309
- category: 'TRIGGER',
310
- },
311
- {
312
- id: 'submit-result',
313
- type: 'submit_approval_result',
314
- label: 'Submit approval result',
315
- category: 'ACTION',
316
- },
317
- ] as WorkflowNodeType[]
318
- }
319
- onSave={vi.fn()}
320
- onLabelChange={vi.fn()}
321
- onAiEdit={vi.fn()}
322
- aiLoading={false}
323
- />,
324
- );
325
-
326
- expect(screen.getByText('Receive call')).toBeInTheDocument();
327
- expect(
328
- screen.queryByText('Receive approval request'),
329
- ).not.toBeInTheDocument();
330
- expect(screen.getByText('Receive external request')).toBeInTheDocument();
331
- expect(
332
- screen.queryByText('Submit approval result'),
333
- ).not.toBeInTheDocument();
334
- });
335
260
  });