@rytass/bpm-core-react 0.16.2 → 0.17.1
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.
- package/CHANGELOG.md +61 -0
- package/README.md +54 -6
- package/dist/chunks/admin-pickers-BRHk3qKq.cjs +2 -0
- package/dist/chunks/admin-pickers-BRHk3qKq.cjs.map +1 -0
- package/dist/chunks/{admin-pickers-DxhzECkD.js → admin-pickers-Djq3h-UR.js} +41 -39
- package/dist/chunks/admin-pickers-Djq3h-UR.js.map +1 -0
- package/dist/chunks/{categories-DjENouRm.cjs → categories-AxxhqjLZ.cjs} +2 -2
- package/dist/chunks/{categories-DjENouRm.cjs.map → categories-AxxhqjLZ.cjs.map} +1 -1
- package/dist/chunks/{categories-1gKxeEqw.js → categories-riC33J_j.js} +2 -2
- package/dist/chunks/{categories-1gKxeEqw.js.map → categories-riC33J_j.js.map} +1 -1
- package/dist/chunks/{compose-DUH9cQ-L.cjs → compose-B7TtrpQJ.cjs} +2 -2
- package/dist/chunks/{compose-DUH9cQ-L.cjs.map → compose-B7TtrpQJ.cjs.map} +1 -1
- package/dist/chunks/{compose-DO6n0NJi.js → compose-_pREPtfN.js} +2 -2
- package/dist/chunks/{compose-DO6n0NJi.js.map → compose-_pREPtfN.js.map} +1 -1
- package/dist/chunks/{delegations-BLzYnOae.cjs → delegations-V9HIe3_P.cjs} +2 -2
- package/dist/chunks/delegations-V9HIe3_P.cjs.map +1 -0
- package/dist/chunks/{delegations-_b4_xBit.js → delegations-xUt1tj8d.js} +2 -1
- package/dist/chunks/{delegations-_b4_xBit.js.map → delegations-xUt1tj8d.js.map} +1 -1
- package/dist/chunks/{designer-B-cfiob9.js → designer-BiywgNXs.js} +1003 -949
- package/dist/chunks/designer-BiywgNXs.js.map +1 -0
- package/dist/chunks/designer-ttAqv859.cjs +65 -0
- package/dist/chunks/designer-ttAqv859.cjs.map +1 -0
- package/dist/chunks/detail-DRCTnuKm.cjs +2 -0
- package/dist/chunks/detail-DRCTnuKm.cjs.map +1 -0
- package/dist/chunks/{detail-C6NdVijG.js → detail-DScLf42P.js} +183 -156
- package/dist/chunks/detail-DScLf42P.js.map +1 -0
- package/dist/chunks/orgs-C8usknWb.cjs +2 -0
- package/dist/chunks/orgs-C8usknWb.cjs.map +1 -0
- package/dist/chunks/{orgs-Bpp1U60k.js → orgs-Lg7tXv2u.js} +584 -544
- package/dist/chunks/orgs-Lg7tXv2u.js.map +1 -0
- package/dist/chunks/users-DRbuDYF1.js +422 -0
- package/dist/chunks/users-DRbuDYF1.js.map +1 -0
- package/dist/chunks/users-DVQicZIo.cjs +2 -0
- package/dist/chunks/users-DVQicZIo.cjs.map +1 -0
- package/dist/components/admin-pickers.d.cts +65 -0
- package/dist/components/approval-instance-list-page.d.cts +17 -0
- package/dist/components/bpm-form-field.d.cts +10 -0
- package/dist/components/bpm-notification-bell-button.d.cts +22 -0
- package/dist/components/dashboard-page.d.cts +7 -0
- package/dist/components/notification-drawer.d.cts +11 -0
- package/dist/components/org-unit-tree-draft-editor.d.cts +24 -0
- package/dist/components/org-unit-tree-draft-editor.d.ts +1 -1
- package/dist/components/pdf-preview.d.cts +12 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -15
- package/dist/index.js +1 -1
- package/dist/lib/auth-provider.d.cts +37 -0
- package/dist/lib/format-date-time.d.cts +5 -0
- package/dist/lib/format-member-label.d.cts +12 -0
- package/dist/lib/member-profile-resolution.d.cts +48 -0
- package/dist/lib/notification-drawer-provider.d.cts +27 -0
- package/dist/lib/notification-unread-provider.d.cts +25 -0
- package/dist/lib/org-tree-draft.d.cts +27 -0
- package/dist/lib/providers.d.cts +31 -0
- package/dist/lib/router-adapter.d.cts +47 -0
- package/dist/lib/routes-config.d.cts +117 -0
- package/dist/lib/task-node-label.d.cts +10 -0
- package/dist/lib/use-bpm-logout.d.cts +12 -0
- package/dist/lib/use-bpm-member.d.cts +17 -0
- package/dist/next/BPMNextProviders.d.cts +51 -0
- package/dist/next/index.d.cts +2 -0
- package/dist/next/index.d.ts +2 -2
- package/dist/next/workflow-chat-route.d.cts +17 -0
- package/dist/pages/admin/delegations/index.cjs +1 -1
- package/dist/pages/admin/delegations/index.d.cts +4 -0
- package/dist/pages/admin/delegations/index.js +1 -1
- package/dist/pages/admin/orgs/index.cjs +1 -1
- package/dist/pages/admin/orgs/index.d.cts +4 -0
- package/dist/pages/admin/orgs/index.js +1 -1
- package/dist/pages/admin/users/index.cjs +1 -1
- package/dist/pages/admin/users/index.d.cts +4 -0
- package/dist/pages/admin/users/index.js +1 -1
- package/dist/pages/admin/webhook-endpoints/index.d.cts +4 -0
- package/dist/pages/cc/index.d.cts +16 -0
- package/dist/pages/dashboard/index.d.cts +16 -0
- package/dist/pages/delegations/index.d.cts +4 -0
- package/dist/pages/inbox/index.d.cts +16 -0
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.d.cts +23 -0
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/instances/new/index.d.cts +20 -0
- package/dist/pages/login/index.d.cts +21 -0
- package/dist/pages/root/index.d.cts +18 -0
- package/dist/pages/search/index.d.cts +16 -0
- package/dist/pages/sent/index.d.cts +16 -0
- package/dist/pages/settings/notifications/index.d.cts +4 -0
- package/dist/pages/templates/categories/index.cjs +1 -1
- package/dist/pages/templates/categories/index.d.cts +4 -0
- package/dist/pages/templates/categories/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.d.cts +25 -0
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.d.cts +8 -0
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/pages/templates/index.d.cts +4 -0
- package/dist/pages/templates/versions/index.d.cts +8 -0
- package/dist/views/admin/delegations/AdminDelegationsView.d.cts +2 -0
- package/dist/views/admin/delegations/index.cjs +1 -1
- package/dist/views/admin/delegations/index.d.cts +1 -0
- package/dist/views/admin/delegations/index.d.ts +1 -1
- package/dist/views/admin/delegations/index.js +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.d.cts +4 -0
- package/dist/views/admin/index.d.ts +4 -4
- package/dist/views/admin/index.js +3 -3
- package/dist/views/admin/orgs/AdminOrgsView.d.cts +2 -0
- package/dist/views/admin/orgs/index.cjs +1 -1
- package/dist/views/admin/orgs/index.d.cts +1 -0
- package/dist/views/admin/orgs/index.d.ts +1 -1
- package/dist/views/admin/orgs/index.js +1 -1
- package/dist/views/admin/users/AdminUsersView.d.cts +2 -0
- package/dist/views/admin/users/MemberTaskReassignModal.d.cts +13 -0
- package/dist/views/admin/users/MemberTaskReassignModal.d.ts +13 -0
- package/dist/views/admin/users/index.cjs +1 -1
- package/dist/views/admin/users/index.d.cts +1 -0
- package/dist/views/admin/users/index.d.ts +1 -1
- package/dist/views/admin/users/index.js +1 -1
- package/dist/views/admin/webhook-endpoints/AdminWebhookEndpointsView.d.cts +8 -0
- package/dist/views/admin/webhook-endpoints/index.d.cts +1 -0
- package/dist/views/admin/webhook-endpoints/index.d.ts +1 -1
- package/dist/views/cc/CcView.d.cts +7 -0
- package/dist/views/cc/index.d.cts +1 -0
- package/dist/views/cc/index.d.ts +1 -1
- package/dist/views/dashboard/DashboardView.d.cts +7 -0
- package/dist/views/dashboard/index.d.cts +1 -0
- package/dist/views/dashboard/index.d.ts +1 -1
- package/dist/views/delegations/DelegationsView.d.cts +2 -0
- package/dist/views/delegations/index.d.cts +1 -0
- package/dist/views/delegations/index.d.ts +1 -1
- package/dist/views/forms/builder/FormBuilderView.d.cts +18 -0
- package/dist/views/forms/builder/index.d.cts +1 -0
- package/dist/views/forms/builder/index.d.ts +1 -1
- package/dist/views/forms/builder/json-code-editor.d.cts +11 -0
- package/dist/views/forms/renderer/FormRendererView.d.cts +24 -0
- package/dist/views/forms/renderer/FormRendererView.d.ts +1 -1
- package/dist/views/forms/renderer/form-data-source-field.d.cts +65 -0
- package/dist/views/forms/renderer/form-field-link.d.cts +16 -0
- package/dist/views/forms/renderer/index.d.cts +2 -0
- package/dist/views/forms/renderer/index.d.ts +2 -2
- package/dist/views/forms/renderer/member-field-options.d.cts +39 -0
- package/dist/views/forms/renderer/member-field.d.cts +21 -0
- package/dist/views/inbox/InboxView.d.cts +7 -0
- package/dist/views/inbox/index.d.cts +1 -0
- package/dist/views/inbox/index.d.ts +1 -1
- package/dist/views/instances/detail/InstanceDetailView.d.cts +27 -0
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.d.cts +7 -0
- package/dist/views/instances/detail/index.d.ts +7 -7
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/InstanceAttachmentsSection.d.cts +15 -0
- package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +36 -0
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +1 -1
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.cts +29 -0
- package/dist/views/instances/detail/sections/InstanceSignaturesSection.d.cts +14 -0
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +55 -0
- package/dist/views/instances/detail/sections/InstanceWebhookDeliveriesSection.d.cts +20 -0
- package/dist/views/instances/detail/sections/container-helpers.d.cts +10 -0
- package/dist/views/instances/detail/sections/container-helpers.d.ts +1 -1
- package/dist/views/instances/detail/sections/shared.d.cts +141 -0
- package/dist/views/instances/detail/submitted-by.d.cts +23 -0
- package/dist/views/instances/index.d.cts +1 -0
- package/dist/views/instances/index.d.ts +1 -1
- package/dist/views/instances/new/InstanceNewView.d.cts +15 -0
- package/dist/views/instances/new/index.d.cts +1 -0
- package/dist/views/instances/new/index.d.ts +1 -1
- package/dist/views/login/LoginView.d.cts +47 -0
- package/dist/views/login/index.d.cts +1 -0
- package/dist/views/login/index.d.ts +1 -1
- package/dist/views/root/RootView.d.cts +10 -0
- package/dist/views/root/index.d.cts +1 -0
- package/dist/views/root/index.d.ts +1 -1
- package/dist/views/search/SearchView.d.cts +7 -0
- package/dist/views/search/index.d.cts +1 -0
- package/dist/views/search/index.d.ts +1 -1
- package/dist/views/sent/SentView.d.cts +7 -0
- package/dist/views/sent/index.d.cts +1 -0
- package/dist/views/sent/index.d.ts +1 -1
- package/dist/views/settings/index.d.cts +1 -0
- package/dist/views/settings/index.d.ts +1 -1
- package/dist/views/settings/notifications/SettingsNotificationsView.d.cts +2 -0
- package/dist/views/settings/notifications/index.d.cts +1 -0
- package/dist/views/settings/notifications/index.d.ts +1 -1
- package/dist/views/templates/TemplatesView.d.cts +7 -0
- package/dist/views/templates/categories/TemplateCategoriesView.d.cts +2 -0
- package/dist/views/templates/categories/index.cjs +1 -1
- package/dist/views/templates/categories/index.d.cts +1 -0
- package/dist/views/templates/categories/index.d.ts +1 -1
- package/dist/views/templates/categories/index.js +1 -1
- package/dist/views/templates/compose/TemplateComposeWizardView.d.cts +21 -0
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.d.cts +2 -0
- package/dist/views/templates/compose/index.d.ts +2 -2
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/compose/steps/ComposeFormStep.d.cts +15 -0
- package/dist/views/templates/compose/steps/ComposeReviewStep.d.cts +12 -0
- package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.cts +22 -0
- package/dist/views/templates/compose/use-template-compose-wizard.d.cts +46 -0
- package/dist/views/templates/designer/NotifyWebhookTargetsEditor.d.cts +20 -0
- package/dist/views/templates/designer/NotifyWebhookTargetsEditor.d.ts +1 -1
- package/dist/views/templates/designer/TemplateDesignerView.d.cts +65 -0
- package/dist/views/templates/designer/chrome-workflow-chat.d.cts +12 -0
- package/dist/views/templates/designer/chrome-workflow-chat.d.ts +1 -1
- package/dist/views/templates/designer/decision-policy-options.d.cts +8 -0
- package/dist/views/templates/designer/designer-version-labels.d.cts +12 -0
- package/dist/views/templates/designer/dry-run-assignee-label.d.cts +28 -0
- package/dist/views/templates/designer/dry-run-sample-data.d.cts +9 -0
- package/dist/views/templates/designer/dynamic-form-resolver-options.d.cts +35 -0
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.d.cts +1 -0
- package/dist/views/templates/designer/index.d.ts +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/dist/views/templates/designer/notify-webhook-designer.d.cts +74 -0
- package/dist/views/templates/designer/position-level-options.d.cts +17 -0
- package/dist/views/templates/designer/use-workflow-chat.d.cts +21 -0
- package/dist/views/templates/designer/use-workflow-chat.d.ts +1 -1
- package/dist/views/templates/designer/use-workflow-designer-controller.d.cts +41 -0
- package/dist/views/templates/designer/workflow-chat-drawer.d.cts +16 -0
- package/dist/views/templates/designer/workflow-chat-drawer.d.ts +1 -1
- package/dist/views/templates/index.cjs +1 -1
- package/dist/views/templates/index.d.cts +3 -0
- package/dist/views/templates/index.d.ts +3 -3
- package/dist/views/templates/index.js +1 -1
- package/dist/views/templates/versions/TemplateVersionsView.d.cts +5 -0
- package/dist/views/templates/versions/index.d.cts +1 -0
- package/dist/views/templates/versions/index.d.ts +1 -1
- package/dist/views/workflow/index.d.cts +4 -0
- package/dist/views/workflow/index.d.ts +4 -4
- package/package.json +387 -147
- package/dist/chunks/admin-pickers-DxhzECkD.js.map +0 -1
- package/dist/chunks/admin-pickers-qe3j--gX.cjs +0 -2
- package/dist/chunks/admin-pickers-qe3j--gX.cjs.map +0 -1
- package/dist/chunks/delegations-BLzYnOae.cjs.map +0 -1
- package/dist/chunks/designer-2YvjP_GU.cjs +0 -65
- package/dist/chunks/designer-2YvjP_GU.cjs.map +0 -1
- package/dist/chunks/designer-B-cfiob9.js.map +0 -1
- package/dist/chunks/detail-C6NdVijG.js.map +0 -1
- package/dist/chunks/detail-DKobK4Cg.cjs +0 -2
- package/dist/chunks/detail-DKobK4Cg.cjs.map +0 -1
- package/dist/chunks/orgs-Bpp1U60k.js.map +0 -1
- package/dist/chunks/orgs-ywaE1_02.cjs +0 -2
- package/dist/chunks/orgs-ywaE1_02.cjs.map +0 -1
- package/dist/chunks/users-BSVo_eNe.js +0 -215
- package/dist/chunks/users-BSVo_eNe.js.map +0 -1
- package/dist/chunks/users-DFSBTDMy.cjs +0 -2
- package/dist/chunks/users-DFSBTDMy.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,64 @@
|
|
|
1
|
+
## 0.17.1 (2026-10-16)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- **react:** give the require condition CommonJS declarations ([ab0121b](https://github.com/Rytass/BPMCore/commit/ab0121b))
|
|
6
|
+
- **template:** say a category in use cannot be deleted ([ab4236b](https://github.com/Rytass/BPMCore/commit/ab4236b))
|
|
7
|
+
- **react:** keep org unit and position picker menus on screen ([bb5cbaa](https://github.com/Rytass/BPMCore/commit/bb5cbaa))
|
|
8
|
+
- **react:** fully specify relative imports in emitted declarations ([022b3e2](https://github.com/Rytass/BPMCore/commit/022b3e2))
|
|
9
|
+
|
|
10
|
+
### ❤️ Thank You
|
|
11
|
+
|
|
12
|
+
- Chia Yu Pai @fantasywind
|
|
13
|
+
|
|
14
|
+
## 0.17.0 (2026-10-15)
|
|
15
|
+
|
|
16
|
+
### 🚀 Features
|
|
17
|
+
|
|
18
|
+
- ⚠️ **workflow-engine:** end SLA-terminated instances as EXPIRED ([7dcca4e](https://github.com/Rytass/BPMCore/commit/7dcca4e))
|
|
19
|
+
- **template:** allow lastDecision in edge conditions ([e8b4788](https://github.com/Rytass/BPMCore/commit/e8b4788))
|
|
20
|
+
- **react:** add member task reassignment modal to admin users ([f12e9f8](https://github.com/Rytass/BPMCore/commit/f12e9f8))
|
|
21
|
+
- **workflow-engine:** add administrator in-place task reassignment ([02ce920](https://github.com/Rytass/BPMCore/commit/02ce920))
|
|
22
|
+
- **template-designer:** let the fallback mode pick a position ([257a361](https://github.com/Rytass/BPMCore/commit/257a361))
|
|
23
|
+
- **views:** ask for a successor unit before retiring an org unit ([b79cd5c](https://github.com/Rytass/BPMCore/commit/b79cd5c))
|
|
24
|
+
- ⚠️ **organization:** retire org units into a successor unit ([514e0b2](https://github.com/Rytass/BPMCore/commit/514e0b2))
|
|
25
|
+
|
|
26
|
+
### 🩹 Fixes
|
|
27
|
+
|
|
28
|
+
- **migrations:** check pg_trgm with the other required extensions ([30a1e58](https://github.com/Rytass/BPMCore/commit/30a1e58))
|
|
29
|
+
- **template:** check CEL roots per call site on publish ([868d236](https://github.com/Rytass/BPMCore/commit/868d236))
|
|
30
|
+
- **instance-detail:** show how a closed instance ended ([a110e08](https://github.com/Rytass/BPMCore/commit/a110e08))
|
|
31
|
+
- ⚠️ **delegation:** order rules by priority, higher first ([96cca55](https://github.com/Rytass/BPMCore/commit/96cca55))
|
|
32
|
+
- **react:** drop a late member task listing in the reassignment modal ([1a7724e](https://github.com/Rytass/BPMCore/commit/1a7724e))
|
|
33
|
+
- **react:** keep reassigned task titles and fit the result table ([3b90530](https://github.com/Rytass/BPMCore/commit/3b90530))
|
|
34
|
+
- **template-designer:** keep unknown approver fallbacks read-only ([5ea88fe](https://github.com/Rytass/BPMCore/commit/5ea88fe))
|
|
35
|
+
|
|
36
|
+
### ⚠️ Breaking Changes
|
|
37
|
+
|
|
38
|
+
- **workflow-engine:** end SLA-terminated instances as EXPIRED ([7dcca4e](https://github.com/Rytass/BPMCore/commit/7dcca4e))
|
|
39
|
+
an instance ended by SLA `TERMINATE_INSTANCE` is now
|
|
40
|
+
`EXPIRED` instead of `CANCELLED`, and its activity log is
|
|
41
|
+
`INSTANCE_EXPIRED` with a null actor instead of `INSTANCE_CANCELLED` in
|
|
42
|
+
the initiator's name. Instances terminated before this change stay
|
|
43
|
+
CANCELLED. A host implementing `BPMWorkflowEngineService` itself must add
|
|
44
|
+
`expireApprovalInstance`.
|
|
45
|
+
- **delegation:** order rules by priority, higher first ([96cca55](https://github.com/Rytass/BPMCore/commit/96cca55))
|
|
46
|
+
when several active delegation rules of one principal
|
|
47
|
+
match a task, the rule with the highest priority now applies instead of
|
|
48
|
+
the oldest. No data migration is needed: priority had no effect before,
|
|
49
|
+
but principals with overlapping rules may now be delegated differently,
|
|
50
|
+
so review their priorities.
|
|
51
|
+
- **organization:** retire org units into a successor unit ([514e0b2](https://github.com/Rytass/BPMCore/commit/514e0b2))
|
|
52
|
+
deleteOrgUnit now also refuses a unit that has no open
|
|
53
|
+
memberships but still has an open ORG_UNIT-scoped manager rule; it used to
|
|
54
|
+
retire it and leave the rule silently dormant. Pass transferToOrgUnitId (or
|
|
55
|
+
end the rule first) to retire such a unit. The refusal message keeps its
|
|
56
|
+
leading "Org unit with memberships cannot be deleted" sentence.
|
|
57
|
+
|
|
58
|
+
### ❤️ Thank You
|
|
59
|
+
|
|
60
|
+
- Chia Yu Pai @fantasywind
|
|
61
|
+
|
|
1
62
|
## 0.16.2 (2026-10-14)
|
|
2
63
|
|
|
3
64
|
### 🚀 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
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";require('../admin-pickers.css');const e=require("./format-member-label-t7ANTF62.cjs");let t=require("react"),n=require("@mezzanine-ui/react"),r=require("@rytass/bpm-core-client"),i=require("react/jsx-runtime");var a={pickerHost:`bpm_pickerHost_Sw6gz`},o=320;function s({disabled:e=!1,name:o,onChange:s,placeholder:c=`搜尋姓名或信箱`,size:l,value:d}){let[f,m]=(0,t.useState)(!1),[h,v]=(0,t.useState)(d?[d]:[]);async function y(e){m(!0);try{v((await(0,r.searchMembers)(e)).map(u))}finally{m(!1)}}return(0,i.jsx)(`div`,{className:a.pickerHost,children:(0,i.jsx)(n.AutoComplete,{asyncData:!0,disabled:e,disabledOptionsFilter:!0,emptyText:`沒有符合的會員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:o,spellCheck:!1},loading:f,loadingText:`搜尋會員中...`,mode:`single`,onChange:e=>s(p(e)),onSearch:y,onSearchTextChange:e=>s(g(e,h)),onVisibilityChange:e=>{e&&y(``)},options:[..._(d?[d]:[],h)],placeholder:c,searchDebounceTime:300,size:l,value:d})})}function c({disabled:e=!1,onChange:r,orgUnits:s,placeholder:c=`選擇組織`,size:l,value:u}){let f=(0,t.useMemo)(()=>s.map(d),[s]);return(0,i.jsx)(`div`,{className:a.pickerHost,children:(0,i.jsx)(n.Select,{clearable:!0,disabled:e,flip:!0,fullWidth:!0,menuMaxHeight:o,onChange:e=>r(m(e)),options:[...f],placeholder:c,size:l,value:u})})}function l({disabled:e=!1,onChange:r,placeholder:s=`選擇職位`,positions:c,size:l,value:u}){let d=(0,t.useMemo)(()=>c.map(f),[c]);return(0,i.jsx)(`div`,{className:a.pickerHost,children:(0,i.jsx)(n.Select,{clearable:!0,disabled:e,flip:!0,fullWidth:!0,menuMaxHeight:o,onChange:e=>r(h(e)),options:[...d],placeholder:s,size:l,value:u})})}function u(t){return{email:t.email,id:t.memberId,name:e.t(t.name,t.email,`dot`)}}function d(e){return{id:e.id,name:`${e.name} · ${e.code}`}}function f(e){return{id:e.id,name:`${e.name} · ${e.code}`}}function p(e){if(!v(e))return null;let t=e.email,n=e.id,r=e.name;return typeof t==`string`&&typeof n==`string`&&typeof r==`string`?{email:t,id:n,name:r}:null}function m(e){if(!v(e))return null;let t=e.id,n=e.name;return typeof t==`string`&&typeof n==`string`?{id:t,name:n}:null}function h(e){if(!v(e))return null;let t=e.id,n=e.name;return typeof t==`string`&&typeof n==`string`?{id:t,name:n}:null}function g(e,t){let n=e.trim().toLocaleLowerCase();if(!n)return null;let r=t.filter(e=>e.id.toLocaleLowerCase()===n||e.email.toLocaleLowerCase()===n||e.name.toLocaleLowerCase()===n);return r.length===1?r[0]:null}function _(e,t){return[...new Map([...e,...t].map(e=>[e.id,e])).values()]}function v(e){return typeof e==`object`&&!!e}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return s}});
|
|
2
|
+
//# sourceMappingURL=admin-pickers-BRHk3qKq.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-pickers-BRHk3qKq.cjs","names":["useState","searchMembers","styles","AutoComplete","useMemo","Select","formatMemberLabel","require_format_member_label","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","admin_pickers_module_default","PICKER_MENU_MAX_HEIGHT","MemberPicker","loading","setLoading","options","setOptions","value","handleSearch","searchText","readMemberOption","onChange","readMemberOptionFromValue","option","readUniqueOption","open","mergeMemberOptions","OrgUnitPicker","orgUnits","readOrgUnitOption","readOrgUnitOptionFromValue","PositionPicker","positions","readPositionOption","readPositionOptionFromValue","member","orgUnit","position","isRecord","email","id","name","normalized","matched","selected"],"sources":["../../src/components/admin-pickers.module.scss","../../src/components/admin-pickers.tsx"],"sourcesContent":[".pickerHost {\n width: 100%;\n min-width: 0;\n\n :global(.mzn-auto-complete),\n :global(.mzn-input),\n :global(.mzn-input-container),\n :global(.mzn-select),\n :global(.mzn-select-trigger),\n :global(.mzn-text-field) {\n width: 100%;\n min-width: 0 !important;\n }\n}\n","'use client';\n\nimport { useMemo, useState, type ReactElement } from 'react';\nimport { AutoComplete, Select } from '@mezzanine-ui/react';\nimport { searchMembers } from '@rytass/bpm-core-client';\nimport type {\n OrgUnitRecord,\n PositionRecord,\n} from '@rytass/bpm-core-client/organization';\nimport { formatMemberLabel } from '../lib/format-member-label';\nimport styles from './admin-pickers.module.scss';\n\nexport type MemberOption = Readonly<{\n email: string;\n id: string;\n name: string;\n}>;\n\nexport type OrgUnitOption = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport type PositionOption = Readonly<{\n id: string;\n name: string;\n}>;\n\n// Without a cap the Mezzanine dropdown grows with its options and never\n// mounts its scrollbar, so a long org-unit or position list runs off the\n// viewport with no way to reach the items below the fold. The pickers also\n// set `flip`: near the bottom of a modal the capped menu still overflows\n// unless it may open upwards.\nconst PICKER_MENU_MAX_HEIGHT = 320;\n\ninterface MemberPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: MemberOption | null) => void;\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: MemberOption | null;\n}\n\ninterface OrgUnitPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: OrgUnitOption | null) => void;\n readonly orgUnits: readonly OrgUnitRecord[];\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: OrgUnitOption | null;\n}\n\ninterface PositionPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: PositionOption | null) => void;\n readonly placeholder?: string;\n readonly positions: readonly PositionRecord[];\n readonly size?: 'main' | 'sub';\n readonly value: PositionOption | null;\n}\n\n/**\n * AutoComplete-backed picker that searches the BPM member directory via\n * `searchMembers()`. Emits a {@link MemberOption} `{ id, name, email }`\n * on selection (or `null` when cleared).\n */\nexport function MemberPicker({\n disabled = false,\n name,\n onChange,\n placeholder = '搜尋姓名或信箱',\n size,\n value,\n}: MemberPickerProps): ReactElement {\n const [loading, setLoading] = useState(false);\n const [options, setOptions] = useState<readonly MemberOption[]>(\n value ? [value] : [],\n );\n\n async function handleSearch(searchText: string): Promise<void> {\n setLoading(true);\n try {\n setOptions((await searchMembers(searchText)).map(readMemberOption));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className={styles.pickerHost}>\n <AutoComplete\n asyncData\n disabled={disabled}\n disabledOptionsFilter\n emptyText=\"沒有符合的會員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name,\n spellCheck: false,\n }}\n loading={loading}\n loadingText=\"搜尋會員中...\"\n mode=\"single\"\n onChange={(option): void => onChange(readMemberOptionFromValue(option))}\n onSearch={handleSearch}\n onSearchTextChange={(searchText): void =>\n onChange(readUniqueOption(searchText, options))\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearch('');\n }\n }}\n options={[...mergeMemberOptions(value ? [value] : [], options)]}\n placeholder={placeholder}\n searchDebounceTime={300}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of org units. Caller is\n * responsible for fetching the org units (typically via\n * `readOrganizationDashboard` from `@rytass/bpm-core-client/organization`).\n */\nexport function OrgUnitPicker({\n disabled = false,\n onChange,\n orgUnits,\n placeholder = '選擇組織',\n size,\n value,\n}: OrgUnitPickerProps): ReactElement {\n const options = useMemo(\n (): readonly OrgUnitOption[] => orgUnits.map(readOrgUnitOption),\n [orgUnits],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readOrgUnitOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of positions.\n */\nexport function PositionPicker({\n disabled = false,\n onChange,\n placeholder = '選擇職位',\n positions,\n size,\n value,\n}: PositionPickerProps): ReactElement {\n const options = useMemo(\n (): readonly PositionOption[] => positions.map(readPositionOption),\n [positions],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readPositionOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\nexport function readMemberOption(member: {\n readonly email: string;\n readonly memberId: string;\n readonly name: string;\n}): MemberOption {\n return {\n email: member.email,\n id: member.memberId,\n name: formatMemberLabel(member.name, member.email, 'dot'),\n };\n}\n\nexport function readOrgUnitOption(orgUnit: OrgUnitRecord): OrgUnitOption {\n return { id: orgUnit.id, name: `${orgUnit.name} · ${orgUnit.code}` };\n}\n\nexport function readPositionOption(position: PositionRecord): PositionOption {\n return { id: position.id, name: `${position.name} · ${position.code}` };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) return null;\n const email = value.email;\n const id = value.id;\n const name = value.name;\n return typeof email === 'string' &&\n typeof id === 'string' &&\n typeof name === 'string'\n ? { email, id, name }\n : null;\n}\n\nfunction readOrgUnitOptionFromValue(value: unknown): OrgUnitOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readPositionOptionFromValue(value: unknown): PositionOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readUniqueOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalized = searchText.trim().toLocaleLowerCase();\n if (!normalized) return null;\n const matched = options.filter(\n (option) =>\n option.id.toLocaleLowerCase() === normalized ||\n option.email.toLocaleLowerCase() === normalized ||\n option.name.toLocaleLowerCase() === normalized,\n );\n return matched.length === 1 ? matched[0] : null;\n}\n\nfunction mergeMemberOptions(\n selected: readonly MemberOption[],\n options: readonly MemberOption[],\n): readonly MemberOption[] {\n const byId = new Map(\n [...selected, ...options].map(\n (option): readonly [string, MemberOption] => [option.id, option],\n ),\n );\n return [...byId.values()];\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
|
|
@@ -4,15 +4,13 @@ import { useMemo as t, useState as n } from "react";
|
|
|
4
4
|
import { AutoComplete as r, Select as i } from "@mezzanine-ui/react";
|
|
5
5
|
import { searchMembers as a } from "@rytass/bpm-core-client";
|
|
6
6
|
import { jsx as o } from "react/jsx-runtime";
|
|
7
|
-
import '../admin-pickers.css';var s = { pickerHost: "bpm_pickerHost_Sw6gz" };
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function
|
|
11
|
-
let [f, p] = n(!1), [h, g] = n(u ? [u] : []);
|
|
12
|
-
async function y(e) {
|
|
7
|
+
import '../admin-pickers.css';var s = { pickerHost: "bpm_pickerHost_Sw6gz" }, c = 320;
|
|
8
|
+
function l({ disabled: e = !1, name: t, onChange: i, placeholder: c = "搜尋姓名或信箱", size: l, value: u }) {
|
|
9
|
+
let [d, p] = n(!1), [m, g] = n(u ? [u] : []);
|
|
10
|
+
async function _(e) {
|
|
13
11
|
p(!0);
|
|
14
12
|
try {
|
|
15
|
-
g((await a(e)).map(
|
|
13
|
+
g((await a(e)).map(f));
|
|
16
14
|
} finally {
|
|
17
15
|
p(!1);
|
|
18
16
|
}
|
|
@@ -30,16 +28,16 @@ function c({ disabled: e = !1, name: t, onChange: i, placeholder: c = "搜尋姓
|
|
|
30
28
|
name: t,
|
|
31
29
|
spellCheck: !1
|
|
32
30
|
},
|
|
33
|
-
loading:
|
|
31
|
+
loading: d,
|
|
34
32
|
loadingText: "搜尋會員中...",
|
|
35
33
|
mode: "single",
|
|
36
|
-
onChange: (e) => i(
|
|
37
|
-
onSearch:
|
|
38
|
-
onSearchTextChange: (e) => i(
|
|
34
|
+
onChange: (e) => i(h(e)),
|
|
35
|
+
onSearch: _,
|
|
36
|
+
onSearchTextChange: (e) => i(v(e, m)),
|
|
39
37
|
onVisibilityChange: (e) => {
|
|
40
|
-
e &&
|
|
38
|
+
e && _("");
|
|
41
39
|
},
|
|
42
|
-
options: [...
|
|
40
|
+
options: [...y(u ? [u] : [], m)],
|
|
43
41
|
placeholder: c,
|
|
44
42
|
searchDebounceTime: 300,
|
|
45
43
|
size: l,
|
|
@@ -47,59 +45,63 @@ function c({ disabled: e = !1, name: t, onChange: i, placeholder: c = "搜尋姓
|
|
|
47
45
|
})
|
|
48
46
|
});
|
|
49
47
|
}
|
|
50
|
-
function
|
|
51
|
-
let
|
|
48
|
+
function u({ disabled: e = !1, onChange: n, orgUnits: r, placeholder: a = "選擇組織", size: l, value: u }) {
|
|
49
|
+
let d = t(() => r.map(p), [r]);
|
|
52
50
|
return /* @__PURE__ */ o("div", {
|
|
53
51
|
className: s.pickerHost,
|
|
54
52
|
children: /* @__PURE__ */ o(i, {
|
|
55
53
|
clearable: !0,
|
|
56
54
|
disabled: e,
|
|
55
|
+
flip: !0,
|
|
57
56
|
fullWidth: !0,
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
menuMaxHeight: c,
|
|
58
|
+
onChange: (e) => n(g(e)),
|
|
59
|
+
options: [...d],
|
|
60
60
|
placeholder: a,
|
|
61
|
-
size:
|
|
62
|
-
value:
|
|
61
|
+
size: l,
|
|
62
|
+
value: u
|
|
63
63
|
})
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
|
-
function
|
|
67
|
-
let
|
|
66
|
+
function d({ disabled: e = !1, onChange: n, placeholder: r = "選擇職位", positions: a, size: l, value: u }) {
|
|
67
|
+
let d = t(() => a.map(m), [a]);
|
|
68
68
|
return /* @__PURE__ */ o("div", {
|
|
69
69
|
className: s.pickerHost,
|
|
70
70
|
children: /* @__PURE__ */ o(i, {
|
|
71
71
|
clearable: !0,
|
|
72
72
|
disabled: e,
|
|
73
|
+
flip: !0,
|
|
73
74
|
fullWidth: !0,
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
menuMaxHeight: c,
|
|
76
|
+
onChange: (e) => n(_(e)),
|
|
77
|
+
options: [...d],
|
|
76
78
|
placeholder: r,
|
|
77
|
-
size:
|
|
78
|
-
value:
|
|
79
|
+
size: l,
|
|
80
|
+
value: u
|
|
79
81
|
})
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
|
-
function
|
|
84
|
+
function f(t) {
|
|
83
85
|
return {
|
|
84
86
|
email: t.email,
|
|
85
87
|
id: t.memberId,
|
|
86
88
|
name: e(t.name, t.email, "dot")
|
|
87
89
|
};
|
|
88
90
|
}
|
|
89
|
-
function
|
|
91
|
+
function p(e) {
|
|
90
92
|
return {
|
|
91
93
|
id: e.id,
|
|
92
94
|
name: `${e.name} · ${e.code}`
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
|
-
function
|
|
97
|
+
function m(e) {
|
|
96
98
|
return {
|
|
97
99
|
id: e.id,
|
|
98
100
|
name: `${e.name} · ${e.code}`
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
|
-
function
|
|
102
|
-
if (!
|
|
103
|
+
function h(e) {
|
|
104
|
+
if (!b(e)) return null;
|
|
103
105
|
let t = e.email, n = e.id, r = e.name;
|
|
104
106
|
return typeof t == "string" && typeof n == "string" && typeof r == "string" ? {
|
|
105
107
|
email: t,
|
|
@@ -107,35 +109,35 @@ function m(e) {
|
|
|
107
109
|
name: r
|
|
108
110
|
} : null;
|
|
109
111
|
}
|
|
110
|
-
function
|
|
111
|
-
if (!
|
|
112
|
+
function g(e) {
|
|
113
|
+
if (!b(e)) return null;
|
|
112
114
|
let t = e.id, n = e.name;
|
|
113
115
|
return typeof t == "string" && typeof n == "string" ? {
|
|
114
116
|
id: t,
|
|
115
117
|
name: n
|
|
116
118
|
} : null;
|
|
117
119
|
}
|
|
118
|
-
function
|
|
119
|
-
if (!
|
|
120
|
+
function _(e) {
|
|
121
|
+
if (!b(e)) return null;
|
|
120
122
|
let t = e.id, n = e.name;
|
|
121
123
|
return typeof t == "string" && typeof n == "string" ? {
|
|
122
124
|
id: t,
|
|
123
125
|
name: n
|
|
124
126
|
} : null;
|
|
125
127
|
}
|
|
126
|
-
function
|
|
128
|
+
function v(e, t) {
|
|
127
129
|
let n = e.trim().toLocaleLowerCase();
|
|
128
130
|
if (!n) return null;
|
|
129
131
|
let r = t.filter((e) => e.id.toLocaleLowerCase() === n || e.email.toLocaleLowerCase() === n || e.name.toLocaleLowerCase() === n);
|
|
130
132
|
return r.length === 1 ? r[0] : null;
|
|
131
133
|
}
|
|
132
|
-
function
|
|
134
|
+
function y(e, t) {
|
|
133
135
|
return [...new Map([...e, ...t].map((e) => [e.id, e])).values()];
|
|
134
136
|
}
|
|
135
|
-
function
|
|
137
|
+
function b(e) {
|
|
136
138
|
return typeof e == "object" && !!e;
|
|
137
139
|
}
|
|
138
140
|
//#endregion
|
|
139
|
-
export {
|
|
141
|
+
export { p as a, f as i, u as n, m as o, d as r, l as t };
|
|
140
142
|
|
|
141
|
-
//# sourceMappingURL=admin-pickers-
|
|
143
|
+
//# sourceMappingURL=admin-pickers-Djq3h-UR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-pickers-Djq3h-UR.js","names":["styles","formatMemberLabel","admin_pickers_module_default","PICKER_MENU_MAX_HEIGHT","MemberPicker","loading","setLoading","useState","options","setOptions","value","handleSearch","searchMembers","searchText","readMemberOption","AutoComplete","onChange","readMemberOptionFromValue","option","readUniqueOption","open","mergeMemberOptions","OrgUnitPicker","useMemo","orgUnits","readOrgUnitOption","Select","readOrgUnitOptionFromValue","PositionPicker","positions","readPositionOption","readPositionOptionFromValue","member","orgUnit","position","isRecord","email","id","name","normalized","matched","selected"],"sources":["../../src/components/admin-pickers.module.scss","../../src/components/admin-pickers.tsx"],"sourcesContent":[".pickerHost {\n width: 100%;\n min-width: 0;\n\n :global(.mzn-auto-complete),\n :global(.mzn-input),\n :global(.mzn-input-container),\n :global(.mzn-select),\n :global(.mzn-select-trigger),\n :global(.mzn-text-field) {\n width: 100%;\n min-width: 0 !important;\n }\n}\n","'use client';\n\nimport { useMemo, useState, type ReactElement } from 'react';\nimport { AutoComplete, Select } from '@mezzanine-ui/react';\nimport { searchMembers } from '@rytass/bpm-core-client';\nimport type {\n OrgUnitRecord,\n PositionRecord,\n} from '@rytass/bpm-core-client/organization';\nimport { formatMemberLabel } from '../lib/format-member-label';\nimport styles from './admin-pickers.module.scss';\n\nexport type MemberOption = Readonly<{\n email: string;\n id: string;\n name: string;\n}>;\n\nexport type OrgUnitOption = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport type PositionOption = Readonly<{\n id: string;\n name: string;\n}>;\n\n// Without a cap the Mezzanine dropdown grows with its options and never\n// mounts its scrollbar, so a long org-unit or position list runs off the\n// viewport with no way to reach the items below the fold. The pickers also\n// set `flip`: near the bottom of a modal the capped menu still overflows\n// unless it may open upwards.\nconst PICKER_MENU_MAX_HEIGHT = 320;\n\ninterface MemberPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: MemberOption | null) => void;\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: MemberOption | null;\n}\n\ninterface OrgUnitPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: OrgUnitOption | null) => void;\n readonly orgUnits: readonly OrgUnitRecord[];\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: OrgUnitOption | null;\n}\n\ninterface PositionPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: PositionOption | null) => void;\n readonly placeholder?: string;\n readonly positions: readonly PositionRecord[];\n readonly size?: 'main' | 'sub';\n readonly value: PositionOption | null;\n}\n\n/**\n * AutoComplete-backed picker that searches the BPM member directory via\n * `searchMembers()`. Emits a {@link MemberOption} `{ id, name, email }`\n * on selection (or `null` when cleared).\n */\nexport function MemberPicker({\n disabled = false,\n name,\n onChange,\n placeholder = '搜尋姓名或信箱',\n size,\n value,\n}: MemberPickerProps): ReactElement {\n const [loading, setLoading] = useState(false);\n const [options, setOptions] = useState<readonly MemberOption[]>(\n value ? [value] : [],\n );\n\n async function handleSearch(searchText: string): Promise<void> {\n setLoading(true);\n try {\n setOptions((await searchMembers(searchText)).map(readMemberOption));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className={styles.pickerHost}>\n <AutoComplete\n asyncData\n disabled={disabled}\n disabledOptionsFilter\n emptyText=\"沒有符合的會員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name,\n spellCheck: false,\n }}\n loading={loading}\n loadingText=\"搜尋會員中...\"\n mode=\"single\"\n onChange={(option): void => onChange(readMemberOptionFromValue(option))}\n onSearch={handleSearch}\n onSearchTextChange={(searchText): void =>\n onChange(readUniqueOption(searchText, options))\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearch('');\n }\n }}\n options={[...mergeMemberOptions(value ? [value] : [], options)]}\n placeholder={placeholder}\n searchDebounceTime={300}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of org units. Caller is\n * responsible for fetching the org units (typically via\n * `readOrganizationDashboard` from `@rytass/bpm-core-client/organization`).\n */\nexport function OrgUnitPicker({\n disabled = false,\n onChange,\n orgUnits,\n placeholder = '選擇組織',\n size,\n value,\n}: OrgUnitPickerProps): ReactElement {\n const options = useMemo(\n (): readonly OrgUnitOption[] => orgUnits.map(readOrgUnitOption),\n [orgUnits],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readOrgUnitOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of positions.\n */\nexport function PositionPicker({\n disabled = false,\n onChange,\n placeholder = '選擇職位',\n positions,\n size,\n value,\n}: PositionPickerProps): ReactElement {\n const options = useMemo(\n (): readonly PositionOption[] => positions.map(readPositionOption),\n [positions],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readPositionOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\nexport function readMemberOption(member: {\n readonly email: string;\n readonly memberId: string;\n readonly name: string;\n}): MemberOption {\n return {\n email: member.email,\n id: member.memberId,\n name: formatMemberLabel(member.name, member.email, 'dot'),\n };\n}\n\nexport function readOrgUnitOption(orgUnit: OrgUnitRecord): OrgUnitOption {\n return { id: orgUnit.id, name: `${orgUnit.name} · ${orgUnit.code}` };\n}\n\nexport function readPositionOption(position: PositionRecord): PositionOption {\n return { id: position.id, name: `${position.name} · ${position.code}` };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) return null;\n const email = value.email;\n const id = value.id;\n const name = value.name;\n return typeof email === 'string' &&\n typeof id === 'string' &&\n typeof name === 'string'\n ? { email, id, name }\n : null;\n}\n\nfunction readOrgUnitOptionFromValue(value: unknown): OrgUnitOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readPositionOptionFromValue(value: unknown): PositionOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readUniqueOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalized = searchText.trim().toLocaleLowerCase();\n if (!normalized) return null;\n const matched = options.filter(\n (option) =>\n option.id.toLocaleLowerCase() === normalized ||\n option.email.toLocaleLowerCase() === normalized ||\n option.name.toLocaleLowerCase() === normalized,\n );\n return matched.length === 1 ? matched[0] : null;\n}\n\nfunction mergeMemberOptions(\n selected: readonly MemberOption[],\n options: readonly MemberOption[],\n): readonly MemberOption[] {\n const byId = new Map(\n [...selected, ...options].map(\n (option): readonly [string, MemberOption] => [option.id, option],\n ),\n );\n return [...byId.values()];\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";require('../categories.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./format-date-time-D-cx5M8z.cjs"),n=require("./bpm-form-field-Bc6k4ZEO.cjs");let r=require("react"),i=require("@mezzanine-ui/react"),a=require("react/jsx-runtime"),o=require("@mezzanine-ui/core/form"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let c=require("@mezzanine-ui/icons"),l=require("@rytass/bpm-core-client/template");var u={templateFilterArea:`bpm_templateFilterArea_nUL-R`,templateModalFields:`bpm_templateModalFields_hUxWp`},d=[10,20,50],f=[{key:`ALL`,label:`全部`},{key:`ACTIVE`,label:`啟用`},{key:`INACTIVE`,label:`停用`}];function p(){let[e,n]=(0,r.useState)([]),[p,y]=(0,r.useState)(1),[b,x]=(0,r.useState)(10),[S,C]=(0,r.useState)(`ALL`),[w,T]=(0,r.useState)(0),[E,D]=(0,r.useState)(null),[O,k]=(0,r.useState)(null),[A,j]=(0,r.useState)(!0),[M,N]=(0,r.useState)(null),[P,F]=(0,r.useState)(!1),[I,L]=(0,r.useState)(``),R=(0,r.useCallback)(async()=>{j(!0),k(null);try{let e=await(0,l.listApprovalTemplateCategoriesPage)({page:p,pageSize:b,searchText:I,status:_(S)});n(e.categories),T(e.totalCount)}catch(e){k(v(e))}finally{j(!1)}},[p,b,S,I]);(0,r.useEffect)(()=>{R()},[R]);let z=(0,r.useMemo)(()=>e.map(e=>({...e,key:e.id,updatedAtLabel:t.t(e.updatedAt)})),[e]),B=(0,r.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`分類名稱`,width:180},{key:`status`,render:e=>(0,a.jsx)(h,{isActive:e.isActive}),title:`狀態`,width:120},{dataIndex:`sortOrder`,key:`sortOrder`,title:`排序`,width:100},{key:`description`,render:e=>(0,a.jsx)(i.Typography,{component:`span`,variant:`body`,children:e.description||`無`}),title:`說明`,width:260},{dataIndex:`updatedAtLabel`,key:`updatedAtLabel`,title:`更新時間`,width:220}],[]);async function V(e){F(!0),k(null);try{M?.type===`EDIT`&&M.record?await(0,l.updateApprovalTemplateCategory)({...e,id:M.record.id}):await(0,l.createApprovalTemplateCategory)(e),N(null),await R()}catch(e){throw k(v(e)),e}finally{F(!1)}}async function H(e){F(!0),k(null);try{await(0,l.updateApprovalTemplateCategory)({description:e.description,id:e.id,isActive:!e.isActive,name:e.name,sortOrder:e.sortOrder}),await R()}catch(e){k(v(e))}finally{F(!1)}}async function U(){if(E){F(!0),k(null);try{await(0,l.deleteApprovalTemplateCategory)(E.id),D(null),await R()}catch(e){k(v(e))}finally{F(!1)}}}let W=(0,r.useMemo)(()=>({render:e=>[{name:`編輯`,onClick:()=>N({record:e,type:`EDIT`})},{name:e.isActive?`停用`:`啟用`,onClick:()=>void H(e),variant:e.isActive?`destructive-secondary`:`base-secondary`},{name:`刪除`,onClick:()=>D({id:e.id,name:e.name}),variant:`destructive-secondary`}],variant:`base-secondary`,width:192}),[R]);return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.PageHeader,{children:(0,a.jsx)(s.default,{description:`維護簽核模板分類,供模板建立、篩選與列表標示使用。`,title:`簽核模板分類`,children:(0,a.jsx)(i.Button,{icon:c.PlusIcon,iconType:`leading`,onClick:()=>N({record:null,type:`CREATE`}),variant:`base-primary`,children:`建立分類`})})}),(0,a.jsx)(i.SectionGroup,{children:(0,a.jsxs)(i.Section,{filterArea:(0,a.jsx)(i.FilterArea,{className:u.templateFilterArea,size:`sub`,children:(0,a.jsx)(i.FilterLine,{children:(0,a.jsx)(i.Filter,{span:3,children:(0,a.jsx)(i.FormField,{fullWidth:!0,layout:o.FormFieldLayout.VERTICAL,name:`categorySearchText`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{L(e.target.value),y(1)},placeholder:`關鍵字:搜尋分類名稱或說明`,size:`sub`,value:I,variant:`base`})})})})}),tab:(0,a.jsx)(i.Tab,{activeKey:S,onChange:e=>{C(g(e)),y(1)},children:f.map(e=>(0,a.jsx)(i.TabItem,{children:e.label},e.key))}),children:[O?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:O}):null,(0,a.jsx)(i.Table,{actions:W,columns:B,dataSource:z,fullWidth:!0,loading:A||P,pagination:{current:p,onChange:e=>{y(e)},onChangePageSize:e=>{y(1),x(e)},pageSize:b,pageSizeLabel:`每頁筆數`,pageSizeOptions:d,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:w}})]})})]}),(0,a.jsx)(m,{loading:P,modal:M,onClose:()=>N(null),onSubmit:V}),(0,a.jsx)(i.Modal,{cancelText:`取消`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`刪除`,loading:P,modalStatusType:`error`,modalType:`standard`,onCancel:()=>D(null),onClose:()=>D(null),onConfirm:()=>void U(),open:!!E,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText
|
|
2
|
-
//# sourceMappingURL=categories-
|
|
1
|
+
"use client";require('../categories.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./format-date-time-D-cx5M8z.cjs"),n=require("./bpm-form-field-Bc6k4ZEO.cjs");let r=require("react"),i=require("@mezzanine-ui/react"),a=require("react/jsx-runtime"),o=require("@mezzanine-ui/core/form"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let c=require("@mezzanine-ui/icons"),l=require("@rytass/bpm-core-client/template");var u={templateFilterArea:`bpm_templateFilterArea_nUL-R`,templateModalFields:`bpm_templateModalFields_hUxWp`},d=[10,20,50],f=[{key:`ALL`,label:`全部`},{key:`ACTIVE`,label:`啟用`},{key:`INACTIVE`,label:`停用`}];function p(){let[e,n]=(0,r.useState)([]),[p,y]=(0,r.useState)(1),[b,x]=(0,r.useState)(10),[S,C]=(0,r.useState)(`ALL`),[w,T]=(0,r.useState)(0),[E,D]=(0,r.useState)(null),[O,k]=(0,r.useState)(null),[A,j]=(0,r.useState)(!0),[M,N]=(0,r.useState)(null),[P,F]=(0,r.useState)(!1),[I,L]=(0,r.useState)(``),R=(0,r.useCallback)(async()=>{j(!0),k(null);try{let e=await(0,l.listApprovalTemplateCategoriesPage)({page:p,pageSize:b,searchText:I,status:_(S)});n(e.categories),T(e.totalCount)}catch(e){k(v(e))}finally{j(!1)}},[p,b,S,I]);(0,r.useEffect)(()=>{R()},[R]);let z=(0,r.useMemo)(()=>e.map(e=>({...e,key:e.id,updatedAtLabel:t.t(e.updatedAt)})),[e]),B=(0,r.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`分類名稱`,width:180},{key:`status`,render:e=>(0,a.jsx)(h,{isActive:e.isActive}),title:`狀態`,width:120},{dataIndex:`sortOrder`,key:`sortOrder`,title:`排序`,width:100},{key:`description`,render:e=>(0,a.jsx)(i.Typography,{component:`span`,variant:`body`,children:e.description||`無`}),title:`說明`,width:260},{dataIndex:`updatedAtLabel`,key:`updatedAtLabel`,title:`更新時間`,width:220}],[]);async function V(e){F(!0),k(null);try{M?.type===`EDIT`&&M.record?await(0,l.updateApprovalTemplateCategory)({...e,id:M.record.id}):await(0,l.createApprovalTemplateCategory)(e),N(null),await R()}catch(e){throw k(v(e)),e}finally{F(!1)}}async function H(e){F(!0),k(null);try{await(0,l.updateApprovalTemplateCategory)({description:e.description,id:e.id,isActive:!e.isActive,name:e.name,sortOrder:e.sortOrder}),await R()}catch(e){k(v(e))}finally{F(!1)}}async function U(){if(E){F(!0),k(null);try{await(0,l.deleteApprovalTemplateCategory)(E.id),D(null),await R()}catch(e){k(v(e))}finally{F(!1)}}}let W=(0,r.useMemo)(()=>({render:e=>[{name:`編輯`,onClick:()=>N({record:e,type:`EDIT`})},{name:e.isActive?`停用`:`啟用`,onClick:()=>void H(e),variant:e.isActive?`destructive-secondary`:`base-secondary`},{name:`刪除`,onClick:()=>D({id:e.id,name:e.name}),variant:`destructive-secondary`}],variant:`base-secondary`,width:192}),[R]);return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.PageHeader,{children:(0,a.jsx)(s.default,{description:`維護簽核模板分類,供模板建立、篩選與列表標示使用。`,title:`簽核模板分類`,children:(0,a.jsx)(i.Button,{icon:c.PlusIcon,iconType:`leading`,onClick:()=>N({record:null,type:`CREATE`}),variant:`base-primary`,children:`建立分類`})})}),(0,a.jsx)(i.SectionGroup,{children:(0,a.jsxs)(i.Section,{filterArea:(0,a.jsx)(i.FilterArea,{className:u.templateFilterArea,size:`sub`,children:(0,a.jsx)(i.FilterLine,{children:(0,a.jsx)(i.Filter,{span:3,children:(0,a.jsx)(i.FormField,{fullWidth:!0,layout:o.FormFieldLayout.VERTICAL,name:`categorySearchText`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{L(e.target.value),y(1)},placeholder:`關鍵字:搜尋分類名稱或說明`,size:`sub`,value:I,variant:`base`})})})})}),tab:(0,a.jsx)(i.Tab,{activeKey:S,onChange:e=>{C(g(e)),y(1)},children:f.map(e=>(0,a.jsx)(i.TabItem,{children:e.label},e.key))}),children:[O?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:O}):null,(0,a.jsx)(i.Table,{actions:W,columns:B,dataSource:z,fullWidth:!0,loading:A||P,pagination:{current:p,onChange:e=>{y(e)},onChangePageSize:e=>{y(1),x(e)},pageSize:b,pageSizeLabel:`每頁筆數`,pageSizeOptions:d,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:w}})]})})]}),(0,a.jsx)(m,{loading:P,modal:M,onClose:()=>N(null),onSubmit:V}),(0,a.jsx)(i.Modal,{cancelText:`取消`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`刪除`,loading:P,modalStatusType:`error`,modalType:`standard`,onCancel:()=>D(null),onClose:()=>D(null),onConfirm:()=>void U(),open:!!E,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`已被模板使用的分類無法刪除,請改用「停用」。`,title:`刪除分類`,children:(0,a.jsxs)(i.Typography,{color:`text-neutral`,variant:`body`,children:[`確定要刪除「`,E?.name??``,`」嗎?`]})})]})}function m({loading:e,modal:t,onClose:o,onSubmit:s}){let[c,l]=(0,r.useState)(``),[d,f]=(0,r.useState)(null),[p,m]=(0,r.useState)(``),[h,g]=(0,r.useState)(`0`);(0,r.useEffect)(()=>{t&&(l(t.record?.description??``),f(null),m(t.record?.name??``),g(String(t.record?.sortOrder??0)))},[t]);async function _(){let e=p.trim(),n=Number(h);if(!e)f(`請輸入分類名稱`);else if(!Number.isInteger(n))f(`排序必須是整數`);else try{await s({description:c.trim()||null,isActive:t?.record?.isActive??!0,name:e,sortOrder:n})}catch(e){f(v(e))}}return(0,a.jsxs)(i.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!p.trim()},confirmText:t?.type===`EDIT`?`儲存`:`建立`,loading:e,modalType:`standard`,onCancel:o,onClose:o,onConfirm:()=>void _(),open:!!t,showModalFooter:!0,showModalHeader:!0,size:`regular`,title:t?.type===`EDIT`?`編輯分類`:`建立分類`,children:[(0,a.jsxs)(`div`,{className:u.templateModalFields,children:[(0,a.jsx)(n.t,{label:`分類名稱`,name:`categoryName`,required:!0,children:(0,a.jsx)(i.Input,{autoFocus:!0,fullWidth:!0,onChange:e=>{m(e.target.value),f(null)},placeholder:`例如:行政管理`,value:p,variant:`base`})}),(0,a.jsx)(n.t,{label:`排序`,name:`categorySortOrder`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{g(e.target.value),f(null)},placeholder:`0`,value:h,variant:`base`})}),(0,a.jsx)(n.t,{label:`說明`,name:`categoryDescription`,children:(0,a.jsx)(i.Textarea,{onChange:e=>{l(e.target.value),f(null)},placeholder:`補充分類用途`,value:c})})]}),d?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:d}):null]})}function h({isActive:e}){return e?(0,a.jsx)(i.Badge,{size:`sub`,text:`啟用`,variant:`dot-success`}):(0,a.jsx)(i.Badge,{size:`sub`,text:`停用`,variant:`dot-inactive`})}function g(e){return e===`ACTIVE`||e===`INACTIVE`?e:`ALL`}function _(e){return e}function v(e){return e instanceof Error?e.message:`發生未知錯誤`}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return p}});
|
|
2
|
+
//# sourceMappingURL=categories-AxxhqjLZ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories-DjENouRm.cjs","names":["useState","useCallback","listApprovalTemplateCategoriesPage","useMemo","formatDateTime","Typography","updateApprovalTemplateCategory","createApprovalTemplateCategory","deleteApprovalTemplateCategory","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Tab","TabItem","Table","Modal","BPMFormField","Textarea","Badge","require_rolldown_runtime","require_format_date_time","require_bpm_form_field","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_template","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","categoryPageResult","readCategoryStatus","requestError","readErrorMessage","rows","category","columns","CategoryStatusBadge","record","handleSaveCategory","input","handleToggleCategory","handleConfirmDelete","tableActions","event","readCategoryStatusTabKey","activeKey","statusTab","page","pageSize","from","to","total","CategoryModal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","isActive","status"],"sources":["../../src/views/templates/templates.module.scss","../../src/views/templates/categories/TemplateCategoriesView.tsx"],"sourcesContent":[".templateFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n\n.templateModalFields {\n display: grid;\n gap: 16px;\n}\n","'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport {\n ApprovalTemplateCategoryRecord,\n ApprovalTemplateCategoryStatus,\n createApprovalTemplateCategory,\n deleteApprovalTemplateCategory,\n listApprovalTemplateCategoriesPage,\n updateApprovalTemplateCategory,\n} from '@rytass/bpm-core-client/template';\nimport styles from '../templates.module.scss';\n\nconst CATEGORY_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst CATEGORY_STATUS_TABS: readonly {\n readonly key: CategoryStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'ACTIVE', label: '啟用' },\n { key: 'INACTIVE', label: '停用' },\n];\ntype CategoryStatusTabKey = 'ACTIVE' | 'ALL' | 'INACTIVE';\n\ntype CategoryRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateCategoryRecord & {\n key: string;\n updatedAtLabel: string;\n }\n>;\n\ntype CategoryModalState = Readonly<{\n record: ApprovalTemplateCategoryRecord | null;\n type: 'CREATE' | 'EDIT';\n}>;\n\ntype DeleteConfirmationState = Readonly<{\n id: string;\n name: string;\n}>;\n\n\nexport function TemplateCategoriesView(): ReactElement {\n const [categories, setCategories] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n const [categoryPage, setCategoryPage] = useState(1);\n const [categoryPageSize, setCategoryPageSize] = useState(10);\n const [categoryStatus, setCategoryStatus] =\n useState<CategoryStatusTabKey>('ALL');\n const [categoryTotalCount, setCategoryTotalCount] = useState(0);\n const [deleteConfirmation, setDeleteConfirmation] =\n useState<DeleteConfirmationState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [modalState, setModalState] = useState<CategoryModalState | null>(null);\n const [saving, setSaving] = useState(false);\n const [searchText, setSearchText] = useState('');\n\n const refreshCategories = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const categoryPageResult = await listApprovalTemplateCategoriesPage({\n page: categoryPage,\n pageSize: categoryPageSize,\n searchText,\n status: readCategoryStatus(categoryStatus),\n });\n\n setCategories(categoryPageResult.categories);\n setCategoryTotalCount(categoryPageResult.totalCount);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [categoryPage, categoryPageSize, categoryStatus, searchText]);\n\n useEffect((): void => {\n void refreshCategories();\n }, [refreshCategories]);\n\n const rows = useMemo(\n (): CategoryRow[] =>\n categories.map((category) => ({\n ...category,\n key: category.id,\n updatedAtLabel: formatDateTime(category.updatedAt),\n })),\n [categories],\n );\n\n const columns = useMemo(\n (): TableColumn<CategoryRow>[] => [\n { dataIndex: 'name', key: 'name', title: '分類名稱', width: 180 },\n {\n key: 'status',\n render: (record: CategoryRow): ReactElement => (\n <CategoryStatusBadge isActive={record.isActive} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n dataIndex: 'sortOrder',\n key: 'sortOrder',\n title: '排序',\n width: 100,\n },\n {\n key: 'description',\n render: (record: CategoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.description || '無'}\n </Typography>\n ),\n title: '說明',\n width: 260,\n },\n {\n dataIndex: 'updatedAtLabel',\n key: 'updatedAtLabel',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function handleSaveCategory(input: CategoryFormInput): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n if (modalState?.type === 'EDIT' && modalState.record) {\n await updateApprovalTemplateCategory({\n ...input,\n id: modalState.record.id,\n });\n } else {\n await createApprovalTemplateCategory(input);\n }\n\n setModalState(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n throw requestError;\n } finally {\n setSaving(false);\n }\n }\n\n async function handleToggleCategory(\n record: ApprovalTemplateCategoryRecord,\n ): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n await updateApprovalTemplateCategory({\n description: record.description,\n id: record.id,\n isActive: !record.isActive,\n name: record.name,\n sortOrder: record.sortOrder,\n });\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handleConfirmDelete(): Promise<void> {\n if (!deleteConfirmation) {\n return;\n }\n\n setSaving(true);\n setError(null);\n\n try {\n await deleteApprovalTemplateCategory(deleteConfirmation.id);\n setDeleteConfirmation(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n const tableActions = useMemo(\n (): TableActions<CategoryRow> => ({\n render: (record): ReturnType<TableActions<CategoryRow>['render']> => [\n {\n name: '編輯',\n onClick: (): void => setModalState({ record, type: 'EDIT' }),\n },\n {\n name: record.isActive ? '停用' : '啟用',\n onClick: (): void => void handleToggleCategory(record),\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n {\n name: '刪除',\n onClick: (): void =>\n setDeleteConfirmation({ id: record.id, name: record.name }),\n variant: 'destructive-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [refreshCategories],\n );\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"維護簽核模板分類,供模板建立、篩選與列表標示使用。\"\n title=\"簽核模板分類\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n setModalState({ record: null, type: 'CREATE' })\n }\n variant=\"base-primary\"\n >\n 建立分類\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"categorySearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setCategoryPage(1);\n }}\n placeholder=\"關鍵字:搜尋分類名稱或說明\"\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={categoryStatus}\n onChange={(activeKey): void => {\n setCategoryStatus(readCategoryStatusTabKey(activeKey));\n setCategoryPage(1);\n }}\n >\n {CATEGORY_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading || saving}\n pagination={{\n current: categoryPage,\n onChange: (page): void => {\n setCategoryPage(page);\n },\n onChangePageSize: (pageSize): void => {\n setCategoryPage(1);\n setCategoryPageSize(pageSize);\n },\n pageSize: categoryPageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: CATEGORY_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: categoryTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n\n <CategoryModal\n loading={saving}\n modal={modalState}\n onClose={(): void => setModalState(null)}\n onSubmit={handleSaveCategory}\n />\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"刪除\"\n loading={saving}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setDeleteConfirmation(null)}\n onClose={(): void => setDeleteConfirmation(null)}\n onConfirm={(): void => void handleConfirmDelete()}\n open={Boolean(deleteConfirmation)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"若分類已被模板使用,系統會改為停用分類並保留既有模板關聯。\"\n title=\"刪除分類\"\n >\n <Typography color=\"text-neutral\" variant=\"body\">\n 確定要刪除「{deleteConfirmation?.name ?? ''}」嗎?\n </Typography>\n </Modal>\n </>\n );\n}\n\ninterface CategoryFormInput {\n readonly description: string | null;\n readonly isActive: boolean;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nfunction CategoryModal({\n loading,\n modal,\n onClose,\n onSubmit,\n}: {\n readonly loading: boolean;\n readonly modal: CategoryModalState | null;\n readonly onClose: () => void;\n readonly onSubmit: (input: CategoryFormInput) => Promise<void>;\n}): ReactElement {\n const [description, setDescription] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [sortOrder, setSortOrder] = useState('0');\n\n useEffect((): void => {\n if (!modal) {\n return;\n }\n\n setDescription(modal.record?.description ?? '');\n setError(null);\n setName(modal.record?.name ?? '');\n setSortOrder(String(modal.record?.sortOrder ?? 0));\n }, [modal]);\n\n async function handleConfirm(): Promise<void> {\n const trimmedName = name.trim();\n const parsedSortOrder = Number(sortOrder);\n\n if (!trimmedName) {\n setError('請輸入分類名稱');\n return;\n }\n\n if (!Number.isInteger(parsedSortOrder)) {\n setError('排序必須是整數');\n return;\n }\n\n try {\n await onSubmit({\n description: description.trim() || null,\n isActive: modal?.record?.isActive ?? true,\n name: trimmedName,\n sortOrder: parsedSortOrder,\n });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !name.trim() }}\n confirmText={modal?.type === 'EDIT' ? '儲存' : '建立'}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={Boolean(modal)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={modal?.type === 'EDIT' ? '編輯分類' : '建立分類'}\n >\n <div className={styles.templateModalFields}>\n <BPMFormField label=\"分類名稱\" name=\"categoryName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:行政管理\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"排序\" name=\"categorySortOrder\">\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortOrder(event.target.value);\n setError(null);\n }}\n placeholder=\"0\"\n value={sortOrder}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"說明\" name=\"categoryDescription\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setDescription(event.target.value);\n setError(null);\n }}\n placeholder=\"補充分類用途\"\n value={description}\n />\n </BPMFormField>\n </div>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction CategoryStatusBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n return isActive ? (\n <Badge size=\"sub\" text=\"啟用\" variant=\"dot-success\" />\n ) : (\n <Badge size=\"sub\" text=\"停用\" variant=\"dot-inactive\" />\n );\n}\n\nfunction readCategoryStatusTabKey(activeKey: Key): CategoryStatusTabKey {\n if (activeKey === 'ACTIVE' || activeKey === 'INACTIVE') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction readCategoryStatus(\n status: CategoryStatusTabKey,\n): ApprovalTemplateCategoryStatus {\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"categories-AxxhqjLZ.cjs","names":["useState","useCallback","listApprovalTemplateCategoriesPage","useMemo","formatDateTime","Typography","updateApprovalTemplateCategory","createApprovalTemplateCategory","deleteApprovalTemplateCategory","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Tab","TabItem","Table","Modal","BPMFormField","Textarea","Badge","require_rolldown_runtime","require_format_date_time","require_bpm_form_field","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_template","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","categoryPageResult","readCategoryStatus","requestError","readErrorMessage","rows","category","columns","CategoryStatusBadge","record","handleSaveCategory","input","handleToggleCategory","handleConfirmDelete","tableActions","event","readCategoryStatusTabKey","activeKey","statusTab","page","pageSize","from","to","total","CategoryModal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","isActive","status"],"sources":["../../src/views/templates/templates.module.scss","../../src/views/templates/categories/TemplateCategoriesView.tsx"],"sourcesContent":[".templateFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n\n.templateModalFields {\n display: grid;\n gap: 16px;\n}\n","'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport {\n ApprovalTemplateCategoryRecord,\n ApprovalTemplateCategoryStatus,\n createApprovalTemplateCategory,\n deleteApprovalTemplateCategory,\n listApprovalTemplateCategoriesPage,\n updateApprovalTemplateCategory,\n} from '@rytass/bpm-core-client/template';\nimport styles from '../templates.module.scss';\n\nconst CATEGORY_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst CATEGORY_STATUS_TABS: readonly {\n readonly key: CategoryStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'ACTIVE', label: '啟用' },\n { key: 'INACTIVE', label: '停用' },\n];\ntype CategoryStatusTabKey = 'ACTIVE' | 'ALL' | 'INACTIVE';\n\ntype CategoryRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateCategoryRecord & {\n key: string;\n updatedAtLabel: string;\n }\n>;\n\ntype CategoryModalState = Readonly<{\n record: ApprovalTemplateCategoryRecord | null;\n type: 'CREATE' | 'EDIT';\n}>;\n\ntype DeleteConfirmationState = Readonly<{\n id: string;\n name: string;\n}>;\n\n\nexport function TemplateCategoriesView(): ReactElement {\n const [categories, setCategories] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n const [categoryPage, setCategoryPage] = useState(1);\n const [categoryPageSize, setCategoryPageSize] = useState(10);\n const [categoryStatus, setCategoryStatus] =\n useState<CategoryStatusTabKey>('ALL');\n const [categoryTotalCount, setCategoryTotalCount] = useState(0);\n const [deleteConfirmation, setDeleteConfirmation] =\n useState<DeleteConfirmationState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [modalState, setModalState] = useState<CategoryModalState | null>(null);\n const [saving, setSaving] = useState(false);\n const [searchText, setSearchText] = useState('');\n\n const refreshCategories = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const categoryPageResult = await listApprovalTemplateCategoriesPage({\n page: categoryPage,\n pageSize: categoryPageSize,\n searchText,\n status: readCategoryStatus(categoryStatus),\n });\n\n setCategories(categoryPageResult.categories);\n setCategoryTotalCount(categoryPageResult.totalCount);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [categoryPage, categoryPageSize, categoryStatus, searchText]);\n\n useEffect((): void => {\n void refreshCategories();\n }, [refreshCategories]);\n\n const rows = useMemo(\n (): CategoryRow[] =>\n categories.map((category) => ({\n ...category,\n key: category.id,\n updatedAtLabel: formatDateTime(category.updatedAt),\n })),\n [categories],\n );\n\n const columns = useMemo(\n (): TableColumn<CategoryRow>[] => [\n { dataIndex: 'name', key: 'name', title: '分類名稱', width: 180 },\n {\n key: 'status',\n render: (record: CategoryRow): ReactElement => (\n <CategoryStatusBadge isActive={record.isActive} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n dataIndex: 'sortOrder',\n key: 'sortOrder',\n title: '排序',\n width: 100,\n },\n {\n key: 'description',\n render: (record: CategoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.description || '無'}\n </Typography>\n ),\n title: '說明',\n width: 260,\n },\n {\n dataIndex: 'updatedAtLabel',\n key: 'updatedAtLabel',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function handleSaveCategory(input: CategoryFormInput): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n if (modalState?.type === 'EDIT' && modalState.record) {\n await updateApprovalTemplateCategory({\n ...input,\n id: modalState.record.id,\n });\n } else {\n await createApprovalTemplateCategory(input);\n }\n\n setModalState(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n throw requestError;\n } finally {\n setSaving(false);\n }\n }\n\n async function handleToggleCategory(\n record: ApprovalTemplateCategoryRecord,\n ): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n await updateApprovalTemplateCategory({\n description: record.description,\n id: record.id,\n isActive: !record.isActive,\n name: record.name,\n sortOrder: record.sortOrder,\n });\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handleConfirmDelete(): Promise<void> {\n if (!deleteConfirmation) {\n return;\n }\n\n setSaving(true);\n setError(null);\n\n try {\n await deleteApprovalTemplateCategory(deleteConfirmation.id);\n setDeleteConfirmation(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n const tableActions = useMemo(\n (): TableActions<CategoryRow> => ({\n render: (record): ReturnType<TableActions<CategoryRow>['render']> => [\n {\n name: '編輯',\n onClick: (): void => setModalState({ record, type: 'EDIT' }),\n },\n {\n name: record.isActive ? '停用' : '啟用',\n onClick: (): void => void handleToggleCategory(record),\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n {\n name: '刪除',\n onClick: (): void =>\n setDeleteConfirmation({ id: record.id, name: record.name }),\n variant: 'destructive-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [refreshCategories],\n );\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"維護簽核模板分類,供模板建立、篩選與列表標示使用。\"\n title=\"簽核模板分類\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n setModalState({ record: null, type: 'CREATE' })\n }\n variant=\"base-primary\"\n >\n 建立分類\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"categorySearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setCategoryPage(1);\n }}\n placeholder=\"關鍵字:搜尋分類名稱或說明\"\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={categoryStatus}\n onChange={(activeKey): void => {\n setCategoryStatus(readCategoryStatusTabKey(activeKey));\n setCategoryPage(1);\n }}\n >\n {CATEGORY_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading || saving}\n pagination={{\n current: categoryPage,\n onChange: (page): void => {\n setCategoryPage(page);\n },\n onChangePageSize: (pageSize): void => {\n setCategoryPage(1);\n setCategoryPageSize(pageSize);\n },\n pageSize: categoryPageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: CATEGORY_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: categoryTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n\n <CategoryModal\n loading={saving}\n modal={modalState}\n onClose={(): void => setModalState(null)}\n onSubmit={handleSaveCategory}\n />\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"刪除\"\n loading={saving}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setDeleteConfirmation(null)}\n onClose={(): void => setDeleteConfirmation(null)}\n onConfirm={(): void => void handleConfirmDelete()}\n open={Boolean(deleteConfirmation)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"已被模板使用的分類無法刪除,請改用「停用」。\"\n title=\"刪除分類\"\n >\n <Typography color=\"text-neutral\" variant=\"body\">\n 確定要刪除「{deleteConfirmation?.name ?? ''}」嗎?\n </Typography>\n </Modal>\n </>\n );\n}\n\ninterface CategoryFormInput {\n readonly description: string | null;\n readonly isActive: boolean;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nfunction CategoryModal({\n loading,\n modal,\n onClose,\n onSubmit,\n}: {\n readonly loading: boolean;\n readonly modal: CategoryModalState | null;\n readonly onClose: () => void;\n readonly onSubmit: (input: CategoryFormInput) => Promise<void>;\n}): ReactElement {\n const [description, setDescription] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [sortOrder, setSortOrder] = useState('0');\n\n useEffect((): void => {\n if (!modal) {\n return;\n }\n\n setDescription(modal.record?.description ?? '');\n setError(null);\n setName(modal.record?.name ?? '');\n setSortOrder(String(modal.record?.sortOrder ?? 0));\n }, [modal]);\n\n async function handleConfirm(): Promise<void> {\n const trimmedName = name.trim();\n const parsedSortOrder = Number(sortOrder);\n\n if (!trimmedName) {\n setError('請輸入分類名稱');\n return;\n }\n\n if (!Number.isInteger(parsedSortOrder)) {\n setError('排序必須是整數');\n return;\n }\n\n try {\n await onSubmit({\n description: description.trim() || null,\n isActive: modal?.record?.isActive ?? true,\n name: trimmedName,\n sortOrder: parsedSortOrder,\n });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !name.trim() }}\n confirmText={modal?.type === 'EDIT' ? '儲存' : '建立'}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={Boolean(modal)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={modal?.type === 'EDIT' ? '編輯分類' : '建立分類'}\n >\n <div className={styles.templateModalFields}>\n <BPMFormField label=\"分類名稱\" name=\"categoryName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:行政管理\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"排序\" name=\"categorySortOrder\">\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortOrder(event.target.value);\n setError(null);\n }}\n placeholder=\"0\"\n value={sortOrder}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"說明\" name=\"categoryDescription\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setDescription(event.target.value);\n setError(null);\n }}\n placeholder=\"補充分類用途\"\n value={description}\n />\n </BPMFormField>\n </div>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction CategoryStatusBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n return isActive ? (\n <Badge size=\"sub\" text=\"啟用\" variant=\"dot-success\" />\n ) : (\n <Badge size=\"sub\" text=\"停用\" variant=\"dot-inactive\" />\n );\n}\n\nfunction readCategoryStatusTabKey(activeKey: Key): CategoryStatusTabKey {\n if (activeKey === 'ACTIVE' || activeKey === 'INACTIVE') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction readCategoryStatus(\n status: CategoryStatusTabKey,\n): ApprovalTemplateCategoryStatus {\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
@@ -252,7 +252,7 @@ function N() {
|
|
|
252
252
|
showModalFooter: !0,
|
|
253
253
|
showModalHeader: !0,
|
|
254
254
|
size: "regular",
|
|
255
|
-
supportingText: "
|
|
255
|
+
supportingText: "已被模板使用的分類無法刪除,請改用「停用」。",
|
|
256
256
|
title: "刪除分類",
|
|
257
257
|
children: /* @__PURE__ */ w(x, {
|
|
258
258
|
color: "text-neutral",
|
|
@@ -373,4 +373,4 @@ function P(e) {
|
|
|
373
373
|
//#endregion
|
|
374
374
|
export { A as n, N as t };
|
|
375
375
|
|
|
376
|
-
//# sourceMappingURL=categories-
|
|
376
|
+
//# sourceMappingURL=categories-riC33J_j.js.map
|