@gadmin2n/schematics 0.0.144 → 0.0.145

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 (279) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/.types.d.ts +10 -0
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/approval.prisma +2 -0
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +140 -19
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +2 -2
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/data-mngt.seed.ts +0 -2
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +694 -327
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-outbox.ts +57 -0
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +35 -5
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +224 -59
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-executor.spec.ts +23 -0
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-executor.ts +16 -5
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.spec.ts +98 -0
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.ts +26 -6
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.dto.ts +17 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.spec.ts +1 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.ts +3 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.dto.ts +0 -2
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-signal-outbox.service.spec.ts +30 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-signal-outbox.service.ts +28 -6
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.spec.ts +63 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.ts +151 -38
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-wait.handler.ts +4 -1
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/human-approval.handler.spec.ts +16 -5
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/human-approval.handler.ts +23 -6
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.spec.ts +130 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.ts +62 -62
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.dto.ts +15 -1
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.util.spec.ts +70 -9
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.util.ts +31 -7
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-signal-outbox.service.spec.ts +30 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-signal-outbox.service.ts +28 -6
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.spec.ts +50 -3
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.ts +26 -3
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +53 -47
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.errors.ts +0 -1
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.spec.ts +541 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.ts +442 -200
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/outbox-retry.util.ts +1 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.spec.ts +150 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.ts +56 -40
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.dto.ts +16 -60
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.controller.ts +13 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.spec.ts +44 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.ts +6 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.spec.ts +258 -12
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.ts +127 -14
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/manual-workflow-execution.spec.ts +85 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/manual-workflow-execution.ts +108 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/parameter-binding.ts +5 -5
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.spec.ts +96 -25
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +77 -34
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.spec.ts +23 -34
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.ts +0 -21
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-cancellation.spec.ts +245 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +639 -188
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.ts +408 -235
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.types.ts +1 -3
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-data-edge.util.spec.ts +279 -95
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-data-edge.util.ts +360 -80
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-event-catalog.spec.ts +323 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution-idempotency.spec.ts +773 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +7 -13
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +0 -16
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.spec.ts +184 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +69 -138
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.spec.ts +113 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.ts +59 -13
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-runtime.facade.ts +86 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-switch-config.spec.ts +25 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-switch-config.ts +45 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.spec.ts +78 -43
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +103 -40
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +57 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +3 -1
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +1000 -240
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +2184 -317
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.spec.ts +279 -2
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.ts +5 -1
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.spec.ts +4 -1
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.ts +5 -1
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.spec.ts +12 -3
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.ts +10 -1
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +2 -24
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +3 -70
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +3 -1
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/RowActions.tsx +25 -5
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/WorkflowActionButton.test.tsx +71 -0
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/WorkflowActionButton.tsx +89 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +1 -0
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +52 -12
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +12 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +2 -2
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +10 -33
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +13 -37
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +55 -7
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +14 -0
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/http.ts +10 -0
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +1 -0
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/workflowAction.ts +19 -0
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/index.ts +1 -0
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/types.ts +3 -1
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +1 -6
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useReferenceUpload.ts +95 -0
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +2 -2
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +672 -110
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +2 -2
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +676 -114
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +13 -1
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +1 -0
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +38 -4
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +276 -376
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/CanvasAiModal.tsx +126 -6
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/DecisionModal.test.tsx +50 -0
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/DecisionModal.tsx +48 -11
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/inbox.tsx +32 -34
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/RegisterBusinessEventModal.test.tsx +111 -0
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/RegisterBusinessEventModal.tsx +167 -0
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/business-events.css +99 -0
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/detail.test.tsx +106 -0
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/detail.tsx +324 -0
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/index.test.tsx +73 -0
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/index.tsx +359 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CanvasZoomControls.tsx +46 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CreateNodeInstanceDrawer.tsx +9 -1
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.test.tsx +105 -4
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +90 -48
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DeletableEdge.tsx +3 -2
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.test.tsx +259 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.tsx +167 -103
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/EnhancedFlowRenderer.tsx +142 -140
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.test.tsx +60 -15
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.tsx +25 -12
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +364 -200
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NewNodeDefaults.test.tsx +220 -52
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.test.tsx +260 -0
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.tsx +300 -130
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +507 -33
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +630 -592
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ParameterBindingEditor.tsx +67 -70
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ReadonlyNodePanel.test.tsx +90 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ReadonlyNodePanel.tsx +325 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.test.tsx +52 -0
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +14 -9
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +2 -1
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +2 -1
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.test.tsx +42 -0
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.tsx +76 -0
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowWorkspaceHeader.tsx +56 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/parameter-binding-editor.css +46 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/workflow-code-editor.css +34 -0
  151. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/ConnectionModal.test.tsx +53 -7
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/ConnectionModal.tsx +123 -62
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connections.css +85 -0
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connectionsApi.ts +29 -0
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.test.tsx +75 -0
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.tsx +69 -36
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.test.tsx +494 -0
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +665 -194
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useReferencedNodeInstanceConfigs.test.tsx +92 -0
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useReferencedNodeInstanceConfigs.ts +96 -0
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.test.tsx +297 -0
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +135 -65
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +53 -42
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +344 -155
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +79 -58
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +123 -144
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +169 -98
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/node-instance-form.css +91 -0
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +54 -31
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-config.css +854 -0
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaField.tsx +41 -14
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaForm.test.tsx +75 -0
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaForm.tsx +3 -0
  174. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/default-widgets.tsx +20 -2
  175. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/widget-registry.tsx +2 -1
  176. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +61 -66
  177. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRuleEditor.test.tsx +33 -1
  178. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRuleEditor.tsx +47 -15
  179. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/BranchConfigEditors.test.tsx +104 -0
  180. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CallableInputParametersEditor.tsx +22 -52
  181. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.test.tsx +72 -0
  182. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.tsx +78 -70
  183. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CronTriggerConfigEditor.tsx +569 -0
  184. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DbExecuteConfigEditor.tsx +130 -0
  185. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DelayConfigEditor.tsx +100 -0
  186. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerConfigEditor.tsx +620 -0
  187. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.test.tsx +22 -45
  188. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.tsx +25 -92
  189. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalWaitConfigEditor.tsx +3 -11
  190. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ForEachConfigEditor.test.tsx +58 -0
  191. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ForEachConfigEditor.tsx +107 -0
  192. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.test.tsx +212 -31
  193. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.tsx +214 -304
  194. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +175 -40
  195. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +693 -293
  196. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/IfElseConfigEditor.tsx +190 -0
  197. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ManualTriggerConfigEditor.test.tsx +152 -0
  198. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ManualTriggerConfigEditor.tsx +286 -0
  199. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ParallelConfigEditor.tsx +101 -0
  200. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ParameterBindingListEditor.tsx +99 -0
  201. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SimplifiedNodeEditors.test.tsx +495 -0
  202. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubWorkflowConfigEditor.test.tsx +124 -0
  203. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubWorkflowConfigEditor.tsx +222 -0
  204. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.tsx +2 -4
  205. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SwitchConfigEditor.tsx +204 -0
  206. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupCreateModal.tsx +3 -1
  207. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupEditModal.tsx +9 -6
  208. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/callable-workflow.ts +4 -0
  209. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/code-config.css +96 -0
  210. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/event-catalog.api.ts +117 -0
  211. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/http-request-config.css +242 -0
  212. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/human-approval-config.css +194 -0
  213. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +264 -167
  214. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +6 -9
  215. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types/parameter-binding.ts +19 -16
  216. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +28 -4
  217. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/useWorkflowFormValidation.test.tsx +59 -0
  218. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/useWorkflowFormValidation.ts +24 -0
  219. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/forEachConnection.test.ts +311 -0
  220. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/forEachConnection.ts +198 -0
  221. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/mainFlowConnection.test.ts +143 -0
  222. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/mainFlowConnection.ts +19 -0
  223. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/newNodeConfig.ts +103 -5
  224. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/removeWorkflowEdges.test.ts +158 -3
  225. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/removeWorkflowEdges.ts +117 -9
  226. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveEffectiveOutput.test.ts +70 -0
  227. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveEffectiveOutput.ts +48 -0
  228. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveLookupPorts.test.ts +55 -0
  229. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveLookupPorts.ts +95 -22
  230. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.test.ts +148 -1
  231. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.ts +62 -11
  232. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveWorkflowDisplay.test.ts +19 -0
  233. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveWorkflowDisplay.ts +1 -1
  234. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/subWorkflowChange.test.ts +45 -0
  235. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/subWorkflowChange.ts +26 -0
  236. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/validateWorkflowDsl.test.ts +502 -0
  237. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/validateWorkflowDsl.ts +694 -0
  238. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowDateTime.test.ts +27 -0
  239. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowDateTime.ts +33 -0
  240. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowHistory.test.ts +34 -0
  241. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowHistory.ts +52 -0
  242. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowPublishError.test.ts +99 -0
  243. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowPublishError.ts +91 -0
  244. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowSkillPrompt.test.ts +74 -0
  245. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowSkillPrompt.ts +120 -0
  246. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/workflow-ui.css +481 -0
  247. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/index.css +1 -1
  248. package/package.json +1 -1
  249. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +0 -62
  250. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/migrate-human-approval-configs.ts +0 -86
  251. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-event-trigger.ts +0 -60
  252. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.external-decision.spec.ts +0 -183
  253. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/legacy-approval-config-migration.ts +0 -227
  254. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.spec.ts +0 -82
  255. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.ts +0 -111
  256. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +0 -54
  257. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +0 -147
  258. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +0 -10
  259. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +0 -350
  260. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +0 -110
  261. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.ts +0 -1
  262. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/InstanceRequiredDialog.tsx +0 -106
  263. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/LookupConnectionDialog.test.tsx +0 -45
  264. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/LookupConnectionDialog.tsx +0 -43
  265. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeTypeBadge.tsx +0 -36
  266. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useNodeInstanceLibrary.ts +0 -41
  267. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.test.tsx +0 -47
  268. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.tsx +0 -182
  269. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.test.tsx +0 -34
  270. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.tsx +0 -16
  271. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/approver-source.test.ts +0 -25
  272. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/approver-source.ts +0 -42
  273. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/lookupConnection.test.ts +0 -208
  274. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/lookupConnection.ts +0 -246
  275. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +0 -111
  276. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +0 -127
  277. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +0 -4
  278. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +0 -282
  279. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +0 -74
@@ -2,9 +2,9 @@ import {
2
2
  applyNodeChanges,
3
3
  Background,
4
4
  ConnectionMode,
5
- Controls,
5
+ ConnectionLineType,
6
6
  MarkerType,
7
- MiniMap,
7
+ Panel,
8
8
  ReactFlow,
9
9
  ReactFlowProvider,
10
10
  useReactFlow,
@@ -14,39 +14,43 @@ import {
14
14
  type Node,
15
15
  type NodeChange,
16
16
  } from '@xyflow/react';
17
+ import { RedoOutlined, UndoOutlined } from '@ant-design/icons';
18
+ import { Alert, Button, Spin, Tooltip } from 'antd';
17
19
  import '@xyflow/react/dist/style.css';
18
20
  import React, {
19
21
  useCallback,
22
+ useEffect,
20
23
  useLayoutEffect,
21
24
  useMemo,
22
25
  useRef,
23
26
  useState,
24
27
  } from 'react';
25
28
  import { useTranslation } from 'react-i18next';
26
- import type {
27
- WorkflowDSL,
28
- WorkflowNodeInstance,
29
- WorkflowNodeType,
30
- } from '../types';
29
+ import type { WorkflowDSL, WorkflowNodeType } from '../types';
31
30
  import {
32
- appendLookupPipelineEdge,
33
- createLookupCall,
34
- replaceLookupCall,
35
- resolveLookupCall,
36
- resolveLookupPipelineConnection,
37
- type ResolvedLookupCall,
38
- } from '../utils/lookupConnection';
31
+ appendForEachPipelineEdge,
32
+ createForEachCall,
33
+ isForEachReservedConnection,
34
+ resolveForEachCall,
35
+ resolveForEachPipelineConnection,
36
+ } from '../utils/forEachConnection';
39
37
  import { withNewNodeDefaults } from '../utils/newNodeConfig';
40
- import { removeWorkflowEdges } from '../utils/removeWorkflowEdges';
38
+ import { isValidMainFlowConnection } from '../utils/mainFlowConnection';
41
39
  import {
40
+ removeWorkflowConnections,
41
+ removeWorkflowNodes,
42
+ } from '../utils/removeWorkflowEdges';
43
+ import {
44
+ normalizeCanvasMainHandles,
45
+ resolveCanvasEdgeHandles,
42
46
  resolveLookupPorts,
43
47
  resolveRuntimePorts,
44
48
  } from '../utils/resolveLookupPorts';
45
49
  import { resolveOutputLabels, resolveOutputs } from '../utils/resolveOutputs';
46
50
  import { CustomNode } from './CustomNode';
51
+ import { CanvasZoomControls } from './CanvasZoomControls';
47
52
  import { DeletableEdge } from './DeletableEdge';
48
- import { InstanceRequiredDialog } from './InstanceRequiredDialog';
49
- import { LookupConnectionDialog } from './LookupConnectionDialog';
53
+ import type { ReferencedConfigStatus } from '../hooks/useReferencedNodeInstanceConfigs';
50
54
 
51
55
  const nodeTypes = { custom: CustomNode };
52
56
  const edgeTypes = { deletable: DeletableEdge };
@@ -59,8 +63,18 @@ interface Props {
59
63
  >;
60
64
  selectedNodeId?: string | null;
61
65
  readonly?: boolean;
66
+ fitViewOnLoad?: boolean;
62
67
  onNodeClick?: (nodeId: string) => void;
63
68
  onDslChange?: (dsl: WorkflowDSL) => void;
69
+ canUndo?: boolean;
70
+ canRedo?: boolean;
71
+ onUndo?: () => void;
72
+ onRedo?: () => void;
73
+ onNodeDragStart?: () => void;
74
+ onNodeDragStop?: () => void;
75
+ referencedConfigs?: Record<string, Record<string, any>>;
76
+ referencedConfigStatus?: ReferencedConfigStatus;
77
+ onRetryReferencedConfigs?: () => void;
64
78
  }
65
79
 
66
80
  function FlowCanvas({
@@ -68,8 +82,18 @@ function FlowCanvas({
68
82
  nodeTypeMap,
69
83
  selectedNodeId,
70
84
  readonly,
85
+ fitViewOnLoad,
71
86
  onNodeClick,
72
87
  onDslChange,
88
+ canUndo,
89
+ canRedo,
90
+ onUndo,
91
+ onRedo,
92
+ onNodeDragStart,
93
+ onNodeDragStop,
94
+ referencedConfigs = {},
95
+ referencedConfigStatus = 'ready',
96
+ onRetryReferencedConfigs,
73
97
  }: Props) {
74
98
  const { t } = useTranslation('workflow');
75
99
  const reactFlowInstance = useReactFlow();
@@ -77,39 +101,44 @@ function FlowCanvas({
77
101
  dslRef.current = dsl;
78
102
  const containerRef = useRef<HTMLDivElement>(null);
79
103
  const hasSetViewport = useRef(false);
80
- const [pendingDrop, setPendingDrop] = useState<{
81
- nodeType: WorkflowNodeType;
82
- position: { x: number; y: number };
83
- }>();
84
- const [pendingLookup, setPendingLookup] = useState<ResolvedLookupCall>();
104
+ const fitViewFrame = useRef<number>();
85
105
  const [selectedEdgeId, setSelectedEdgeId] = useState<string>();
106
+ const hasDynamicTemplatePorts = Boolean(
107
+ dsl?.nodes.some(
108
+ (node) =>
109
+ node.type === 'switch' &&
110
+ node.instanceRef &&
111
+ node.configOverride == null,
112
+ ),
113
+ );
86
114
 
87
115
  const deleteEdges = useCallback(
88
116
  (edgeId: string) => {
89
117
  const currentDsl = dslRef.current;
90
118
  if (!currentDsl || !onDslChange || readonly) return;
91
- onDslChange({
92
- ...currentDsl,
93
- edges: removeWorkflowEdges(currentDsl.edges, [edgeId]),
94
- });
119
+ onDslChange(removeWorkflowConnections(currentDsl, [edgeId]));
95
120
  setSelectedEdgeId(undefined);
96
121
  },
97
122
  [onDslChange, readonly],
98
123
  );
99
124
 
125
+ const deleteNode = useCallback(
126
+ (nodeId: string) => {
127
+ const currentDsl = dslRef.current;
128
+ if (!currentDsl || !onDslChange || readonly) return;
129
+ onDslChange(removeWorkflowNodes(currentDsl, [nodeId]));
130
+ onNodeClick?.('');
131
+ },
132
+ [onDslChange, onNodeClick, readonly],
133
+ );
134
+
100
135
  const addDroppedNode = useCallback(
101
- (
102
- nodeType: WorkflowNodeType,
103
- position: { x: number; y: number },
104
- instance?: WorkflowNodeInstance,
105
- ) => {
136
+ (nodeType: WorkflowNodeType, position: { x: number; y: number }) => {
106
137
  const currentDsl = dslRef.current;
107
138
  if (!onDslChange) return;
108
- const initialConfig: Record<string, any> = instance
109
- ? { ...instance.config }
110
- : {};
139
+ const initialConfig: Record<string, any> = {};
111
140
  const schema = nodeType.configSchema as any;
112
- if (!instance && schema?.properties) {
141
+ if (schema?.properties) {
113
142
  for (const [key, prop] of Object.entries<any>(schema.properties)) {
114
143
  if (prop.default !== undefined) initialConfig[key] = prop.default;
115
144
  else if (prop.type === 'string') initialConfig[key] = '';
@@ -123,25 +152,20 @@ function FlowCanvas({
123
152
  const newNode = {
124
153
  id: crypto.randomUUID(),
125
154
  type: nodeType.type,
126
- label: instance?.name ?? nodeType.label,
127
- position,
128
- config: instance
129
- ? initialConfig
130
- : withNewNodeDefaults(nodeType.type, initialConfig),
131
- ...(instance && {
132
- instanceRef: {
133
- instanceId: instance.id,
134
- instanceCode: instance.code,
135
- },
155
+ label: t(`nodeTypes.${nodeType.type}`, {
156
+ defaultValue: nodeType.label,
136
157
  }),
158
+ position,
159
+ config: withNewNodeDefaults(nodeType.type, initialConfig),
137
160
  };
138
161
  onDslChange(
139
162
  currentDsl
140
163
  ? { ...currentDsl, nodes: [...currentDsl.nodes, newNode] }
141
164
  : { nodes: [newNode], edges: [] },
142
165
  );
166
+ onNodeClick?.(newNode.id);
143
167
  },
144
- [onDslChange],
168
+ [onDslChange, onNodeClick, t],
145
169
  );
146
170
 
147
171
  const { nodes, edges } = useMemo(() => {
@@ -149,7 +173,25 @@ function FlowCanvas({
149
173
 
150
174
  const rfNodes: Node[] = dsl.nodes.map((n) => {
151
175
  const category = nodeTypeMap?.[n.type]?.category || 'ACTION';
152
- const lookupPorts = resolveLookupPorts(n);
176
+ const referencedConfig =
177
+ !readonly && n.instanceRef
178
+ ? referencedConfigs[n.instanceRef.instanceId]
179
+ : undefined;
180
+ const effectiveNodeConfig = n.instanceRef
181
+ ? (n.configOverride ?? referencedConfig ?? n.config)
182
+ : n.config;
183
+ const effectiveNode =
184
+ effectiveNodeConfig === n.config
185
+ ? n
186
+ : { ...n, config: effectiveNodeConfig };
187
+ const configUnavailable = Boolean(
188
+ !readonly &&
189
+ (n.type === 'switch' || n.type === 'parallel') &&
190
+ n.instanceRef &&
191
+ n.configOverride == null &&
192
+ referencedConfigStatus !== 'ready',
193
+ );
194
+ const lookupPorts = resolveLookupPorts(effectiveNode);
153
195
  // Transpose x/y for vertical (top-to-bottom) layout
154
196
  // Scale y down to compress vertical spacing (original x-step=250 → 120)
155
197
  // Add y offset so top node isn't clipped
@@ -158,6 +200,7 @@ function FlowCanvas({
158
200
  id: n.id,
159
201
  type: 'custom',
160
202
  position,
203
+ connectable: !configUnavailable,
161
204
  selected: n.id === selectedNodeId,
162
205
  data: {
163
206
  label:
@@ -166,64 +209,123 @@ function FlowCanvas({
166
209
  : n.label,
167
210
  category,
168
211
  type: n.type,
169
- outputs: resolveOutputs(n, nodeTypeMap?.[n.type]),
170
- outputLabels: resolveOutputLabels(n),
212
+ outputs: resolveOutputs(n, nodeTypeMap?.[n.type], referencedConfig),
213
+ outputLabels: resolveOutputLabels(n, t, referencedConfig),
171
214
  lookupPorts,
172
- runtimePorts: resolveRuntimePorts(n),
215
+ runtimePorts: resolveRuntimePorts(effectiveNode),
216
+ configUnavailable,
217
+ configStatus: configUnavailable ? referencedConfigStatus : undefined,
173
218
  isSelected: n.id === selectedNodeId,
174
219
  readonly: !!readonly,
220
+ onDelete: readonly ? undefined : deleteNode,
175
221
  },
176
222
  };
177
223
  });
178
224
 
179
- const rfEdges: Edge[] = dsl.edges.map((e) => ({
180
- id: e.id,
181
- selected: e.id === selectedEdgeId,
182
- source: e.source,
183
- target: e.target,
184
- sourceHandle: e.sourceHandle,
185
- targetHandle: e.targetHandle,
186
- label:
225
+ const rfEdges: Edge[] = dsl.edges.map((e) => {
226
+ const selected = e.id === selectedEdgeId;
227
+ const canvasHandles = resolveCanvasEdgeHandles(dsl, e);
228
+ const stroke =
187
229
  e.kind === 'CALL'
188
- ? t('edge.call')
189
- : e.kind === 'RETURN'
190
- ? (e.label ?? t('edge.return'))
191
- : e.kind === 'DATA'
192
- ? `${e.sourcePath ?? 'data'} → ${e.targetHandle ?? 'input'}`
230
+ ? '#fa8c16'
231
+ : e.kind === 'RETURN' || selected
232
+ ? '#1677ff'
233
+ : '#8c8c8c';
234
+ return {
235
+ id: e.id,
236
+ selected,
237
+ source: e.source,
238
+ target: e.target,
239
+ sourceHandle: canvasHandles.sourceHandle,
240
+ targetHandle: canvasHandles.targetHandle,
241
+ label:
242
+ e.kind === 'CALL'
243
+ ? (e.label ?? t('edge.call'))
244
+ : e.kind === 'RETURN'
245
+ ? (e.label ?? t('edge.return'))
193
246
  : e.label,
194
- type: 'deletable',
195
- data: { onDelete: readonly ? undefined : deleteEdges },
196
- markerEnd:
197
- e.kind === 'CALL' || e.kind === 'RETURN'
198
- ? {
199
- type: MarkerType.ArrowClosed,
200
- color: e.kind === 'CALL' ? '#fa8c16' : '#1677ff',
201
- }
202
- : undefined,
203
- animated: e.kind !== 'DATA',
204
- style:
205
- e.kind === 'CALL'
206
- ? { stroke: '#fa8c16', strokeWidth: 2 }
207
- : e.kind === 'RETURN'
208
- ? { stroke: '#1677ff', strokeWidth: 2 }
209
- : e.kind === 'DATA'
210
- ? { stroke: '#1677ff', strokeDasharray: '6 4' }
211
- : undefined,
212
- }));
247
+ type: 'deletable',
248
+ data: { onDelete: readonly ? undefined : deleteEdges },
249
+ markerEnd: { type: MarkerType.ArrowClosed, color: stroke },
250
+ animated: selected,
251
+ style: { stroke, strokeWidth: selected ? 2.5 : 1.6 },
252
+ };
253
+ });
213
254
 
214
255
  return { nodes: rfNodes, edges: rfEdges };
215
256
  }, [
216
257
  dsl,
217
258
  nodeTypeMap,
259
+ referencedConfigs,
260
+ referencedConfigStatus,
218
261
  selectedNodeId,
219
262
  selectedEdgeId,
220
263
  readonly,
221
264
  deleteEdges,
265
+ deleteNode,
222
266
  t,
223
267
  ]);
224
268
 
225
- // Set viewport once before first paint: horizontal center + vertical top padding
269
+ const layoutKey = useMemo(
270
+ () =>
271
+ nodes
272
+ .map(
273
+ (node) =>
274
+ `${node.id}:${node.position.x.toFixed(2)}:${node.position.y.toFixed(2)}`,
275
+ )
276
+ .join('|'),
277
+ [nodes],
278
+ );
279
+ const fitViewKey = `${layoutKey}:${selectedNodeId ? 'panel' : 'canvas'}`;
280
+
281
+ const scheduleFitView = useCallback(() => {
282
+ if (!fitViewOnLoad || nodes.length === 0) return;
283
+ if (fitViewFrame.current !== undefined) {
284
+ cancelAnimationFrame(fitViewFrame.current);
285
+ }
286
+ fitViewFrame.current = requestAnimationFrame(() => {
287
+ fitViewFrame.current = requestAnimationFrame(() => {
288
+ reactFlowInstance.fitView({
289
+ padding: 0.18,
290
+ minZoom: 0.2,
291
+ maxZoom: 1,
292
+ });
293
+ fitViewFrame.current = undefined;
294
+ });
295
+ });
296
+ }, [fitViewOnLoad, nodes.length, reactFlowInstance]);
297
+
298
+ useEffect(() => {
299
+ const container = containerRef.current;
300
+ if (!fitViewOnLoad || !container) return;
301
+
302
+ let previousWidth = -1;
303
+ let previousHeight = -1;
304
+ const observer = new ResizeObserver(([entry]) => {
305
+ const { width, height } = entry.contentRect;
306
+ if (width === previousWidth && height === previousHeight) return;
307
+ previousWidth = width;
308
+ previousHeight = height;
309
+ scheduleFitView();
310
+ });
311
+ observer.observe(container);
312
+
313
+ return () => {
314
+ observer.disconnect();
315
+ if (fitViewFrame.current !== undefined) {
316
+ cancelAnimationFrame(fitViewFrame.current);
317
+ fitViewFrame.current = undefined;
318
+ }
319
+ };
320
+ }, [fitViewOnLoad, scheduleFitView]);
321
+
322
+ // The read-only viewer fits every loaded layout. The editor keeps its existing
323
+ // top-aligned viewport so adding and moving nodes does not constantly reframe it.
226
324
  useLayoutEffect(() => {
325
+ if (fitViewOnLoad) {
326
+ scheduleFitView();
327
+ return;
328
+ }
227
329
  if (!hasSetViewport.current && containerRef.current && nodes.length > 0) {
228
330
  const containerWidth = containerRef.current.clientWidth;
229
331
  let minX = Infinity,
@@ -238,7 +340,7 @@ function FlowCanvas({
238
340
  reactFlowInstance.setViewport({ x, y: 0, zoom: 1 });
239
341
  hasSetViewport.current = true;
240
342
  }
241
- }, [nodes, reactFlowInstance]);
343
+ }, [fitViewKey, fitViewOnLoad, nodes, reactFlowInstance, scheduleFitView]);
242
344
 
243
345
  const onNodesChange = useCallback(
244
346
  (changes: NodeChange[]) => {
@@ -255,14 +357,12 @@ function FlowCanvas({
255
357
  const removeChanges = changes.filter((c) => c.type === 'remove');
256
358
 
257
359
  if (removeChanges.length > 0) {
258
- const removedIds = new Set(
259
- removeChanges.map((c) => (c as any).id as string),
360
+ onDslChange(
361
+ removeWorkflowNodes(
362
+ currentDsl,
363
+ removeChanges.map((change) => (change as any).id as string),
364
+ ),
260
365
  );
261
- const newNodes = currentDsl.nodes.filter((n) => !removedIds.has(n.id));
262
- const newEdges = currentDsl.edges.filter(
263
- (e) => !removedIds.has(e.source) && !removedIds.has(e.target),
264
- );
265
- onDslChange({ nodes: newNodes, edges: newEdges });
266
366
  } else if (positionChanged) {
267
367
  const newNodes = currentDsl.nodes.map((n) => {
268
368
  const rfNode = updatedRfNodes.find((rn) => rn.id === n.id);
@@ -291,11 +391,12 @@ function FlowCanvas({
291
391
 
292
392
  const removeChanges = changes.filter((c) => c.type === 'remove');
293
393
  if (removeChanges.length > 0) {
294
- const newEdges = removeWorkflowEdges(
295
- currentDsl.edges,
296
- removeChanges.map((change) => (change as any).id as string),
394
+ onDslChange(
395
+ removeWorkflowConnections(
396
+ currentDsl,
397
+ removeChanges.map((change) => (change as any).id as string),
398
+ ),
297
399
  );
298
- onDslChange({ ...currentDsl, edges: newEdges });
299
400
  }
300
401
  },
301
402
  [onDslChange],
@@ -305,27 +406,40 @@ function FlowCanvas({
305
406
  (connection: Connection) => {
306
407
  const currentDsl = dslRef.current;
307
408
  if (!currentDsl || !onDslChange) return;
308
- const lookup = resolveLookupCall(currentDsl, connection);
309
- if (lookup) {
310
- setPendingLookup(lookup);
409
+ connection = normalizeCanvasMainHandles(connection);
410
+ if (
411
+ referencedConfigStatus !== 'ready' &&
412
+ connectionTouchesDynamicTemplate(currentDsl, connection)
413
+ )
311
414
  return;
312
- }
313
- const pipelineEdge = resolveLookupPipelineConnection(
415
+ const connectionDsl = withReferencedConfigs(
314
416
  currentDsl,
315
- connection,
417
+ referencedConfigs,
316
418
  );
317
- if (pipelineEdge) {
419
+ const forEachCall = resolveForEachCall(connectionDsl, connection);
420
+ if (forEachCall) {
318
421
  onDslChange({
319
422
  ...currentDsl,
320
- edges: appendLookupPipelineEdge(currentDsl.edges, pipelineEdge),
423
+ edges: [...currentDsl.edges, createForEachCall(forEachCall)],
321
424
  });
322
425
  return;
323
426
  }
324
- if (
325
- connection.sourceHandle?.startsWith('lookup:') ||
326
- connection.targetHandle?.startsWith('approver:')
327
- )
427
+ const forEachPipelineEdge = resolveForEachPipelineConnection(
428
+ connectionDsl,
429
+ connection,
430
+ );
431
+ if (forEachPipelineEdge) {
432
+ onDslChange({
433
+ ...currentDsl,
434
+ edges: appendForEachPipelineEdge(
435
+ currentDsl.edges,
436
+ forEachPipelineEdge,
437
+ ),
438
+ });
328
439
  return;
440
+ }
441
+ if (isForEachReservedConnection(connectionDsl, connection)) return;
442
+ if (!isValidMainFlowConnection(connectionDsl, connection)) return;
329
443
  const newEdge = {
330
444
  id: `e-${connection.source}-${connection.target}-${Date.now()}`,
331
445
  source: connection.source!,
@@ -339,22 +453,38 @@ function FlowCanvas({
339
453
  edges: [...currentDsl.edges, newEdge],
340
454
  });
341
455
  },
342
- [onDslChange],
456
+ [onDslChange, referencedConfigs, referencedConfigStatus],
343
457
  );
344
458
 
345
- const isValidConnection = useCallback((connection: Edge | Connection) => {
346
- const currentDsl = dslRef.current;
347
- if (!currentDsl) return false;
348
- if (resolveLookupCall(currentDsl, connection as Connection)) return true;
349
- if (resolveLookupPipelineConnection(currentDsl, connection as Connection))
350
- return true;
351
- const sourceHandle = connection.sourceHandle ?? '';
352
- const targetHandle = connection.targetHandle ?? '';
353
- return (
354
- !sourceHandle.startsWith('lookup:') &&
355
- !targetHandle.startsWith('approver:')
356
- );
357
- }, []);
459
+ const isValidConnection = useCallback(
460
+ (connection: Edge | Connection) => {
461
+ const currentDsl = dslRef.current;
462
+ if (!currentDsl) return false;
463
+ connection = normalizeCanvasMainHandles(connection);
464
+ if (
465
+ referencedConfigStatus !== 'ready' &&
466
+ connectionTouchesDynamicTemplate(currentDsl, connection)
467
+ )
468
+ return false;
469
+ const connectionDsl = withReferencedConfigs(
470
+ currentDsl,
471
+ referencedConfigs,
472
+ );
473
+ if (resolveForEachCall(connectionDsl, connection as Connection))
474
+ return true;
475
+ if (
476
+ resolveForEachPipelineConnection(
477
+ connectionDsl,
478
+ connection as Connection,
479
+ )
480
+ )
481
+ return true;
482
+ if (isForEachReservedConnection(connectionDsl, connection as Connection))
483
+ return false;
484
+ return isValidMainFlowConnection(connectionDsl, connection);
485
+ },
486
+ [referencedConfigs, referencedConfigStatus],
487
+ );
358
488
 
359
489
  const onDragOver = useCallback((event: React.DragEvent) => {
360
490
  event.preventDefault();
@@ -364,7 +494,7 @@ function FlowCanvas({
364
494
  const onDrop = useCallback(
365
495
  (event: React.DragEvent) => {
366
496
  event.preventDefault();
367
- if (!onDslChange) return;
497
+ if (!onDslChange || readonly) return;
368
498
 
369
499
  const data = event.dataTransfer.getData('application/workflow-node-type');
370
500
  if (!data) return;
@@ -386,36 +516,41 @@ function FlowCanvas({
386
516
  y: flowPosition.x / 1.5,
387
517
  };
388
518
 
389
- if (
390
- nodeType.instancePolicy === 'REQUIRED' ||
391
- nodeType.instancePolicy === 'OPTIONAL'
392
- ) {
393
- setPendingDrop({ nodeType, position });
394
- return;
395
- }
396
519
  addDroppedNode(nodeType, position);
397
520
  },
398
- [reactFlowInstance, onDslChange, addDroppedNode],
521
+ [reactFlowInstance, onDslChange, addDroppedNode, readonly],
399
522
  );
400
523
 
401
524
  return (
402
- <div ref={containerRef} style={{ width: '100%', height: '100%' }}>
525
+ <div
526
+ ref={containerRef}
527
+ className="workflow-canvas"
528
+ style={{ width: '100%', height: '100%' }}
529
+ >
403
530
  <ReactFlow
404
531
  nodes={nodes}
405
532
  edges={edges}
533
+ fitView={fitViewOnLoad}
534
+ fitViewOptions={{ padding: 0.18, minZoom: 0.2, maxZoom: 1 }}
535
+ minZoom={0.2}
536
+ maxZoom={2}
406
537
  nodeTypes={nodeTypes}
407
538
  edgeTypes={edgeTypes}
408
- onNodesChange={onNodesChange}
409
- onEdgesChange={onEdgesChange}
410
- onConnect={onConnect}
539
+ onNodesChange={readonly ? undefined : onNodesChange}
540
+ onEdgesChange={readonly ? undefined : onEdgesChange}
541
+ onConnect={readonly ? undefined : onConnect}
411
542
  isValidConnection={isValidConnection}
412
- onDragOver={onDragOver}
413
- onDrop={onDrop}
414
- nodesDraggable={true}
415
- nodesConnectable={true}
543
+ onDragOver={readonly ? undefined : onDragOver}
544
+ onDrop={readonly ? undefined : onDrop}
545
+ onNodeDragStart={readonly ? undefined : onNodeDragStart}
546
+ onNodeDragStop={readonly ? undefined : onNodeDragStop}
547
+ nodesDraggable={!readonly}
548
+ nodesConnectable={!readonly}
416
549
  elementsSelectable={true}
417
- connectionMode={ConnectionMode.Loose}
418
- deleteKeyCode={['Backspace', 'Delete']}
550
+ connectionMode={ConnectionMode.Strict}
551
+ connectionLineType={ConnectionLineType.Bezier}
552
+ connectionLineStyle={{ stroke: '#1677ff', strokeWidth: 2 }}
553
+ deleteKeyCode={readonly ? null : ['Backspace', 'Delete']}
419
554
  panOnScroll={true}
420
555
  zoomOnScroll={false}
421
556
  zoomOnPinch={false}
@@ -433,68 +568,69 @@ function FlowCanvas({
433
568
  onNodeClick?.('');
434
569
  }}
435
570
  >
436
- <Background />
437
- <Controls showInteractive={false} />
438
- <MiniMap
439
- nodeColor={(node) => {
440
- const category = (node.data as any)?.category || 'ACTION';
441
- const colors: Record<string, string> = {
442
- TRIGGER: '#91caff',
443
- ACTION: '#b7eb8f',
444
- CONDITION: '#ffd591',
445
- FLOW_CONTROL: '#d3adf7',
446
- APPROVAL: '#ffa39e',
447
- SUB_WORKFLOW: '#adc6ff',
448
- };
449
- return colors[category] || '#b7eb8f';
450
- }}
451
- nodeStrokeWidth={3}
452
- maskColor="rgba(240, 240, 240, 0.6)"
453
- zoomable
454
- pannable
571
+ {hasDynamicTemplatePorts && referencedConfigStatus === 'loading' && (
572
+ <Panel
573
+ position="top-right"
574
+ className="workflow-canvas__config-state nodrag nopan"
575
+ >
576
+ <Spin size="small" />
577
+ <span>{t('editor.templateConfigLoading')}</span>
578
+ </Panel>
579
+ )}
580
+ {hasDynamicTemplatePorts && referencedConfigStatus === 'error' && (
581
+ <Panel
582
+ position="top-right"
583
+ className="workflow-canvas__config-alert nodrag nopan"
584
+ >
585
+ <Alert
586
+ type="error"
587
+ showIcon
588
+ message={t('editor.templateConfigLoadFailed')}
589
+ description={t('editor.templateConfigLoadFailedHint')}
590
+ action={
591
+ onRetryReferencedConfigs ? (
592
+ <Button size="small" onClick={onRetryReferencedConfigs}>
593
+ {t('common.retry')}
594
+ </Button>
595
+ ) : undefined
596
+ }
597
+ />
598
+ </Panel>
599
+ )}
600
+ {!readonly && (
601
+ <Panel
602
+ position="top-left"
603
+ className="workflow-canvas__history-controls nodrag nopan"
604
+ >
605
+ <Tooltip title={t('editor.undo')}>
606
+ <Button
607
+ type="text"
608
+ size="small"
609
+ icon={<UndoOutlined />}
610
+ disabled={!canUndo}
611
+ onClick={onUndo}
612
+ aria-label={t('editor.undo')}
613
+ />
614
+ </Tooltip>
615
+ <Tooltip title={t('editor.redo')}>
616
+ <Button
617
+ type="text"
618
+ size="small"
619
+ icon={<RedoOutlined />}
620
+ disabled={!canRedo}
621
+ onClick={onRedo}
622
+ aria-label={t('editor.redo')}
623
+ />
624
+ </Tooltip>
625
+ </Panel>
626
+ )}
627
+ <Background
628
+ gap={22}
629
+ size={1}
630
+ color="var(--ant-color-border-secondary)"
455
631
  />
632
+ <CanvasZoomControls />
456
633
  </ReactFlow>
457
- <InstanceRequiredDialog
458
- open={Boolean(pendingDrop)}
459
- nodeType={pendingDrop?.nodeType}
460
- allowInline={pendingDrop?.nodeType.instancePolicy === 'OPTIONAL'}
461
- onCancel={() => setPendingDrop(undefined)}
462
- onInline={() => {
463
- if (pendingDrop)
464
- addDroppedNode(pendingDrop.nodeType, pendingDrop.position);
465
- setPendingDrop(undefined);
466
- }}
467
- onSelect={(instance) => {
468
- if (pendingDrop)
469
- addDroppedNode(
470
- pendingDrop.nodeType,
471
- pendingDrop.position,
472
- instance,
473
- );
474
- setPendingDrop(undefined);
475
- }}
476
- />
477
- <LookupConnectionDialog
478
- open={Boolean(pendingLookup)}
479
- apPortLabel={pendingLookup?.apPortLabel}
480
- httpNodeLabel={pendingLookup?.httpNode.label}
481
- onCancel={() => setPendingLookup(undefined)}
482
- onConfirm={() => {
483
- const currentDsl = dslRef.current;
484
- if (pendingLookup && currentDsl && onDslChange) {
485
- const call = createLookupCall(pendingLookup);
486
- onDslChange({
487
- ...currentDsl,
488
- edges: replaceLookupCall(
489
- currentDsl.edges,
490
- pendingLookup,
491
- call.edge,
492
- ),
493
- });
494
- }
495
- setPendingLookup(undefined);
496
- }}
497
- />
498
634
  </div>
499
635
  );
500
636
  }
@@ -506,3 +642,31 @@ export function FlowRenderer(props: Props) {
506
642
  </ReactFlowProvider>
507
643
  );
508
644
  }
645
+
646
+ function connectionTouchesDynamicTemplate(
647
+ dsl: WorkflowDSL,
648
+ connection: Edge | Connection,
649
+ ): boolean {
650
+ return [connection.source, connection.target].some((nodeId) => {
651
+ const node = dsl.nodes.find((item) => item.id === nodeId);
652
+ return Boolean(
653
+ (node?.type === 'switch' || node?.type === 'parallel') &&
654
+ node.instanceRef &&
655
+ node.configOverride == null,
656
+ );
657
+ });
658
+ }
659
+
660
+ function withReferencedConfigs(
661
+ dsl: WorkflowDSL,
662
+ referencedConfigs: Record<string, Record<string, any>>,
663
+ ): WorkflowDSL {
664
+ return {
665
+ ...dsl,
666
+ nodes: dsl.nodes.map((node) => {
667
+ if (!node.instanceRef || node.configOverride != null) return node;
668
+ const config = referencedConfigs[node.instanceRef.instanceId];
669
+ return config ? { ...node, config } : node;
670
+ }),
671
+ };
672
+ }