@rytass/bpm-core-react 0.16.2 → 0.17.0

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 (68) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +54 -6
  3. package/dist/chunks/{compose-DO6n0NJi.js → compose-Crklayzy.js} +2 -2
  4. package/dist/chunks/{compose-DO6n0NJi.js.map → compose-Crklayzy.js.map} +1 -1
  5. package/dist/chunks/{compose-DUH9cQ-L.cjs → compose-DZ7RKvUp.cjs} +2 -2
  6. package/dist/chunks/{compose-DUH9cQ-L.cjs.map → compose-DZ7RKvUp.cjs.map} +1 -1
  7. package/dist/chunks/{delegations-BLzYnOae.cjs → delegations-V9HIe3_P.cjs} +2 -2
  8. package/dist/chunks/delegations-V9HIe3_P.cjs.map +1 -0
  9. package/dist/chunks/{delegations-_b4_xBit.js → delegations-xUt1tj8d.js} +2 -1
  10. package/dist/chunks/{delegations-_b4_xBit.js.map → delegations-xUt1tj8d.js.map} +1 -1
  11. package/dist/chunks/{designer-B-cfiob9.js → designer-D9eFma1W.js} +1002 -948
  12. package/dist/chunks/designer-D9eFma1W.js.map +1 -0
  13. package/dist/chunks/designer-sJGTGYOf.cjs +65 -0
  14. package/dist/chunks/designer-sJGTGYOf.cjs.map +1 -0
  15. package/dist/chunks/detail-DRCTnuKm.cjs +2 -0
  16. package/dist/chunks/detail-DRCTnuKm.cjs.map +1 -0
  17. package/dist/chunks/{detail-C6NdVijG.js → detail-DScLf42P.js} +183 -156
  18. package/dist/chunks/detail-DScLf42P.js.map +1 -0
  19. package/dist/chunks/{orgs-Bpp1U60k.js → orgs-CY0i1fie.js} +583 -543
  20. package/dist/chunks/orgs-CY0i1fie.js.map +1 -0
  21. package/dist/chunks/orgs-Dr0FFoZo.cjs +2 -0
  22. package/dist/chunks/orgs-Dr0FFoZo.cjs.map +1 -0
  23. package/dist/chunks/users-BCyePbwB.js +422 -0
  24. package/dist/chunks/users-BCyePbwB.js.map +1 -0
  25. package/dist/chunks/users-DVBJluFR.cjs +2 -0
  26. package/dist/chunks/users-DVBJluFR.cjs.map +1 -0
  27. package/dist/pages/admin/delegations/index.cjs +1 -1
  28. package/dist/pages/admin/delegations/index.js +1 -1
  29. package/dist/pages/admin/orgs/index.cjs +1 -1
  30. package/dist/pages/admin/orgs/index.js +1 -1
  31. package/dist/pages/admin/users/index.cjs +1 -1
  32. package/dist/pages/admin/users/index.js +1 -1
  33. package/dist/pages/instances/detail/index.cjs +1 -1
  34. package/dist/pages/instances/detail/index.js +1 -1
  35. package/dist/pages/templates/compose/index.cjs +1 -1
  36. package/dist/pages/templates/compose/index.js +1 -1
  37. package/dist/pages/templates/designer/index.cjs +1 -1
  38. package/dist/pages/templates/designer/index.js +1 -1
  39. package/dist/views/admin/delegations/index.cjs +1 -1
  40. package/dist/views/admin/delegations/index.js +1 -1
  41. package/dist/views/admin/index.cjs +1 -1
  42. package/dist/views/admin/index.js +3 -3
  43. package/dist/views/admin/orgs/index.cjs +1 -1
  44. package/dist/views/admin/orgs/index.js +1 -1
  45. package/dist/views/admin/users/MemberTaskReassignModal.d.ts +13 -0
  46. package/dist/views/admin/users/index.cjs +1 -1
  47. package/dist/views/admin/users/index.js +1 -1
  48. package/dist/views/instances/detail/index.cjs +1 -1
  49. package/dist/views/instances/detail/index.js +1 -1
  50. package/dist/views/templates/compose/index.cjs +1 -1
  51. package/dist/views/templates/compose/index.js +1 -1
  52. package/dist/views/templates/designer/index.cjs +1 -1
  53. package/dist/views/templates/designer/index.js +1 -1
  54. package/package.json +3 -3
  55. package/dist/chunks/delegations-BLzYnOae.cjs.map +0 -1
  56. package/dist/chunks/designer-2YvjP_GU.cjs +0 -65
  57. package/dist/chunks/designer-2YvjP_GU.cjs.map +0 -1
  58. package/dist/chunks/designer-B-cfiob9.js.map +0 -1
  59. package/dist/chunks/detail-C6NdVijG.js.map +0 -1
  60. package/dist/chunks/detail-DKobK4Cg.cjs +0 -2
  61. package/dist/chunks/detail-DKobK4Cg.cjs.map +0 -1
  62. package/dist/chunks/orgs-Bpp1U60k.js.map +0 -1
  63. package/dist/chunks/orgs-ywaE1_02.cjs +0 -2
  64. package/dist/chunks/orgs-ywaE1_02.cjs.map +0 -1
  65. package/dist/chunks/users-BSVo_eNe.js +0 -215
  66. package/dist/chunks/users-BSVo_eNe.js.map +0 -1
  67. package/dist/chunks/users-DFSBTDMy.cjs +0 -2
  68. package/dist/chunks/users-DFSBTDMy.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,51 @@
1
+ ## 0.17.0 (2026-10-15)
2
+
3
+ ### 🚀 Features
4
+
5
+ - ⚠️ **workflow-engine:** end SLA-terminated instances as EXPIRED ([7dcca4e](https://github.com/Rytass/BPMCore/commit/7dcca4e))
6
+ - **template:** allow lastDecision in edge conditions ([e8b4788](https://github.com/Rytass/BPMCore/commit/e8b4788))
7
+ - **react:** add member task reassignment modal to admin users ([f12e9f8](https://github.com/Rytass/BPMCore/commit/f12e9f8))
8
+ - **workflow-engine:** add administrator in-place task reassignment ([02ce920](https://github.com/Rytass/BPMCore/commit/02ce920))
9
+ - **template-designer:** let the fallback mode pick a position ([257a361](https://github.com/Rytass/BPMCore/commit/257a361))
10
+ - **views:** ask for a successor unit before retiring an org unit ([b79cd5c](https://github.com/Rytass/BPMCore/commit/b79cd5c))
11
+ - ⚠️ **organization:** retire org units into a successor unit ([514e0b2](https://github.com/Rytass/BPMCore/commit/514e0b2))
12
+
13
+ ### 🩹 Fixes
14
+
15
+ - **migrations:** check pg_trgm with the other required extensions ([30a1e58](https://github.com/Rytass/BPMCore/commit/30a1e58))
16
+ - **template:** check CEL roots per call site on publish ([868d236](https://github.com/Rytass/BPMCore/commit/868d236))
17
+ - **instance-detail:** show how a closed instance ended ([a110e08](https://github.com/Rytass/BPMCore/commit/a110e08))
18
+ - ⚠️ **delegation:** order rules by priority, higher first ([96cca55](https://github.com/Rytass/BPMCore/commit/96cca55))
19
+ - **react:** drop a late member task listing in the reassignment modal ([1a7724e](https://github.com/Rytass/BPMCore/commit/1a7724e))
20
+ - **react:** keep reassigned task titles and fit the result table ([3b90530](https://github.com/Rytass/BPMCore/commit/3b90530))
21
+ - **template-designer:** keep unknown approver fallbacks read-only ([5ea88fe](https://github.com/Rytass/BPMCore/commit/5ea88fe))
22
+
23
+ ### ⚠️ Breaking Changes
24
+
25
+ - **workflow-engine:** end SLA-terminated instances as EXPIRED ([7dcca4e](https://github.com/Rytass/BPMCore/commit/7dcca4e))
26
+ an instance ended by SLA `TERMINATE_INSTANCE` is now
27
+ `EXPIRED` instead of `CANCELLED`, and its activity log is
28
+ `INSTANCE_EXPIRED` with a null actor instead of `INSTANCE_CANCELLED` in
29
+ the initiator's name. Instances terminated before this change stay
30
+ CANCELLED. A host implementing `BPMWorkflowEngineService` itself must add
31
+ `expireApprovalInstance`.
32
+ - **delegation:** order rules by priority, higher first ([96cca55](https://github.com/Rytass/BPMCore/commit/96cca55))
33
+ when several active delegation rules of one principal
34
+ match a task, the rule with the highest priority now applies instead of
35
+ the oldest. No data migration is needed: priority had no effect before,
36
+ but principals with overlapping rules may now be delegated differently,
37
+ so review their priorities.
38
+ - **organization:** retire org units into a successor unit ([514e0b2](https://github.com/Rytass/BPMCore/commit/514e0b2))
39
+ deleteOrgUnit now also refuses a unit that has no open
40
+ memberships but still has an open ORG_UNIT-scoped manager rule; it used to
41
+ retire it and leave the rule silently dormant. Pass transferToOrgUnitId (or
42
+ end the rule first) to retire such a unit. The refusal message keeps its
43
+ leading "Org unit with memberships cannot be deleted" sentence.
44
+
45
+ ### ❤️ Thank You
46
+
47
+ - Chia Yu Pai @fantasywind
48
+
1
49
  ## 0.16.2 (2026-10-14)
2
50
 
3
51
  ### 🚀 Features
package/README.md CHANGED
@@ -17,13 +17,23 @@ network query.
17
17
  The controlled `FormBuilderView` loads only the host-registered DataSource
18
18
  Catalog. It filters sources by control capability, supports typed field and
19
19
  constant parameter bindings, preserves bindings when a field key is renamed,
20
- and asks for confirmation before source/mode changes or removing a field used
21
- by another dynamic field. The editor can send the complete schema to the
20
+ and asks for confirmation before switching the selection mode, replacing an
21
+ already-configured DataSource, or removing a field used by another dynamic
22
+ field. Picking a source applies at once; switching away from a configured
23
+ source drops its bindings. The editor can send the complete schema to the
22
24
  server-side lint contract before publishing.
23
25
 
24
26
  ## Status
25
27
 
26
- `0.4.0` (breaking) — drops the bundled navigation shell. BPM views no longer wrap themselves in an `<AppLayout>` / Mezzanine `<Navigation>`; the host owns the layout chrome and mounts BPM views inside its own sidebar / top bar. New host-facing widgets ship in the root barrel: `useBPMMember`, `useBPMLogout`, `<BPMNotificationBellButton />`. See `CHANGELOG.md` for the migration walkthrough, and `docs/integration-guide.md` for a host integration recipe.
28
+ The current version is in `package.json` and `CHANGELOG.md` (the packages
29
+ share one version number under `nx release`).
30
+
31
+ Version 0.4.0 was a breaking release that dropped the bundled navigation shell:
32
+ BPM views no longer wrap themselves in an `<AppLayout>` / Mezzanine `<Navigation>`,
33
+ and the host owns the layout chrome. The 0.4.0 entry in `CHANGELOG.md` has the
34
+ migration walkthrough. Host-facing widgets in the root barrel are `useBPMMember`,
35
+ `useBPMLogout`, and `<BPMNotificationBellButton />`. For a host integration
36
+ recipe, see `docs/integration-guide.md`.
27
37
 
28
38
  ## Install
29
39
 
@@ -31,11 +41,35 @@ server-side lint contract before publishing.
31
41
  pnpm add @rytass/bpm-core-react @rytass/bpm-core-client @rytass/bpm-core-shared @mezzanine-ui/react @mezzanine-ui/icons
32
42
  ```
33
43
 
34
- Peer requirements: React 18+, Mezzanine UI 1.1+. Next.js is required only when consuming the `pages/*` subpath; framework-agnostic consumers can use `views/*` directly with their own router adapter.
44
+ Required peers: `react` / `react-dom` 18+, `@mezzanine-ui/react`, `@mezzanine-ui/core`
45
+ and `@mezzanine-ui/icons` `>=1.0.0` (this workspace develops against Mezzanine
46
+ 1.5.1, pinned in the root `package.json`), plus `@rytass/bpm-core-client` and
47
+ `@rytass/bpm-core-shared` at the same version. Every other peer is declared
48
+ optional in `package.json` → `peerDependenciesMeta` and is needed only by the
49
+ feature that imports it:
50
+
51
+ - `next` (>=15) — the `pages/*` and `next/*` subpaths; framework-agnostic
52
+ consumers can use `views/*` directly with their own router adapter.
53
+ - `@xyflow/react`, `dagre` — the flow designer and flow diagrams.
54
+ - `@hello-pangea/dnd` — drag-and-drop in the form builder.
55
+ - `@uiw/react-codemirror`, `@codemirror/view`, `@codemirror/lang-json` — JSON editors.
56
+ - `react-pdf` (>=10), `pdfjs-dist` (`^5.4.296 || ^6.3.289`) — PDF preview.
57
+ - `ai` (>=6), `@ai-sdk/react`, `@ai-sdk/openai` — the designer AI assistant.
58
+
59
+ `package.json` is the authoritative list.
60
+
61
+ ### Next.js + pnpm setup (conditional)
35
62
 
36
- ### Next.js + pnpm setup
63
+ `transpilePackages` is **not required by default**. The published packages ship
64
+ compiled `dist/` output with `exports` maps. This repository's `apps/client`
65
+ does not set `transpilePackages` (`apps/client/next.config.js`) and imports the
66
+ libraries through tsconfig path aliases to their source.
37
67
 
38
- If your host uses Next.js (15+) with pnpm strict mode, add the package to `transpilePackages` in `next.config.js`. Without this, Next's Turbopack cannot resolve transitive peer-dep imports such as `@rytass/bpm-core-client/workflow` from inside pnpm-isolated `node_modules/.pnpm/...` paths.
68
+ Add the setting only if your build reports an unresolved transitive import
69
+ under pnpm strict mode, for example `@rytass/bpm-core-client/workflow` imported
70
+ from inside `node_modules/.pnpm/...`. This README has **not** reproduced that
71
+ failure against the published packages; treat the snippet below as the workaround
72
+ to try in that case, not as a requirement.
39
73
 
40
74
  ```js
41
75
  /** @type {import('next').NextConfig} */
@@ -54,6 +88,20 @@ module.exports = {
54
88
  };
55
89
  ```
56
90
 
91
+ ### Designer feature flags (Next.js host env)
92
+
93
+ The designer page shim (`pages/templates/designer`) reads these server-side
94
+ environment variables. Set them in the host's `.env.local` or deployment config.
95
+
96
+ - `BPM_AI_ASSISTANT_ENABLED=true`: shows the designer AI assistant. It is hidden
97
+ by default. It also needs `OPENAI_API_KEY` (server-only); without the key the
98
+ toggle shows as a disabled placeholder.
99
+ - `BPM_TEMPLATE_DRY_RUN_ENABLED=false`: hides the 試跑流程 (dry-run) button. The
100
+ button is shown by default; only the exact value `'false'` hides it.
101
+
102
+ For direct control, `TemplateDesignerView` accepts `showAiAssistant`,
103
+ `aiAssistantAvailable`, and `showDryRun` props.
104
+
57
105
  ## Usage
58
106
 
59
107
  ### Host integration shape
@@ -3,7 +3,7 @@ import { r as e } from "./router-adapter-DftlFTOd.js";
3
3
  import { r as t } from "./routes-config-yZbESPlw.js";
4
4
  import { t as n } from "./FormRendererView-cZGOOjU5.js";
5
5
  import { t as r } from "./FormBuilderView-BYL42M0d.js";
6
- import { t as i } from "./designer-B-cfiob9.js";
6
+ import { t as i } from "./designer-D9eFma1W.js";
7
7
  import { useCallback as a, useEffect as o, useState as s } from "react";
8
8
  import { Button as c, Empty as l, FormField as u, Input as d, PageHeader as f, Section as p, SectionGroup as m, Select as h, Step as g, Stepper as _, Table as v, Tag as y, Typography as b } from "@mezzanine-ui/react";
9
9
  import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
@@ -455,4 +455,4 @@ var q = {
455
455
  //#endregion
456
456
  export { U as i, V as n, H as r, K as t };
457
457
 
458
- //# sourceMappingURL=compose-DO6n0NJi.js.map
458
+ //# sourceMappingURL=compose-Crklayzy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose-DO6n0NJi.js","names":["_Fragment","_Fragment","_Fragment","_Fragment","useRouterAdapter","useBPMRoutes","FormRenderer","FormBuilderView","TemplateDesignerView","Fragment$1","ContentHeader","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","useState","active","result","listApprovalTemplateCategoriesPage","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","FormField","FormFieldLayout","Input","onNameChange","event","name","Select","onCategoryIdChange","Typography","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","Empty","Table","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","Tag","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","useCallback","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","composeApprovalTemplateWithForm","EMPTY_WORKFLOW_DEFINITION","requestError","readErrorMessage","error","readFormSchemaLintMessage","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","PageHeader","Button","SectionGroup","Section","Stepper","Step","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n switch (node.data.approverResolver.type) {\n case 'DIRECT':\n return '指定成員';\n case 'POSITION':\n return '指定職位';\n case 'ORG_UNIT_MEMBER':\n return '單位成員';\n case 'ORG_UNIT_POSITION':\n return '單位職位';\n case 'ORG_MANAGER':\n return '主管';\n case 'ORG_MANAGER_CHAIN':\n return '主管鏈';\n case 'ORG_UNIT_MANAGER':\n return '單位主管';\n case 'DYNAMIC_FORM':\n return '依表單欄位指定';\n case 'EXPRESSION':\n return '運算式';\n default:\n return '簽核人';\n }\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { readFormSchemaLintMessage } from '@rytass/bpm-core-client/form';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(readErrorMessage(requestError));\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n\nfunction readErrorMessage(error: unknown): string {\n // Publish failures can carry stable `FORM_DATA_SOURCE_*` codes; map them to\n // readable copy and leave every other message untouched.\n return error instanceof Error\n ? readFormSchemaLintMessage(error.message)\n : '發生未知錯誤';\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"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"}
1
+ {"version":3,"file":"compose-Crklayzy.js","names":["_Fragment","_Fragment","_Fragment","_Fragment","useRouterAdapter","useBPMRoutes","FormRenderer","FormBuilderView","TemplateDesignerView","Fragment$1","ContentHeader","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","useState","active","result","listApprovalTemplateCategoriesPage","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","FormField","FormFieldLayout","Input","onNameChange","event","name","Select","onCategoryIdChange","Typography","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","Empty","Table","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","Tag","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","useCallback","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","composeApprovalTemplateWithForm","EMPTY_WORKFLOW_DEFINITION","requestError","readErrorMessage","error","readFormSchemaLintMessage","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","PageHeader","Button","SectionGroup","Section","Stepper","Step","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n switch (node.data.approverResolver.type) {\n case 'DIRECT':\n return '指定成員';\n case 'POSITION':\n return '指定職位';\n case 'ORG_UNIT_MEMBER':\n return '單位成員';\n case 'ORG_UNIT_POSITION':\n return '單位職位';\n case 'ORG_MANAGER':\n return '主管';\n case 'ORG_MANAGER_CHAIN':\n return '主管鏈';\n case 'ORG_UNIT_MANAGER':\n return '單位主管';\n case 'DYNAMIC_FORM':\n return '依表單欄位指定';\n case 'EXPRESSION':\n return '運算式';\n default:\n return '簽核人';\n }\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { readFormSchemaLintMessage } from '@rytass/bpm-core-client/form';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(readErrorMessage(requestError));\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n\nfunction readErrorMessage(error: unknown): string {\n // Publish failures can carry stable `FORM_DATA_SOURCE_*` codes; map them to\n // readable copy and leave every other message untouched.\n return error instanceof Error\n ? readFormSchemaLintMessage(error.message)\n : '發生未知錯誤';\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-C1j_vFKo.cjs"),r=require("./FormRendererView-DRFi_IH7.cjs"),i=require("./FormBuilderView-aBcA-_tt.cjs"),a=require("./designer-2YvjP_GU.cjs");let o=require("react"),s=require("@mezzanine-ui/react"),c=require("react/jsx-runtime"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@rytass/bpm-core-client/form"),f=require("@rytass/bpm-core-client/template");var p={id:`UNCATEGORIZED`,name:`未分類`},m=100;function h({categoryId:e,formSchema:t,formUiSchema:n,name:r,onCategoryIdChange:a,onFormChange:u,onNameChange:d}){let[h,_]=(0,o.useState)([]);(0,o.useEffect)(()=>{let e=!0;return(async()=>{try{let t=await(0,f.listApprovalTemplateCategoriesPage)({page:1,pageSize:m,searchText:``,status:`ACTIVE`});e&&_(t.categories)}catch{e&&_([])}})(),()=>{e=!1}},[]);let v=[p,...h.map(e=>({id:e.id,name:e.name}))],y=v.find(t=>t.id===e)??p;return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(`div`,{style:g,children:[(0,c.jsx)(s.FormField,{label:`名稱`,layout:l.FormFieldLayout.VERTICAL,name:`composeName`,children:(0,c.jsx)(s.Input,{fullWidth:!0,onChange:e=>d(e.target.value),placeholder:`例如:請款簽核`,value:r})}),(0,c.jsx)(s.FormField,{label:`分類(選填)`,layout:l.FormFieldLayout.VERTICAL,name:`composeCategory`,children:(0,c.jsx)(s.Select,{clearable:!1,fullWidth:!0,onChange:e=>a(e&&e.id!==p.id?e.id:null),options:v,placeholder:`未分類`,value:y})})]}),(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。`}),(0,c.jsx)(i.t,{onChange:u,value:{schema:t,uiSchema:n}})]})}var g={display:`grid`,gap:16,gridTemplateColumns:`repeat(auto-fit, minmax(220px, 1fr))`};function _({formSchema:e,formUiSchema:t,initiatorPolicyCel:n,name:i,publishError:a,workflowDefinition:o}){let l=o?.nodes??[],u=o?.edges??[],d=e.fields.length,f=new Map(l.map(e=>[e.id,e.data.label])),p=l.map(e=>({detail:x(e)??`—`,key:e.id,label:e.data.label,typeLabel:b(e)})),m=u.filter(e=>!!e.data.condition).map(e=>({condition:e.data.condition??``,key:e.id,source:f.get(e.source)??e.source,target:f.get(e.target)??e.target}));return(0,c.jsxs)(`div`,{style:S,children:[(0,c.jsx)(s.Typography,{component:`h2`,style:C,variant:`h2`,children:i||`(未命名)`}),(0,c.jsxs)(`div`,{style:S,children:[(0,c.jsx)(s.Typography,{variant:`h3`,children:`表單預覽`}),d>0?(0,c.jsx)(r.t,{dataSourceContext:{kind:`preview`},readonly:!0,schema:e,uiSchema:t}):(0,c.jsx)(s.Empty,{title:`尚未設計表單欄位`})]}),(0,c.jsxs)(`div`,{style:S,children:[(0,c.jsx)(s.Typography,{variant:`h3`,children:`流程概覽`}),l.length>0?(0,c.jsx)(s.Table,{columns:v,dataSource:p,fullWidth:!0}):(0,c.jsx)(s.Empty,{title:`尚未設計流程節點`}),m.length>0?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`條件分流`}),(0,c.jsx)(s.Table,{columns:y,dataSource:m,fullWidth:!0})]}):null,n?(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`caption`,children:[`發起權限:`,n]}):null]}),a?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:a}):null]})}var v=[{key:`type`,render:e=>(0,c.jsx)(s.Tag,{label:e.typeLabel,size:`sub`,type:`static`}),title:`類型`,width:130},{dataIndex:`label`,key:`label`,title:`節點`},{dataIndex:`detail`,key:`detail`,title:`簽核方式`,width:160}],y=[{dataIndex:`source`,key:`source`,title:`來源`,width:180},{dataIndex:`target`,key:`target`,title:`目標`,width:180},{dataIndex:`condition`,key:`condition`,title:`條件`}];function b(e){switch(e.type){case`startEvent`:return`開始`;case`endEvent`:return e.data.endState===`REJECTED`?`結束(駁回)`:`結束(核准)`;case`userTask`:return`簽核`;case`serviceTask`:return`服務`;case`exclusiveGateway`:return`條件閘道`;case`parallelGateway`:return`平行閘道`;default:return`節點`}}function x(e){if(e.type!==`userTask`)return null;switch(e.data.approverResolver.type){case`DIRECT`:return`指定成員`;case`POSITION`:return`指定職位`;case`ORG_UNIT_MEMBER`:return`單位成員`;case`ORG_UNIT_POSITION`:return`單位職位`;case`ORG_MANAGER`:return`主管`;case`ORG_MANAGER_CHAIN`:return`主管鏈`;case`ORG_UNIT_MANAGER`:return`單位主管`;case`DYNAMIC_FORM`:return`依表單欄位指定`;case`EXPRESSION`:return`運算式`;default:return`簽核人`}}var S={display:`grid`,gap:12},C={marginTop:`var(--mzn-spacing-padding-vertical-spacious)`};function w({aiAssistantAvailable:e=!1,formSchema:t,initiatorPolicyCel:n,onInitiatorPolicyChange:r,onWorkflowChange:i,showAiAssistant:o=!1,workflowDefinition:l}){return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。`}),(0,c.jsx)(a.t,{aiAssistantAvailable:e,embedded:!0,formSchemaOverride:t,initialInitiatorPolicyCel:n,initialWorkflowDefinition:l??void 0,onInitiatorPolicyChange:r,onWorkflowChange:i,showAiAssistant:o})]})}var T={fields:[],schemaVersion:1},E={layout:[],schemaVersion:1};function D(){let[e,t]=(0,o.useState)(0),[n,r]=(0,o.useState)(``),[i,a]=(0,o.useState)(null),[s,c]=(0,o.useState)(T),[l,u]=(0,o.useState)(E),[d,p]=(0,o.useState)(null),[m,h]=(0,o.useState)(null),[g,_]=(0,o.useState)(`idle`),[v,y]=(0,o.useState)(null),b=n.trim().length>0&&s.fields.length>0,x=(0,o.useCallback)(e=>{t(e)},[]),S=(0,o.useCallback)(()=>{t(e=>e<2?e+1:e)},[]),C=(0,o.useCallback)(()=>{t(e=>e>0?e-1:e)},[]),w=(0,o.useCallback)(e=>{c(e.schema),u(e.uiSchema)},[]),D=(0,o.useCallback)(e=>{p(e)},[]),A=(0,o.useCallback)(e=>{h(e)},[]);return{canLeaveBasics:b,categoryId:i,currentStep:e,formSchema:s,formUiSchema:l,goBack:C,goNext:S,goToStep:x,initiatorPolicyCel:m,name:n,publish:(0,o.useCallback)(async()=>{_(`submitting`),y(null);try{let e=await(0,f.composeApprovalTemplateWithForm)({category:null,categoryId:i,formDefinitionId:null,formDescription:null,formName:n,initiatorPolicyCel:m,notificationConfig:null,publish:!0,schema:s,slaDefaults:null,templateDescription:null,templateId:null,templateName:n,uiSchema:l,workflowDefinition:d??O});return _(`success`),e}catch(e){return y(k(e)),_(`error`),null}},[i,s,l,m,n,d]),publishError:v,publishPhase:g,setCategoryId:a,setFormValue:w,setInitiatorPolicyCel:A,setName:r,setWorkflowDefinition:D,workflowDefinition:d}}var O={edges:[],meta:{schemaVersion:1},nodes:[{data:{label:`開始`},id:`start`,position:{x:80,y:160},type:`startEvent`},{data:{endState:`APPROVED`,label:`完成`,triggerMode:`AND`},id:`end`,position:{x:560,y:160},type:`endEvent`}]};function k(e){return e instanceof Error?(0,d.readFormSchemaLintMessage)(e.message):`發生未知錯誤`}function A({aiAssistantAvailable:e=!1,showAiAssistant:r=!1}={}){let i=t.r(),a=n.r(),o=D(),l=o.publishPhase===`submitting`;async function d(){let e=await o.publish();e&&i.push(a.templateDesigner(e.templateId))}return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.PageHeader,{children:(0,c.jsx)(u.default,{description:`一次完成表單與流程設計,發佈後即可直接發起。`,title:`建立模板(表單 + 流程)`,children:(0,c.jsx)(s.Button,{disabled:l,onClick:()=>i.push(a.templates()),variant:`base-secondary`,children:`返回模板列表`})})}),(0,c.jsx)(s.SectionGroup,{children:(0,c.jsxs)(s.Section,{children:[(0,c.jsxs)(s.Stepper,{currentStep:o.currentStep,children:[(0,c.jsx)(s.Step,{description:`設計欄位與版面`,title:`表單設計`}),(0,c.jsx)(s.Step,{description:`設計簽核節點與條件`,title:`流程設計`}),(0,c.jsx)(s.Step,{description:`確認後發佈`,title:`檢視並發佈`})]}),o.currentStep===0?(0,c.jsx)(h,{categoryId:o.categoryId,formSchema:o.formSchema,formUiSchema:o.formUiSchema,name:o.name,onCategoryIdChange:o.setCategoryId,onFormChange:o.setFormValue,onNameChange:o.setName}):null,o.currentStep===1?(0,c.jsx)(w,{aiAssistantAvailable:e,formSchema:o.formSchema,initiatorPolicyCel:o.initiatorPolicyCel,onInitiatorPolicyChange:o.setInitiatorPolicyCel,onWorkflowChange:o.setWorkflowDefinition,showAiAssistant:r,workflowDefinition:o.workflowDefinition}):null,o.currentStep===2?(0,c.jsx)(_,{formSchema:o.formSchema,formUiSchema:o.formUiSchema,initiatorPolicyCel:o.initiatorPolicyCel,name:o.name,publishError:o.publishError,workflowDefinition:o.workflowDefinition}):null,(0,c.jsxs)(`div`,{style:j,children:[o.currentStep===0&&!o.canLeaveBasics?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`請填寫模板名稱、表單名稱,並至少新增一個表單欄位。`}):(0,c.jsx)(`span`,{}),(0,c.jsxs)(`div`,{style:M,children:[(0,c.jsx)(s.Button,{disabled:o.currentStep===0||l,onClick:o.goBack,variant:`base-secondary`,children:`上一步`}),o.currentStep<2?(0,c.jsx)(s.Button,{disabled:o.currentStep===0&&!o.canLeaveBasics,onClick:o.goNext,variant:`base-primary`,children:`下一步`}):(0,c.jsx)(s.Button,{disabled:l,loading:l,onClick:()=>{d()},variant:`base-primary`,children:`發佈`})]})]})]})})]})}var j={alignItems:`center`,display:`flex`,marginTop:`var(--mzn-spacing-padding-vertical-spacious)`,justifyContent:`space-between`,gap:16},M={display:`flex`,gap:8};Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return A}});
2
- //# sourceMappingURL=compose-DUH9cQ-L.cjs.map
1
+ "use client";const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-C1j_vFKo.cjs"),r=require("./FormRendererView-DRFi_IH7.cjs"),i=require("./FormBuilderView-aBcA-_tt.cjs"),a=require("./designer-sJGTGYOf.cjs");let o=require("react"),s=require("@mezzanine-ui/react"),c=require("react/jsx-runtime"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@rytass/bpm-core-client/form"),f=require("@rytass/bpm-core-client/template");var p={id:`UNCATEGORIZED`,name:`未分類`},m=100;function h({categoryId:e,formSchema:t,formUiSchema:n,name:r,onCategoryIdChange:a,onFormChange:u,onNameChange:d}){let[h,_]=(0,o.useState)([]);(0,o.useEffect)(()=>{let e=!0;return(async()=>{try{let t=await(0,f.listApprovalTemplateCategoriesPage)({page:1,pageSize:m,searchText:``,status:`ACTIVE`});e&&_(t.categories)}catch{e&&_([])}})(),()=>{e=!1}},[]);let v=[p,...h.map(e=>({id:e.id,name:e.name}))],y=v.find(t=>t.id===e)??p;return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(`div`,{style:g,children:[(0,c.jsx)(s.FormField,{label:`名稱`,layout:l.FormFieldLayout.VERTICAL,name:`composeName`,children:(0,c.jsx)(s.Input,{fullWidth:!0,onChange:e=>d(e.target.value),placeholder:`例如:請款簽核`,value:r})}),(0,c.jsx)(s.FormField,{label:`分類(選填)`,layout:l.FormFieldLayout.VERTICAL,name:`composeCategory`,children:(0,c.jsx)(s.Select,{clearable:!1,fullWidth:!0,onChange:e=>a(e&&e.id!==p.id?e.id:null),options:v,placeholder:`未分類`,value:y})})]}),(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。`}),(0,c.jsx)(i.t,{onChange:u,value:{schema:t,uiSchema:n}})]})}var g={display:`grid`,gap:16,gridTemplateColumns:`repeat(auto-fit, minmax(220px, 1fr))`};function _({formSchema:e,formUiSchema:t,initiatorPolicyCel:n,name:i,publishError:a,workflowDefinition:o}){let l=o?.nodes??[],u=o?.edges??[],d=e.fields.length,f=new Map(l.map(e=>[e.id,e.data.label])),p=l.map(e=>({detail:x(e)??`—`,key:e.id,label:e.data.label,typeLabel:b(e)})),m=u.filter(e=>!!e.data.condition).map(e=>({condition:e.data.condition??``,key:e.id,source:f.get(e.source)??e.source,target:f.get(e.target)??e.target}));return(0,c.jsxs)(`div`,{style:S,children:[(0,c.jsx)(s.Typography,{component:`h2`,style:C,variant:`h2`,children:i||`(未命名)`}),(0,c.jsxs)(`div`,{style:S,children:[(0,c.jsx)(s.Typography,{variant:`h3`,children:`表單預覽`}),d>0?(0,c.jsx)(r.t,{dataSourceContext:{kind:`preview`},readonly:!0,schema:e,uiSchema:t}):(0,c.jsx)(s.Empty,{title:`尚未設計表單欄位`})]}),(0,c.jsxs)(`div`,{style:S,children:[(0,c.jsx)(s.Typography,{variant:`h3`,children:`流程概覽`}),l.length>0?(0,c.jsx)(s.Table,{columns:v,dataSource:p,fullWidth:!0}):(0,c.jsx)(s.Empty,{title:`尚未設計流程節點`}),m.length>0?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`條件分流`}),(0,c.jsx)(s.Table,{columns:y,dataSource:m,fullWidth:!0})]}):null,n?(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`caption`,children:[`發起權限:`,n]}):null]}),a?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:a}):null]})}var v=[{key:`type`,render:e=>(0,c.jsx)(s.Tag,{label:e.typeLabel,size:`sub`,type:`static`}),title:`類型`,width:130},{dataIndex:`label`,key:`label`,title:`節點`},{dataIndex:`detail`,key:`detail`,title:`簽核方式`,width:160}],y=[{dataIndex:`source`,key:`source`,title:`來源`,width:180},{dataIndex:`target`,key:`target`,title:`目標`,width:180},{dataIndex:`condition`,key:`condition`,title:`條件`}];function b(e){switch(e.type){case`startEvent`:return`開始`;case`endEvent`:return e.data.endState===`REJECTED`?`結束(駁回)`:`結束(核准)`;case`userTask`:return`簽核`;case`serviceTask`:return`服務`;case`exclusiveGateway`:return`條件閘道`;case`parallelGateway`:return`平行閘道`;default:return`節點`}}function x(e){if(e.type!==`userTask`)return null;switch(e.data.approverResolver.type){case`DIRECT`:return`指定成員`;case`POSITION`:return`指定職位`;case`ORG_UNIT_MEMBER`:return`單位成員`;case`ORG_UNIT_POSITION`:return`單位職位`;case`ORG_MANAGER`:return`主管`;case`ORG_MANAGER_CHAIN`:return`主管鏈`;case`ORG_UNIT_MANAGER`:return`單位主管`;case`DYNAMIC_FORM`:return`依表單欄位指定`;case`EXPRESSION`:return`運算式`;default:return`簽核人`}}var S={display:`grid`,gap:12},C={marginTop:`var(--mzn-spacing-padding-vertical-spacious)`};function w({aiAssistantAvailable:e=!1,formSchema:t,initiatorPolicyCel:n,onInitiatorPolicyChange:r,onWorkflowChange:i,showAiAssistant:o=!1,workflowDefinition:l}){return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。`}),(0,c.jsx)(a.t,{aiAssistantAvailable:e,embedded:!0,formSchemaOverride:t,initialInitiatorPolicyCel:n,initialWorkflowDefinition:l??void 0,onInitiatorPolicyChange:r,onWorkflowChange:i,showAiAssistant:o})]})}var T={fields:[],schemaVersion:1},E={layout:[],schemaVersion:1};function D(){let[e,t]=(0,o.useState)(0),[n,r]=(0,o.useState)(``),[i,a]=(0,o.useState)(null),[s,c]=(0,o.useState)(T),[l,u]=(0,o.useState)(E),[d,p]=(0,o.useState)(null),[m,h]=(0,o.useState)(null),[g,_]=(0,o.useState)(`idle`),[v,y]=(0,o.useState)(null),b=n.trim().length>0&&s.fields.length>0,x=(0,o.useCallback)(e=>{t(e)},[]),S=(0,o.useCallback)(()=>{t(e=>e<2?e+1:e)},[]),C=(0,o.useCallback)(()=>{t(e=>e>0?e-1:e)},[]),w=(0,o.useCallback)(e=>{c(e.schema),u(e.uiSchema)},[]),D=(0,o.useCallback)(e=>{p(e)},[]),A=(0,o.useCallback)(e=>{h(e)},[]);return{canLeaveBasics:b,categoryId:i,currentStep:e,formSchema:s,formUiSchema:l,goBack:C,goNext:S,goToStep:x,initiatorPolicyCel:m,name:n,publish:(0,o.useCallback)(async()=>{_(`submitting`),y(null);try{let e=await(0,f.composeApprovalTemplateWithForm)({category:null,categoryId:i,formDefinitionId:null,formDescription:null,formName:n,initiatorPolicyCel:m,notificationConfig:null,publish:!0,schema:s,slaDefaults:null,templateDescription:null,templateId:null,templateName:n,uiSchema:l,workflowDefinition:d??O});return _(`success`),e}catch(e){return y(k(e)),_(`error`),null}},[i,s,l,m,n,d]),publishError:v,publishPhase:g,setCategoryId:a,setFormValue:w,setInitiatorPolicyCel:A,setName:r,setWorkflowDefinition:D,workflowDefinition:d}}var O={edges:[],meta:{schemaVersion:1},nodes:[{data:{label:`開始`},id:`start`,position:{x:80,y:160},type:`startEvent`},{data:{endState:`APPROVED`,label:`完成`,triggerMode:`AND`},id:`end`,position:{x:560,y:160},type:`endEvent`}]};function k(e){return e instanceof Error?(0,d.readFormSchemaLintMessage)(e.message):`發生未知錯誤`}function A({aiAssistantAvailable:e=!1,showAiAssistant:r=!1}={}){let i=t.r(),a=n.r(),o=D(),l=o.publishPhase===`submitting`;async function d(){let e=await o.publish();e&&i.push(a.templateDesigner(e.templateId))}return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.PageHeader,{children:(0,c.jsx)(u.default,{description:`一次完成表單與流程設計,發佈後即可直接發起。`,title:`建立模板(表單 + 流程)`,children:(0,c.jsx)(s.Button,{disabled:l,onClick:()=>i.push(a.templates()),variant:`base-secondary`,children:`返回模板列表`})})}),(0,c.jsx)(s.SectionGroup,{children:(0,c.jsxs)(s.Section,{children:[(0,c.jsxs)(s.Stepper,{currentStep:o.currentStep,children:[(0,c.jsx)(s.Step,{description:`設計欄位與版面`,title:`表單設計`}),(0,c.jsx)(s.Step,{description:`設計簽核節點與條件`,title:`流程設計`}),(0,c.jsx)(s.Step,{description:`確認後發佈`,title:`檢視並發佈`})]}),o.currentStep===0?(0,c.jsx)(h,{categoryId:o.categoryId,formSchema:o.formSchema,formUiSchema:o.formUiSchema,name:o.name,onCategoryIdChange:o.setCategoryId,onFormChange:o.setFormValue,onNameChange:o.setName}):null,o.currentStep===1?(0,c.jsx)(w,{aiAssistantAvailable:e,formSchema:o.formSchema,initiatorPolicyCel:o.initiatorPolicyCel,onInitiatorPolicyChange:o.setInitiatorPolicyCel,onWorkflowChange:o.setWorkflowDefinition,showAiAssistant:r,workflowDefinition:o.workflowDefinition}):null,o.currentStep===2?(0,c.jsx)(_,{formSchema:o.formSchema,formUiSchema:o.formUiSchema,initiatorPolicyCel:o.initiatorPolicyCel,name:o.name,publishError:o.publishError,workflowDefinition:o.workflowDefinition}):null,(0,c.jsxs)(`div`,{style:j,children:[o.currentStep===0&&!o.canLeaveBasics?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`請填寫模板名稱、表單名稱,並至少新增一個表單欄位。`}):(0,c.jsx)(`span`,{}),(0,c.jsxs)(`div`,{style:M,children:[(0,c.jsx)(s.Button,{disabled:o.currentStep===0||l,onClick:o.goBack,variant:`base-secondary`,children:`上一步`}),o.currentStep<2?(0,c.jsx)(s.Button,{disabled:o.currentStep===0&&!o.canLeaveBasics,onClick:o.goNext,variant:`base-primary`,children:`下一步`}):(0,c.jsx)(s.Button,{disabled:l,loading:l,onClick:()=>{d()},variant:`base-primary`,children:`發佈`})]})]})]})})]})}var j={alignItems:`center`,display:`flex`,marginTop:`var(--mzn-spacing-padding-vertical-spacious)`,justifyContent:`space-between`,gap:16},M={display:`flex`,gap:8};Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return A}});
2
+ //# sourceMappingURL=compose-DZ7RKvUp.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose-DUH9cQ-L.cjs","names":["useState","listApprovalTemplateCategoriesPage","_Fragment","FormField","FormFieldLayout","Input","Select","Typography","FormBuilderView","Typography","FormRenderer","Empty","Table","_Fragment","Tag","_Fragment","Typography","TemplateDesignerView","useState","useCallback","composeApprovalTemplateWithForm","readFormSchemaLintMessage","useRouterAdapter","useBPMRoutes","_Fragment","PageHeader","ContentHeader","Button","SectionGroup","Section","Stepper","Step","Typography","require_rolldown_runtime","require_router_adapter","require_routes_config","require_FormRendererView","require_FormBuilderView","require_designer","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_rytass_bpm_core_client_form","_rytass_bpm_core_client_template","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","active","result","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","onNameChange","event","name","onCategoryIdChange","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","EMPTY_WORKFLOW_DEFINITION","requestError","readErrorMessage","error","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n switch (node.data.approverResolver.type) {\n case 'DIRECT':\n return '指定成員';\n case 'POSITION':\n return '指定職位';\n case 'ORG_UNIT_MEMBER':\n return '單位成員';\n case 'ORG_UNIT_POSITION':\n return '單位職位';\n case 'ORG_MANAGER':\n return '主管';\n case 'ORG_MANAGER_CHAIN':\n return '主管鏈';\n case 'ORG_UNIT_MANAGER':\n return '單位主管';\n case 'DYNAMIC_FORM':\n return '依表單欄位指定';\n case 'EXPRESSION':\n return '運算式';\n default:\n return '簽核人';\n }\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { readFormSchemaLintMessage } from '@rytass/bpm-core-client/form';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(readErrorMessage(requestError));\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n\nfunction readErrorMessage(error: unknown): string {\n // Publish failures can carry stable `FORM_DATA_SOURCE_*` codes; map them to\n // readable copy and leave every other message untouched.\n return error instanceof Error\n ? readFormSchemaLintMessage(error.message)\n : '發生未知錯誤';\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"qiBAiBA,IAAM8C,EAAoC,CACxC,GAAI,gBACJ,KAAM,KACR,EAEMC,EAAqB,IAe3B,SAAgBC,EAAgB,CAC9B,aACA,aACA,eACA,OACA,qBACA,eACA,gBACqC,CACrC,GAAM,CAACC,EAAiBC,IAAA,EAAsBlD,EAAAA,SAAAA,CAE5C,CAAC,CAAC,GAEJ,EAAAuC,EAAA,UAAA,KAA8B,CAC5B,IAAIY,EAAS,GAqBb,OAnBM,SAA2B,CAC/B,GAAI,CACF,IAAMC,EAAS,MAAA,EAAMnD,EAAAA,mCAAAA,CAAmC,CACtD,KAAM,EACN,SAAU8C,EACV,WAAY,GACZ,OAAQ,QACV,CAAC,EAEGI,GACFD,EAAmBE,EAAO,UAAU,CAExC,MAAQ,CACFD,GACFD,EAAmB,CAAC,CAAC,CAEzB,CACF,EAAA,CAAG,MAEgB,CACjB,EAAS,EACX,CACF,EAAG,CAAC,CAAC,EAEL,IAAMG,EAA+B,CACnCP,EACA,GAAGG,EAAgB,IAAK,IAAc,CACpC,GAAIK,EAAS,GACb,KAAMA,EAAS,IACjB,EAAE,CACJ,EACMC,EACJF,EAAc,KAAM,GAAWG,EAAO,KAAOC,CAAU,GACvDX,EAEF,OACE,EAAAL,EAAA,KAAA,CAAAvC,EAAAA,SAAA,CAAA,SAAA,EACE,EAAAuC,EAAA,KAAA,CAAC,MAAD,CAAK,MAAOiB,EAAZ,SAAA,EACE,EAAAjB,EAAA,IAAA,CAACtC,EAAAA,UAAD,CACE,MAAM,KACN,OAAQC,EAAAA,gBAAgB,SACxB,KAAK,cAEL,UAAA,EAAAqC,EAAA,IAAA,CAACpC,EAAAA,MAAD,CACE,UAAA,GACA,SAAW,GACTsD,EAAaC,EAAM,OAAO,KAAK,EAEjC,YAAY,UACZ,MAAOC,CACR,CAAA,CACQ,CAAA,GACX,EAAApB,EAAA,IAAA,CAACtC,EAAAA,UAAD,CACE,MAAM,SACN,OAAQC,EAAAA,gBAAgB,SACxB,KAAK,kBAEL,UAAA,EAAAqC,EAAA,IAAA,CAACnC,EAAAA,OAAD,CACE,UAAW,GACX,UAAA,GACA,SAAW,GACTwD,EACEN,GAAUA,EAAO,KAAOV,EAAqB,GACzCU,EAAO,GACP,IACN,EAEF,QAASH,EACT,YAAY,MACZ,MAAOE,CACR,CAAA,CACQ,CAAA,CACR,KACL,EAAAd,EAAA,IAAA,CAAClC,EAAAA,WAAD,CAAY,MAAM,eAAe,QAAQ,UAAU,SAAA,+BAEvC,CAAA,GACZ,EAAAkC,EAAA,IAAA,CAACjC,EAAAA,EAAD,CACE,SAAUuD,EACV,MAAO,CAAE,OAAQC,EAAY,SAAUC,CAAa,CACrD,CAAA,CACD,CAAA,CAAA,CAEN,CAEA,IAAMP,EAAoB,CACxB,QAAS,OACT,IAAK,GACL,oBAAqB,sCACvB,ECnGA,SAAgBQ,EAAkB,CAChC,aACA,eACA,qBACA,OACA,eACA,sBACuC,CACvC,IAAMC,EAAQC,GAAoB,OAAS,CAAC,EACtCC,EAAQD,GAAoB,OAAS,CAAC,EACtCE,EAAaN,EAAW,OAAO,OAC/BO,EAAgB,IAAI,IACxBJ,EAAM,IAAK,GAAS,CAACK,EAAK,GAAIA,EAAK,KAAK,KAAK,CAAU,CACzD,EACMC,EAA0BN,EAAM,IAAK,IAAU,CACnD,OAAQO,EAAeF,CAAI,GAAK,IAChC,IAAKA,EAAK,GACV,MAAOA,EAAK,KAAK,MACjB,UAAWG,EAAkBH,CAAI,CACnC,EAAE,EACII,EAA0BP,EAC7B,OAAQ,GAAS,EAAQQ,EAAK,KAAK,SAAU,CAAC,CAC9C,IAAK,IAAU,CACd,UAAWA,EAAK,KAAK,WAAa,GAClC,IAAKA,EAAK,GACV,OAAQN,EAAc,IAAIM,EAAK,MAAM,GAAKA,EAAK,OAC/C,OAAQN,EAAc,IAAIM,EAAK,MAAM,GAAKA,EAAK,MACjD,EAAE,EAEJ,OACE,EAAApC,EAAA,KAAA,CAAC,MAAD,CAAK,MAAOqC,EAAZ,SAAA,EACE,EAAArC,EAAA,IAAA,CAAChC,EAAAA,WAAD,CAAY,UAAU,KAAK,MAAOsE,EAAa,QAAQ,KACpD,SAAAlB,GAAQ,OACC,CAAA,GAEZ,EAAApB,EAAA,KAAA,CAAC,MAAD,CAAK,MAAOqC,EAAZ,SAAA,EACE,EAAArC,EAAA,IAAA,CAAChC,EAAAA,WAAD,CAAY,QAAQ,KAAK,SAAA,MAAgB,CAAA,EACxC6D,EAAa,GACZ,EAAA7B,EAAA,IAAA,CAAC/B,EAAAA,EAAD,CACE,kBAAmB,CAAE,KAAM,SAAU,EACrC,SAAA,GACA,OAAQsD,EACR,SAAUC,CACX,CAAA,GAED,EAAAxB,EAAA,IAAA,CAAC9B,EAAAA,MAAD,CAAO,MAAM,UAAY,CAAA,CAExB,KAEL,EAAA8B,EAAA,KAAA,CAAC,MAAD,CAAK,MAAOqC,EAAZ,SAAA,EACE,EAAArC,EAAA,IAAA,CAAChC,EAAAA,WAAD,CAAY,QAAQ,KAAK,SAAA,MAAgB,CAAA,EACxC0D,EAAM,OAAS,GACd,EAAA1B,EAAA,IAAA,CAAC7B,EAAAA,MAAD,CAAO,QAASoE,EAAc,WAAYP,EAAU,UAAA,EAAW,CAAA,GAE/D,EAAAhC,EAAA,IAAA,CAAC9B,EAAAA,MAAD,CAAO,MAAM,UAAY,CAAA,EAE1BiE,EAAW,OAAS,GACnB,EAAAnC,EAAA,KAAA,CAAA5B,EAAAA,SAAA,CAAA,SAAA,EACE,EAAA4B,EAAA,IAAA,CAAChC,EAAAA,WAAD,CAAY,MAAM,eAAe,QAAQ,UAAU,SAAA,MAEvC,CAAA,GACZ,EAAAgC,EAAA,IAAA,CAAC7B,EAAAA,MAAD,CAAO,QAASqE,EAAgB,WAAYL,EAAY,UAAA,EAAW,CAAA,CACnE,CAAA,CAAA,EACA,KACHM,GACC,EAAAzC,EAAA,KAAA,CAAChC,EAAAA,WAAD,CAAY,MAAM,eAAe,QAAQ,UAAzC,SAAA,CAAmD,QAC3CyE,CACI,CACV,CAAA,EAAA,IACD,IAEJC,GACC,EAAA1C,EAAA,IAAA,CAAChC,EAAAA,WAAD,CAAY,MAAM,aAAa,QAAQ,OACpC,SAAA0E,CACS,CAAA,EACV,IACD,GAET,CAEA,IAAMH,EAA2C,CAC/C,CACE,IAAK,OACL,OAAS,IACP,EAAAvC,EAAA,IAAA,CAAC3B,EAAAA,IAAD,CAAK,MAAOsE,EAAO,UAAW,KAAK,MAAM,KAAK,QAAU,CAAA,EAE1D,MAAO,KACP,MAAO,GACT,EACA,CAAE,UAAW,QAAS,IAAK,QAAS,MAAO,IAAK,EAChD,CAAE,UAAW,SAAU,IAAK,SAAU,MAAO,OAAQ,MAAO,GAAI,CAClE,EAEMH,EAA2C,CAC/C,CAAE,UAAW,SAAU,IAAK,SAAU,MAAO,KAAM,MAAO,GAAI,EAC9D,CAAE,UAAW,SAAU,IAAK,SAAU,MAAO,KAAM,MAAO,GAAI,EAC9D,CAAE,UAAW,YAAa,IAAK,YAAa,MAAO,IAAK,CAC1D,EAEA,SAASN,EAAkB,EAA4B,CACrD,OAAQH,EAAK,KAAb,CACE,IAAK,aACH,MAAO,KACT,IAAK,WACH,OAAOA,EAAK,KAAK,WAAa,WAAa,SAAW,SACxD,IAAK,WACH,MAAO,KACT,IAAK,cACH,MAAO,KACT,IAAK,mBACH,MAAO,OACT,IAAK,kBACH,MAAO,OACT,QACE,MAAO,IACX,CACF,CAEA,SAASE,EAAe,EAAmC,CACzD,GAAIF,EAAK,OAAS,WAChB,OAAO,KAGT,OAAQA,EAAK,KAAK,iBAAiB,KAAnC,CACE,IAAK,SACH,MAAO,OACT,IAAK,WACH,MAAO,OACT,IAAK,kBACH,MAAO,OACT,IAAK,oBACH,MAAO,OACT,IAAK,cACH,MAAO,KACT,IAAK,oBACH,MAAO,MACT,IAAK,mBACH,MAAO,OACT,IAAK,eACH,MAAO,UACT,IAAK,aACH,MAAO,MACT,QACE,MAAO,KACX,CACF,CAEA,IAAMM,EAA6B,CACjC,QAAS,OACT,IAAK,EACP,EAIMC,EAA6B,CACjC,UAAW,8CACb,EC3KA,SAAgBM,EAAoB,CAClC,uBAAuB,GACvB,aACA,qBACA,0BACA,mBACA,kBAAkB,GAClB,sBACyC,CACzC,OACE,EAAA5C,EAAA,KAAA,CAAA1B,EAAAA,SAAA,CAAA,SAAA,EACE,EAAA0B,EAAA,IAAA,CAACzB,EAAAA,WAAD,CAAY,MAAM,eAAe,QAAQ,UAAU,SAAA,gCAEvC,CAAA,GACZ,EAAAyB,EAAA,IAAA,CAACxB,EAAAA,EAAD,CACwB,uBACtB,SAAA,GACA,mBAAoB+C,EACpB,0BAA2BkB,EAC3B,0BAA2Bd,GAAsB,IAAA,GACxB,0BACP,mBACD,iBAClB,CAAA,CACD,CAAA,CAAA,CAEN,CCnCA,IAAakB,EAAkD,CAC7D,OAAQ,CAAC,EACT,cAAe,CACjB,EAEaC,EAA6C,CACxD,OAAQ,CAAC,EACT,cAAe,CACjB,EAyCA,SAAgBC,GAAkD,CAChE,GAAM,CAACC,EAAaC,IAAA,EAAkBxE,EAAAA,SAAAA,CAA4B,CAAC,EAC7D,CAAC2C,EAAM8B,IAAA,EAAWzE,EAAAA,SAAAA,CAAS,EAAE,EAC7B,CAACuC,EAAYmC,IAAA,EAAiB1E,EAAAA,SAAAA,CAAwB,IAAI,EAC1D,CAAC8C,EAAY6B,IAAA,EAAiB3E,EAAAA,SAAAA,CAClCoE,CACF,EACM,CAACrB,EAAc6B,IAAA,EAAmB5E,EAAAA,SAAAA,CACtCqE,CACF,EACM,CAACnB,EAAoB2B,IAAA,EACzB7E,EAAAA,SAAAA,CAAoC,IAAI,EACpC,CAACgE,EAAoBc,IAAA,EAA8B9E,EAAAA,SAAAA,CAEvD,IAAI,EACA,CAAC+E,EAAcC,IAAA,EAAmBhF,EAAAA,SAAAA,CAA8B,MAAM,EACtE,CAACiE,EAAcgB,IAAA,EAAmBjF,EAAAA,SAAAA,CAAwB,IAAI,EAE9DkF,EAAiBvC,EAAK,KAAK,CAAC,CAAC,OAAS,GAAKG,EAAW,OAAO,OAAS,EAEtEqC,GAAA,EAAWlF,EAAAA,YAAAA,CAAa,GAAkC,CAC9DuE,EAAeY,CAAI,CACrB,EAAG,CAAC,CAAC,EAECC,GAAA,EAASpF,EAAAA,YAAAA,KAAwB,CACrCuE,EAAgB,GACdY,EAAO,EAAMA,EAAO,EAA2BA,CACjD,CACF,EAAG,CAAC,CAAC,EAECE,GAAA,EAASrF,EAAAA,YAAAA,KAAwB,CACrCuE,EAAgB,GACdY,EAAO,EAAMA,EAAO,EAA2BA,CACjD,CACF,EAAG,CAAC,CAAC,EAECG,GAAA,EAAetF,EAAAA,YAAAA,CAClB,GAGW,CACV0E,EAAca,EAAK,MAAM,EACzBZ,EAAgBY,EAAK,QAAQ,CAC/B,EACA,CAAC,CACH,EAEMC,GAAA,EAAwBxF,EAAAA,YAAAA,CAC3B,GAAyC,CACxC4E,EAA2Ba,CAAU,CACvC,EACA,CAAC,CACH,EAEMC,GAAA,EAAwB1F,EAAAA,YAAAA,CAAa,GAA6B,CACtE6E,EAA2Bc,CAAG,CAChC,EAAG,CAAC,CAAC,EA6CL,MAAO,CACL,iBACA,aACA,cACA,aACA,eACA,SACA,SACA,WACA,qBACA,OACA,SAAA,EArDA3F,EAAAA,YAAAA,CAAY,SAAmE,CAC7E+E,EAAgB,YAAY,EAC5BC,EAAgB,IAAI,EAEpB,GAAI,CACF,IAAM/C,EAAS,MAAA,EAAMhC,EAAAA,gCAAAA,CAAgC,CACnD,SAAU,KACV,aACA,iBAAkB,KAClB,gBAAiB,KAEjB,SAAUyC,EACV,qBACA,mBAAoB,KACpB,QAAS,GACT,OAAQG,EACR,YAAa,KACb,oBAAqB,KACrB,WAAY,KACZ,aAAcH,EACd,SAAUI,EACV,mBAAoBG,GAAsB2C,CAC5C,CAAC,EAID,OAFAb,EAAgB,SAAS,EAElB9C,CACT,OAAS4D,EAAuB,CAI9B,OAHAb,EAAgBc,EAAiBD,CAAY,CAAC,EAC9Cd,EAAgB,OAAO,EAEhB,IACT,CACF,EAAG,CACDzC,EACAO,EACAC,EACAiB,EACArB,EACAO,CACF,CAaA,EACA,eACA,eACA,gBACA,eACA,wBACA,UACA,wBACA,oBACF,CACF,CAEA,IAAM2C,EAAgD,CACpD,MAAO,CAAC,EACR,KAAM,CAAE,cAAe,CAAE,EACzB,MAAO,CACL,CACE,KAAM,CAAE,MAAO,IAAK,EACpB,GAAI,QACJ,SAAU,CAAE,EAAG,GAAI,EAAG,GAAI,EAC1B,KAAM,YACR,EACA,CACE,KAAM,CAAE,SAAU,WAAY,MAAO,KAAM,YAAa,KAAM,EAC9D,GAAI,MACJ,SAAU,CAAE,EAAG,IAAK,EAAG,GAAI,EAC3B,KAAM,UACR,CACF,CACF,EAEA,SAASE,EAAiB,EAAwB,CAGhD,OAAOC,aAAiB,OAAA,EACpB7F,EAAAA,0BAAAA,CAA0B6F,EAAM,OAAO,EACvC,QACN,CChLA,SAAgBC,EAA0B,CACxC,uBAAuB,GACvB,kBAAkB,IACgB,CAAC,EAAiB,CACpD,IAAMC,EAAS9F,EAAAA,EAAiB,EAC1B+F,EAAS9F,EAAAA,EAAa,EACtB+F,EAAS9B,EAAyB,EAClC+B,EAAaD,EAAO,eAAiB,aAE3C,eAAeE,GAA+B,CAC5C,IAAMpE,EAAS,MAAMkE,EAAO,QAAQ,EAEhClE,GACFgE,EAAO,KAAKC,EAAO,iBAAiBjE,EAAO,UAAU,CAAC,CAE1D,CAEA,OACE,EAAAX,EAAA,KAAA,CAAAjB,EAAAA,SAAA,CAAA,SAAA,EACE,EAAAiB,EAAA,IAAA,CAAChB,EAAAA,WAAD,CAAA,UACE,EAAAgB,EAAA,IAAA,CAACf,EAAAA,QAAD,CACE,YAAY,yBACZ,MAAM,gBAEN,UAAA,EAAAe,EAAA,IAAA,CAACd,EAAAA,OAAD,CACE,SAAU4F,EACV,YAAqBH,EAAO,KAAKC,EAAO,UAAU,CAAC,EACnD,QAAQ,iBACT,SAAA,QAEO,CAAA,CACK,CAAA,CACL,CAAA,GAEZ,EAAA5E,EAAA,IAAA,CAACb,EAAAA,aAAD,CAAA,UACE,EAAAa,EAAA,KAAA,CAACZ,EAAAA,QAAD,CAAA,SAAA,EACE,EAAAY,EAAA,KAAA,CAACX,EAAAA,QAAD,CAAS,YAAawF,EAAO,YAA7B,SAAA,EACE,EAAA7E,EAAA,IAAA,CAACV,EAAAA,KAAD,CAAM,YAAY,UAAU,MAAM,MAAQ,CAAA,GAC1C,EAAAU,EAAA,IAAA,CAACV,EAAAA,KAAD,CAAM,YAAY,YAAY,MAAM,MAAQ,CAAA,GAC5C,EAAAU,EAAA,IAAA,CAACV,EAAAA,KAAD,CAAM,YAAY,QAAQ,MAAM,OAAS,CAAA,CAClC,IAERuF,EAAO,cAAgB,GACtB,EAAA7E,EAAA,IAAA,CAACO,EAAD,CACE,WAAYsE,EAAO,WACnB,WAAYA,EAAO,WACnB,aAAcA,EAAO,aACrB,KAAMA,EAAO,KACb,mBAAoBA,EAAO,cAC3B,aAAcA,EAAO,aACrB,aAAcA,EAAO,OACtB,CAAA,EACC,KAEHA,EAAO,cAAgB,GACtB,EAAA7E,EAAA,IAAA,CAAC4C,EAAD,CACwB,uBACtB,WAAYiC,EAAO,WACnB,mBAAoBA,EAAO,mBAC3B,wBAAyBA,EAAO,sBAChC,iBAAkBA,EAAO,sBACR,kBACjB,mBAAoBA,EAAO,kBAC5B,CAAA,EACC,KAEHA,EAAO,cAAgB,GACtB,EAAA7E,EAAA,IAAA,CAACyB,EAAD,CACE,WAAYoD,EAAO,WACnB,aAAcA,EAAO,aACrB,mBAAoBA,EAAO,mBAC3B,KAAMA,EAAO,KACb,aAAcA,EAAO,aACrB,mBAAoBA,EAAO,kBAC5B,CAAA,EACC,MAEJ,EAAA7E,EAAA,KAAA,CAAC,MAAD,CAAK,MAAOgF,EAAZ,SAAA,CACGH,EAAO,cAAgB,GAAK,CAACA,EAAO,gBACnC,EAAA7E,EAAA,IAAA,CAACT,EAAAA,WAAD,CAAY,MAAM,eAAe,QAAQ,UAAU,SAAA,2BAEvC,CAAA,GAEZ,EAAAS,EAAA,IAAA,CAAC,OAAD,CAAO,CAAA,GAET,EAAAA,EAAA,KAAA,CAAC,MAAD,CAAK,MAAOiF,EAAZ,SAAA,EACE,EAAAjF,EAAA,IAAA,CAACd,EAAAA,OAAD,CACE,SAAU2F,EAAO,cAAgB,GAAKC,EACtC,QAASD,EAAO,OAChB,QAAQ,iBACT,SAAA,KAEO,CAAA,EACPA,EAAO,YAAc,GACpB,EAAA7E,EAAA,IAAA,CAACd,EAAAA,OAAD,CACE,SAAU2F,EAAO,cAAgB,GAAK,CAACA,EAAO,eAC9C,QAASA,EAAO,OAChB,QAAQ,eACT,SAAA,KAEO,CAAA,GAER,EAAA7E,EAAA,IAAA,CAACd,EAAAA,OAAD,CACE,SAAU4F,EACV,QAASA,EACT,YAAqB,CACnBC,EAAmB,CACrB,EACA,QAAQ,eACT,SAAA,IAEO,CAAA,CAEP,CACF,CAAA,CAAA,GACE,CAAA,CAAA,CACG,CAAA,CACd,CAAA,CAAA,CAEN,CAEA,IAAMC,EAAe,CACnB,WAAY,SACZ,QAAS,OAET,UAAW,+CACX,eAAgB,gBAChB,IAAK,EACP,EAEMC,EAAuB,CAC3B,QAAS,OACT,IAAK,CACP"}
1
+ {"version":3,"file":"compose-DZ7RKvUp.cjs","names":["useState","listApprovalTemplateCategoriesPage","_Fragment","FormField","FormFieldLayout","Input","Select","Typography","FormBuilderView","Typography","FormRenderer","Empty","Table","_Fragment","Tag","_Fragment","Typography","TemplateDesignerView","useState","useCallback","composeApprovalTemplateWithForm","readFormSchemaLintMessage","useRouterAdapter","useBPMRoutes","_Fragment","PageHeader","ContentHeader","Button","SectionGroup","Section","Stepper","Step","Typography","require_rolldown_runtime","require_router_adapter","require_routes_config","require_FormRendererView","require_FormBuilderView","require_designer","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_rytass_bpm_core_client_form","_rytass_bpm_core_client_template","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","active","result","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","onNameChange","event","name","onCategoryIdChange","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","EMPTY_WORKFLOW_DEFINITION","requestError","readErrorMessage","error","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n switch (node.data.approverResolver.type) {\n case 'DIRECT':\n return '指定成員';\n case 'POSITION':\n return '指定職位';\n case 'ORG_UNIT_MEMBER':\n return '單位成員';\n case 'ORG_UNIT_POSITION':\n return '單位職位';\n case 'ORG_MANAGER':\n return '主管';\n case 'ORG_MANAGER_CHAIN':\n return '主管鏈';\n case 'ORG_UNIT_MANAGER':\n return '單位主管';\n case 'DYNAMIC_FORM':\n return '依表單欄位指定';\n case 'EXPRESSION':\n return '運算式';\n default:\n return '簽核人';\n }\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { readFormSchemaLintMessage } from '@rytass/bpm-core-client/form';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(readErrorMessage(requestError));\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n\nfunction readErrorMessage(error: unknown): string {\n // Publish failures can carry stable `FORM_DATA_SOURCE_*` codes; map them to\n // readable copy and leave every other message untouched.\n return error instanceof Error\n ? readFormSchemaLintMessage(error.message)\n : '發生未知錯誤';\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"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"}