@rytass/bpm-core-react 0.3.0 → 0.3.2

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 (184) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/README.md +13 -1
  3. package/dist/chunks/app-navigation-BSkMsEhy.js +268 -0
  4. package/dist/chunks/app-navigation-BSkMsEhy.js.map +1 -0
  5. package/dist/chunks/app-navigation-KnlJCUp1.cjs +2 -0
  6. package/dist/chunks/app-navigation-KnlJCUp1.cjs.map +1 -0
  7. package/dist/chunks/approval-instance-list-page-CVXgE2K3.cjs +2 -0
  8. package/dist/chunks/approval-instance-list-page-CVXgE2K3.cjs.map +1 -0
  9. package/dist/chunks/{approval-instance-list-page-BgE4vQw8.js → approval-instance-list-page-CqNdoZqx.js} +103 -99
  10. package/dist/chunks/approval-instance-list-page-CqNdoZqx.js.map +1 -0
  11. package/dist/chunks/builder-CMlJfQHE.cjs +3 -0
  12. package/dist/chunks/builder-CMlJfQHE.cjs.map +1 -0
  13. package/dist/chunks/{builder-Du_0apkh.js → builder-D950gct_.js} +436 -432
  14. package/dist/chunks/builder-D950gct_.js.map +1 -0
  15. package/dist/chunks/categories-5yEM3p3N.cjs +2 -0
  16. package/dist/chunks/categories-5yEM3p3N.cjs.map +1 -0
  17. package/dist/chunks/categories-BIpOG451.js +387 -0
  18. package/dist/chunks/categories-BIpOG451.js.map +1 -0
  19. package/dist/chunks/dashboard-page-1K_jQXQk.cjs +2 -0
  20. package/dist/chunks/dashboard-page-1K_jQXQk.cjs.map +1 -0
  21. package/dist/chunks/dashboard-page-R_T2OEiE.js +122 -0
  22. package/dist/chunks/dashboard-page-R_T2OEiE.js.map +1 -0
  23. package/dist/chunks/delegations-B2j-wNEO.js +646 -0
  24. package/dist/chunks/delegations-B2j-wNEO.js.map +1 -0
  25. package/dist/chunks/delegations-CsB9ozLu.cjs +2 -0
  26. package/dist/chunks/delegations-CsB9ozLu.cjs.map +1 -0
  27. package/dist/chunks/delegations-CvtwTXNP.cjs +2 -0
  28. package/dist/chunks/delegations-CvtwTXNP.cjs.map +1 -0
  29. package/dist/chunks/delegations-dKodb0WW.js +573 -0
  30. package/dist/chunks/delegations-dKodb0WW.js.map +1 -0
  31. package/dist/chunks/detail-BcGAqJ_R.js +1523 -0
  32. package/dist/chunks/detail-BcGAqJ_R.js.map +1 -0
  33. package/dist/chunks/detail-CqjqLd65.cjs +2 -0
  34. package/dist/chunks/detail-CqjqLd65.cjs.map +1 -0
  35. package/dist/chunks/{format-date-time-hKLVMxq4.cjs → format-date-time-26_pFvv4.cjs} +2 -2
  36. package/dist/chunks/{format-date-time-hKLVMxq4.cjs.map → format-date-time-26_pFvv4.cjs.map} +1 -1
  37. package/dist/chunks/notifications-2swRqDPF.js +198 -0
  38. package/dist/chunks/notifications-2swRqDPF.js.map +1 -0
  39. package/dist/chunks/notifications-BaYDebFt.cjs +2 -0
  40. package/dist/chunks/notifications-BaYDebFt.cjs.map +1 -0
  41. package/dist/chunks/{orgs-c29y74w2.js → orgs-CuHxxd_n.js} +665 -661
  42. package/dist/chunks/orgs-CuHxxd_n.js.map +1 -0
  43. package/dist/chunks/orgs-YMiVLNvL.cjs +2 -0
  44. package/dist/chunks/orgs-YMiVLNvL.cjs.map +1 -0
  45. package/dist/chunks/routes-config-2aKbWq2H.cjs +2 -0
  46. package/dist/chunks/routes-config-2aKbWq2H.cjs.map +1 -0
  47. package/dist/chunks/routes-config-dxahImVe.js +43 -0
  48. package/dist/chunks/routes-config-dxahImVe.js.map +1 -0
  49. package/dist/chunks/templates-DTkbSgFY.cjs +2 -0
  50. package/dist/chunks/templates-DTkbSgFY.cjs.map +1 -0
  51. package/dist/chunks/{templates-Dn9QHFSy.js → templates-DoDWM68t.js} +136 -132
  52. package/dist/chunks/templates-DoDWM68t.js.map +1 -0
  53. package/dist/chunks/users-3ySyUW4u.cjs +2 -0
  54. package/dist/chunks/users-3ySyUW4u.cjs.map +1 -0
  55. package/dist/chunks/users-sMfrSjRQ.js +219 -0
  56. package/dist/chunks/users-sMfrSjRQ.js.map +1 -0
  57. package/dist/components/app-navigation.d.ts +17 -10
  58. package/dist/index.cjs +1 -1
  59. package/dist/index.cjs.map +1 -1
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +101 -99
  62. package/dist/index.js.map +1 -1
  63. package/dist/lib/notification-drawer-provider.d.ts +1 -1
  64. package/dist/lib/notification-unread-provider.d.ts +1 -1
  65. package/dist/lib/providers.d.ts +1 -1
  66. package/dist/lib/routes-config.d.ts +96 -0
  67. package/dist/next/index.cjs +1 -1
  68. package/dist/next/index.cjs.map +1 -1
  69. package/dist/next/index.d.ts +1 -0
  70. package/dist/next/index.js +22 -21
  71. package/dist/next/index.js.map +1 -1
  72. package/dist/pages/admin/delegations/index.cjs +1 -1
  73. package/dist/pages/admin/delegations/index.js +1 -1
  74. package/dist/pages/admin/orgs/index.cjs +1 -1
  75. package/dist/pages/admin/orgs/index.js +1 -1
  76. package/dist/pages/admin/users/index.cjs +1 -1
  77. package/dist/pages/admin/users/index.js +1 -1
  78. package/dist/pages/delegations/index.cjs +1 -1
  79. package/dist/pages/delegations/index.js +1 -1
  80. package/dist/pages/forms/builder/index.cjs +1 -1
  81. package/dist/pages/forms/builder/index.js +1 -1
  82. package/dist/pages/instances/detail/index.cjs +1 -1
  83. package/dist/pages/instances/detail/index.js +1 -1
  84. package/dist/pages/settings/notifications/index.cjs +1 -1
  85. package/dist/pages/settings/notifications/index.js +1 -1
  86. package/dist/pages/templates/categories/index.cjs +1 -1
  87. package/dist/pages/templates/categories/index.js +1 -1
  88. package/dist/pages/templates/index.cjs +1 -1
  89. package/dist/pages/templates/index.js +1 -1
  90. package/dist/views/admin/delegations/index.cjs +1 -1
  91. package/dist/views/admin/delegations/index.js +1 -1
  92. package/dist/views/admin/index.cjs +1 -1
  93. package/dist/views/admin/index.js +3 -3
  94. package/dist/views/admin/orgs/index.cjs +1 -1
  95. package/dist/views/admin/orgs/index.js +1 -1
  96. package/dist/views/admin/users/index.cjs +1 -1
  97. package/dist/views/admin/users/index.js +1 -1
  98. package/dist/views/cc/index.cjs +1 -1
  99. package/dist/views/cc/index.js +1 -1
  100. package/dist/views/dashboard/index.cjs +1 -1
  101. package/dist/views/dashboard/index.js +1 -1
  102. package/dist/views/delegations/index.cjs +1 -1
  103. package/dist/views/delegations/index.js +1 -1
  104. package/dist/views/forms/builder/index.cjs +1 -1
  105. package/dist/views/forms/builder/index.js +1 -1
  106. package/dist/views/forms/index.cjs +1 -1
  107. package/dist/views/forms/index.cjs.map +1 -1
  108. package/dist/views/forms/index.js +84 -80
  109. package/dist/views/forms/index.js.map +1 -1
  110. package/dist/views/inbox/index.cjs +1 -1
  111. package/dist/views/inbox/index.cjs.map +1 -1
  112. package/dist/views/inbox/index.js +83 -79
  113. package/dist/views/inbox/index.js.map +1 -1
  114. package/dist/views/instances/detail/index.cjs +1 -1
  115. package/dist/views/instances/detail/index.js +1 -1
  116. package/dist/views/instances/new/index.cjs +1 -1
  117. package/dist/views/instances/new/index.cjs.map +1 -1
  118. package/dist/views/instances/new/index.js +107 -100
  119. package/dist/views/instances/new/index.js.map +1 -1
  120. package/dist/views/search/index.cjs +1 -1
  121. package/dist/views/search/index.js +1 -1
  122. package/dist/views/sent/index.cjs +1 -1
  123. package/dist/views/sent/index.js +1 -1
  124. package/dist/views/settings/index.cjs +1 -1
  125. package/dist/views/settings/index.js +1 -1
  126. package/dist/views/settings/notifications/index.cjs +1 -1
  127. package/dist/views/settings/notifications/index.js +1 -1
  128. package/dist/views/templates/categories/index.cjs +1 -1
  129. package/dist/views/templates/categories/index.js +1 -1
  130. package/dist/views/templates/designer/index.cjs +6 -6
  131. package/dist/views/templates/designer/index.cjs.map +1 -1
  132. package/dist/views/templates/designer/index.js +758 -754
  133. package/dist/views/templates/designer/index.js.map +1 -1
  134. package/dist/views/templates/index.cjs +1 -1
  135. package/dist/views/templates/index.js +2 -2
  136. package/dist/views/templates/versions/index.cjs +1 -1
  137. package/dist/views/templates/versions/index.cjs.map +1 -1
  138. package/dist/views/templates/versions/index.js +47 -43
  139. package/dist/views/templates/versions/index.js.map +1 -1
  140. package/package.json +3 -3
  141. package/dist/chunks/app-navigation-BRRFCkxZ.cjs +0 -2
  142. package/dist/chunks/app-navigation-BRRFCkxZ.cjs.map +0 -1
  143. package/dist/chunks/app-navigation-rxhpHCch.js +0 -262
  144. package/dist/chunks/app-navigation-rxhpHCch.js.map +0 -1
  145. package/dist/chunks/approval-instance-list-page-2vUWc5-c.cjs +0 -2
  146. package/dist/chunks/approval-instance-list-page-2vUWc5-c.cjs.map +0 -1
  147. package/dist/chunks/approval-instance-list-page-BgE4vQw8.js.map +0 -1
  148. package/dist/chunks/builder-B8X-m6C5.cjs +0 -3
  149. package/dist/chunks/builder-B8X-m6C5.cjs.map +0 -1
  150. package/dist/chunks/builder-Du_0apkh.js.map +0 -1
  151. package/dist/chunks/categories-DG4k7S8V.js +0 -383
  152. package/dist/chunks/categories-DG4k7S8V.js.map +0 -1
  153. package/dist/chunks/categories-DshBQG33.cjs +0 -2
  154. package/dist/chunks/categories-DshBQG33.cjs.map +0 -1
  155. package/dist/chunks/dashboard-page-CTBwpu_D.js +0 -114
  156. package/dist/chunks/dashboard-page-CTBwpu_D.js.map +0 -1
  157. package/dist/chunks/dashboard-page-DcDiWQp2.cjs +0 -2
  158. package/dist/chunks/dashboard-page-DcDiWQp2.cjs.map +0 -1
  159. package/dist/chunks/delegations-BAZQbElH.js +0 -642
  160. package/dist/chunks/delegations-BAZQbElH.js.map +0 -1
  161. package/dist/chunks/delegations-DzrckrPp.js +0 -569
  162. package/dist/chunks/delegations-DzrckrPp.js.map +0 -1
  163. package/dist/chunks/delegations-Z8hTajLj.cjs +0 -2
  164. package/dist/chunks/delegations-Z8hTajLj.cjs.map +0 -1
  165. package/dist/chunks/delegations-hb9JoVZe.cjs +0 -2
  166. package/dist/chunks/delegations-hb9JoVZe.cjs.map +0 -1
  167. package/dist/chunks/detail-DilI0PPe.js +0 -1519
  168. package/dist/chunks/detail-DilI0PPe.js.map +0 -1
  169. package/dist/chunks/detail-DuRg3Y7b.cjs +0 -2
  170. package/dist/chunks/detail-DuRg3Y7b.cjs.map +0 -1
  171. package/dist/chunks/notifications-B2Lk3grg.js +0 -194
  172. package/dist/chunks/notifications-B2Lk3grg.js.map +0 -1
  173. package/dist/chunks/notifications-C8ADhnxF.cjs +0 -2
  174. package/dist/chunks/notifications-C8ADhnxF.cjs.map +0 -1
  175. package/dist/chunks/orgs-CGv3VNDR.cjs +0 -2
  176. package/dist/chunks/orgs-CGv3VNDR.cjs.map +0 -1
  177. package/dist/chunks/orgs-c29y74w2.js.map +0 -1
  178. package/dist/chunks/templates-Cd0WFheA.cjs +0 -2
  179. package/dist/chunks/templates-Cd0WFheA.cjs.map +0 -1
  180. package/dist/chunks/templates-Dn9QHFSy.js.map +0 -1
  181. package/dist/chunks/users-B-trMu0E.cjs +0 -2
  182. package/dist/chunks/users-B-trMu0E.cjs.map +0 -1
  183. package/dist/chunks/users-itVXXRj7.js +0 -215
  184. package/dist/chunks/users-itVXXRj7.js.map +0 -1
@@ -1,11 +1,12 @@
1
1
  "use client";
2
2
  import { a as e } from "./auth-provider-Bnox5gsx.js";
3
3
  import { t } from "./format-date-time-CB-LxzqT.js";
4
- import { t as n } from "./app-navigation-rxhpHCch.js";
5
- import { t as r } from "./bpm-form-field-Cao0rMol.js";
6
- import { n as i } from "./categories-DG4k7S8V.js";
7
- import { useCallback as a, useEffect as o, useMemo as s, useState as c } from "react";
8
- import { Badge as l, Button as u, Filter as d, FilterArea as f, FilterLine as p, FormField as m, Input as h, Layout as g, Modal as _, PageHeader as v, Section as y, SectionGroup as b, Select as x, Tab as ee, TabItem as S, Table as C, Typography as w } from "@mezzanine-ui/react";
4
+ import { t as n } from "./app-navigation-BSkMsEhy.js";
5
+ import { r } from "./routes-config-dxahImVe.js";
6
+ import { t as i } from "./bpm-form-field-Cao0rMol.js";
7
+ import { n as a } from "./categories-BIpOG451.js";
8
+ import { useCallback as o, useEffect as s, useMemo as c, useState as l } from "react";
9
+ import { Badge as u, Button as d, Filter as f, FilterArea as p, FilterLine as m, FormField as h, Input as g, Modal as _, PageHeader as v, Section as y, SectionGroup as b, Select as x, Tab as ee, TabItem as S, Table as C, Typography as w } from "@mezzanine-ui/react";
9
10
  import { Fragment as te, jsx as T, jsxs as E } from "react/jsx-runtime";
10
11
  import { listLaunchableTemplates as ne } from "@rytass/bpm-core-client/workflow";
11
12
  import { PlusIcon as re } from "@mezzanine-ui/icons";
@@ -13,14 +14,14 @@ import ie from "@mezzanine-ui/react/ContentHeader";
13
14
  import { FormFieldLayout as D } from "@mezzanine-ui/core/form";
14
15
  import { createApprovalTemplate as ae, listApprovalTemplateCategoriesPage as oe, listApprovalTemplatesPage as se } from "@rytass/bpm-core-client/template";
15
16
  //#region src/views/templates/template-name-modal.tsx
16
- function ce({ confirmText: e, categoryOptions: t, initialName: n, loading: i, onClose: a, onSubmit: s, open: l, title: u }) {
17
- let [d, f] = c(n), [p, m] = c(t[0] ?? k), [g, v] = c(null), y = d.trim();
18
- o(() => {
19
- l && (f(n), m(t[0] ?? k), v(null));
17
+ function ce({ confirmText: e, categoryOptions: t, initialName: n, loading: r, onClose: a, onSubmit: o, open: c, title: u }) {
18
+ let [d, f] = l(n), [p, m] = l(t[0] ?? k), [h, v] = l(null), y = d.trim();
19
+ s(() => {
20
+ c && (f(n), m(t[0] ?? k), v(null));
20
21
  }, [
21
22
  t,
22
23
  n,
23
- l
24
+ c
24
25
  ]);
25
26
  async function b() {
26
27
  if (!y) {
@@ -28,7 +29,7 @@ function ce({ confirmText: e, categoryOptions: t, initialName: n, loading: i, on
28
29
  return;
29
30
  }
30
31
  try {
31
- await s({
32
+ await o({
32
33
  categoryId: p.categoryId,
33
34
  name: y
34
35
  });
@@ -40,22 +41,22 @@ function ce({ confirmText: e, categoryOptions: t, initialName: n, loading: i, on
40
41
  cancelText: "取消",
41
42
  confirmButtonProps: { disabled: !y },
42
43
  confirmText: e,
43
- loading: i,
44
+ loading: r,
44
45
  modalType: "standard",
45
46
  onCancel: a,
46
47
  onClose: a,
47
48
  onConfirm: () => void b(),
48
- open: l,
49
+ open: c,
49
50
  showModalFooter: !0,
50
51
  showModalHeader: !0,
51
52
  size: "narrow",
52
53
  title: u,
53
54
  children: [
54
- /* @__PURE__ */ T(r, {
55
+ /* @__PURE__ */ T(i, {
55
56
  label: "模板名稱",
56
57
  name: "templateName",
57
58
  required: !0,
58
- children: /* @__PURE__ */ T(h, {
59
+ children: /* @__PURE__ */ T(g, {
59
60
  autoFocus: !0,
60
61
  fullWidth: !0,
61
62
  onChange: (e) => {
@@ -66,7 +67,7 @@ function ce({ confirmText: e, categoryOptions: t, initialName: n, loading: i, on
66
67
  variant: "base"
67
68
  })
68
69
  }),
69
- /* @__PURE__ */ T(r, {
70
+ /* @__PURE__ */ T(i, {
70
71
  label: "分類",
71
72
  name: "templateCategory",
72
73
  children: /* @__PURE__ */ T(x, {
@@ -80,10 +81,10 @@ function ce({ confirmText: e, categoryOptions: t, initialName: n, loading: i, on
80
81
  value: p
81
82
  })
82
83
  }),
83
- g ? /* @__PURE__ */ T(w, {
84
+ h ? /* @__PURE__ */ T(w, {
84
85
  color: "text-error",
85
86
  variant: "body",
86
- children: g
87
+ children: h
87
88
  }) : null
88
89
  ]
89
90
  });
@@ -124,13 +125,13 @@ var le = [
124
125
  label: "草稿"
125
126
  }
126
127
  ], de = 100;
127
- function M({ activeHref: r = "/templates" } = {}) {
128
- let l = e(), [_, O] = c([]), [A, j] = c(P), [M, z] = c([]), [B, he] = c(/* @__PURE__ */ new Set()), [ge, V] = c(!1), [H, U] = c(!1), [W, G] = c(null), [_e, K] = c(!0), [q, J] = c(1), [Y, ve] = c(10), [X, ye] = c(""), [Z, be] = c("ALL"), [xe, Q] = c(0), $ = a(async () => {
128
+ function M({ activeHref: i } = {}) {
129
+ let u = e(), _ = r(), O = i ?? _.templates(), [A, j] = l([]), [M, R] = l(N), [z, ge] = l([]), [B, _e] = l(/* @__PURE__ */ new Set()), [ve, V] = l(!1), [H, U] = l(!1), [W, G] = l(null), [ye, K] = l(!0), [q, J] = l(1), [Y, be] = l(10), [X, xe] = l(""), [Z, Se] = l("ALL"), [Q, Ce] = l(0), $ = o(async () => {
129
130
  K(!0), G(null);
130
131
  try {
131
132
  let [e, t, n] = await Promise.all([
132
133
  se({
133
- categoryId: A.categoryId,
134
+ categoryId: M.categoryId,
134
135
  page: q,
135
136
  pageSize: Y,
136
137
  searchText: X,
@@ -144,29 +145,29 @@ function M({ activeHref: r = "/templates" } = {}) {
144
145
  status: "ACTIVE"
145
146
  })
146
147
  ]);
147
- z([...n.categories.map(F)]), O(e.templates), Q(e.totalCount), he(new Set(t.map((e) => e.id)));
148
+ ge([...n.categories.map(P)]), j(e.templates), Ce(e.totalCount), _e(new Set(t.map((e) => e.id)));
148
149
  } catch (e) {
149
150
  G(fe(e));
150
151
  } finally {
151
152
  K(!1);
152
153
  }
153
154
  }, [
154
- A,
155
+ M,
155
156
  q,
156
157
  Y,
157
158
  X,
158
159
  Z
159
160
  ]);
160
- o(() => {
161
+ s(() => {
161
162
  $();
162
163
  }, [$]);
163
- let Se = s(() => _.map((e) => ({
164
+ let we = c(() => A.map((e) => ({
164
165
  ...e,
165
- categoryLabel: R(e),
166
+ categoryLabel: L(e),
166
167
  key: e.id,
167
168
  status: e.currentVersionId ? "PUBLISHED" : "DRAFT",
168
169
  updatedAt: t(e.updatedAt)
169
- })), [_]), Ce = s(() => [
170
+ })), [A]), Te = c(() => [
170
171
  {
171
172
  dataIndex: "name",
172
173
  key: "name",
@@ -181,7 +182,7 @@ function M({ activeHref: r = "/templates" } = {}) {
181
182
  },
182
183
  {
183
184
  key: "category",
184
- render: (e) => /* @__PURE__ */ T(N, { record: e }),
185
+ render: (e) => /* @__PURE__ */ T(he, { record: e }),
185
186
  title: "分類",
186
187
  width: 160
187
188
  },
@@ -191,132 +192,135 @@ function M({ activeHref: r = "/templates" } = {}) {
191
192
  title: "更新時間",
192
193
  width: 220
193
194
  }
194
- ], []), we = s(() => ({
195
+ ], []), Ee = c(() => ({
195
196
  render: (e) => [
196
197
  {
197
198
  disabled: (e) => !B.has(e.id),
198
199
  name: "發起",
199
- onClick: () => l.push(`/instances/new?templateId=${e.id}`),
200
+ onClick: () => u.push(_.caseNew(e.id)),
200
201
  variant: "base-primary"
201
202
  },
202
203
  {
203
204
  name: "設計",
204
- onClick: () => l.push(`/templates/${e.id}/designer`)
205
+ onClick: () => u.push(_.templateDesigner(e.id))
205
206
  },
206
207
  {
207
208
  name: "版本",
208
- onClick: () => l.push(`/templates/${e.id}/versions`)
209
+ onClick: () => u.push(_.templateVersions(e.id))
209
210
  }
210
211
  ],
211
212
  variant: "base-secondary",
212
213
  width: 192
213
- }), [B, l]);
214
- async function Te({ categoryId: e, name: t }) {
214
+ }), [B, u]);
215
+ async function De({ categoryId: e, name: t }) {
215
216
  U(!0), G(null);
216
217
  try {
217
218
  let n = await ae({
218
219
  categoryId: e,
219
220
  name: t
220
221
  });
221
- V(!1), l.push(`/templates/${n}/designer`);
222
+ V(!1), u.push(_.templateDesigner(n));
222
223
  } finally {
223
224
  U(!1);
224
225
  }
225
226
  }
226
- return /* @__PURE__ */ E(te, { children: [/* @__PURE__ */ E(g, { children: [/* @__PURE__ */ T(n, { activeHref: r }), /* @__PURE__ */ E(g.Main, { children: [/* @__PURE__ */ T(v, { children: /* @__PURE__ */ T(ie, {
227
- description: "建立流程模板、維護草稿與發布版本。",
228
- title: "簽核模板",
229
- children: /* @__PURE__ */ T(u, {
230
- disabled: H,
231
- icon: re,
232
- iconType: "leading",
233
- onClick: () => V(!0),
234
- variant: "base-primary",
235
- children: "建立模板"
236
- })
237
- }) }), /* @__PURE__ */ T(b, { children: /* @__PURE__ */ E(y, {
238
- filterArea: /* @__PURE__ */ T(f, {
239
- className: i.templateFilterArea,
240
- size: "sub",
241
- children: /* @__PURE__ */ E(p, { children: [/* @__PURE__ */ T(d, {
242
- span: 3,
243
- children: /* @__PURE__ */ T(m, {
244
- fullWidth: !0,
245
- layout: D.VERTICAL,
246
- name: "templateSearchText",
227
+ return /* @__PURE__ */ E(te, { children: [/* @__PURE__ */ E(n, {
228
+ activeHref: O,
229
+ children: [/* @__PURE__ */ T(v, { children: /* @__PURE__ */ T(ie, {
230
+ description: "建立流程模板、維護草稿與發布版本。",
231
+ title: "簽核模板",
232
+ children: /* @__PURE__ */ T(d, {
233
+ disabled: H,
234
+ icon: re,
235
+ iconType: "leading",
236
+ onClick: () => V(!0),
237
+ variant: "base-primary",
238
+ children: "建立模板"
239
+ })
240
+ }) }), /* @__PURE__ */ T(b, { children: /* @__PURE__ */ E(y, {
241
+ filterArea: /* @__PURE__ */ T(p, {
242
+ className: a.templateFilterArea,
243
+ size: "sub",
244
+ children: /* @__PURE__ */ E(m, { children: [/* @__PURE__ */ T(f, {
245
+ span: 3,
247
246
  children: /* @__PURE__ */ T(h, {
248
247
  fullWidth: !0,
249
- onChange: (e) => {
250
- ye(e.target.value), J(1);
251
- },
252
- placeholder: "關鍵字:搜尋模板名稱、分類或描述",
253
- size: "sub",
254
- value: X,
255
- variant: "base"
248
+ layout: D.VERTICAL,
249
+ name: "templateSearchText",
250
+ children: /* @__PURE__ */ T(g, {
251
+ fullWidth: !0,
252
+ onChange: (e) => {
253
+ xe(e.target.value), J(1);
254
+ },
255
+ placeholder: "關鍵字:搜尋模板名稱、分類或描述",
256
+ size: "sub",
257
+ value: X,
258
+ variant: "base"
259
+ })
256
260
  })
257
- })
258
- }), /* @__PURE__ */ T(d, {
259
- span: 2,
260
- children: /* @__PURE__ */ T(m, {
261
- fullWidth: !0,
262
- layout: D.VERTICAL,
263
- name: "templateCategoryFilter",
264
- children: /* @__PURE__ */ T(x, {
265
- clearable: !1,
261
+ }), /* @__PURE__ */ T(f, {
262
+ span: 2,
263
+ children: /* @__PURE__ */ T(h, {
266
264
  fullWidth: !0,
267
- onChange: (e) => {
268
- j(I(e, M)), J(1);
269
- },
270
- options: [P, ...M],
271
- placeholder: "分類",
272
- renderValue: (e) => `分類:${L(e)}`,
273
- size: "sub",
274
- value: A
265
+ layout: D.VERTICAL,
266
+ name: "templateCategoryFilter",
267
+ children: /* @__PURE__ */ T(x, {
268
+ clearable: !1,
269
+ fullWidth: !0,
270
+ onChange: (e) => {
271
+ R(F(e, z)), J(1);
272
+ },
273
+ options: [N, ...z],
274
+ placeholder: "分類",
275
+ renderValue: (e) => `分類:${I(e)}`,
276
+ size: "sub",
277
+ value: M
278
+ })
275
279
  })
276
- })
277
- })] })
278
- }),
279
- tab: /* @__PURE__ */ T(ee, {
280
- activeKey: Z,
281
- onChange: (e) => {
282
- be(pe(e)), J(1);
283
- },
284
- children: ue.map((e) => /* @__PURE__ */ T(S, { children: e.label }, e.key))
285
- }),
286
- children: [W ? /* @__PURE__ */ T(w, {
287
- color: "text-error",
288
- variant: "body",
289
- children: W
290
- }) : null, /* @__PURE__ */ T(C, {
291
- actions: we,
292
- columns: Ce,
293
- dataSource: Se,
294
- fullWidth: !0,
295
- loading: _e,
296
- pagination: {
297
- current: q,
280
+ })] })
281
+ }),
282
+ tab: /* @__PURE__ */ T(ee, {
283
+ activeKey: Z,
298
284
  onChange: (e) => {
299
- J(e);
300
- },
301
- onChangePageSize: (e) => {
302
- J(1), ve(e);
285
+ Se(pe(e)), J(1);
303
286
  },
304
- pageSize: Y,
305
- pageSizeLabel: "每頁筆數",
306
- pageSizeOptions: le,
307
- renderResultSummary: (e, t, n) => `顯示 ${e}-${t} 筆,共 ${n} 筆`,
308
- showPageSizeOptions: !0,
309
- total: xe
310
- }
311
- })]
312
- }) })] })] }), /* @__PURE__ */ T(ce, {
313
- categoryOptions: [k, ...M],
287
+ children: ue.map((e) => /* @__PURE__ */ T(S, { children: e.label }, e.key))
288
+ }),
289
+ children: [W ? /* @__PURE__ */ T(w, {
290
+ color: "text-error",
291
+ variant: "body",
292
+ children: W
293
+ }) : null, /* @__PURE__ */ T(C, {
294
+ actions: Ee,
295
+ columns: Te,
296
+ dataSource: we,
297
+ fullWidth: !0,
298
+ loading: ye,
299
+ pagination: {
300
+ current: q,
301
+ onChange: (e) => {
302
+ J(e);
303
+ },
304
+ onChangePageSize: (e) => {
305
+ J(1), be(e);
306
+ },
307
+ pageSize: Y,
308
+ pageSizeLabel: "每頁筆數",
309
+ pageSizeOptions: le,
310
+ renderResultSummary: (e, t, n) => `顯示 ${e}-${t} 筆,共 ${n} 筆`,
311
+ showPageSizeOptions: !0,
312
+ total: Q
313
+ }
314
+ })]
315
+ }) })]
316
+ }), /* @__PURE__ */ T(ce, {
317
+ categoryOptions: [k, ...z],
314
318
  confirmText: "建立",
315
319
  initialName: "",
316
320
  loading: H,
317
321
  onClose: () => V(!1),
318
- onSubmit: Te,
319
- open: ge,
322
+ onSubmit: De,
323
+ open: ve,
320
324
  title: "建立簽核模板"
321
325
  })] });
322
326
  }
@@ -327,18 +331,18 @@ function pe(e) {
327
331
  return e === "PUBLISHED" || e === "DRAFT" ? e : "ALL";
328
332
  }
329
333
  function me({ status: e }) {
330
- return e === "PUBLISHED" ? /* @__PURE__ */ T(l, {
334
+ return e === "PUBLISHED" ? /* @__PURE__ */ T(u, {
331
335
  size: "sub",
332
336
  text: "已發布",
333
337
  variant: "dot-success"
334
- }) : /* @__PURE__ */ T(l, {
338
+ }) : /* @__PURE__ */ T(u, {
335
339
  size: "sub",
336
340
  text: "草稿",
337
341
  variant: "dot-inactive"
338
342
  });
339
343
  }
340
- function N({ record: e }) {
341
- return e.categoryDetail?.isActive === !1 ? /* @__PURE__ */ T(l, {
344
+ function he({ record: e }) {
345
+ return e.categoryDetail?.isActive === !1 ? /* @__PURE__ */ T(u, {
342
346
  size: "sub",
343
347
  text: `${e.categoryLabel}(停用)`,
344
348
  variant: "dot-inactive"
@@ -348,33 +352,33 @@ function N({ record: e }) {
348
352
  children: e.categoryLabel
349
353
  });
350
354
  }
351
- var P = {
355
+ var N = {
352
356
  categoryId: null,
353
357
  id: "ALL_CATEGORIES",
354
358
  name: "全部分類"
355
359
  };
356
- function F(e) {
360
+ function P(e) {
357
361
  return {
358
362
  categoryId: e.id,
359
363
  id: e.id,
360
364
  name: e.name
361
365
  };
362
366
  }
363
- function I(e, t) {
364
- if (!z(e)) return P;
367
+ function F(e, t) {
368
+ if (!R(e)) return N;
365
369
  let n = typeof e.id == "string" ? e.id : null;
366
- return n === P.id ? P : t.find((e) => e.id === n) ?? P;
370
+ return n === N.id ? N : t.find((e) => e.id === n) ?? N;
367
371
  }
368
- function L(e) {
369
- return Array.isArray(e) || !z(e) ? P.name : typeof e.name == "string" ? e.name : P.name;
372
+ function I(e) {
373
+ return Array.isArray(e) || !R(e) ? N.name : typeof e.name == "string" ? e.name : N.name;
370
374
  }
371
- function R(e) {
375
+ function L(e) {
372
376
  return e.categoryDetail?.name ?? e.category ?? "未分類";
373
377
  }
374
- function z(e) {
378
+ function R(e) {
375
379
  return typeof e == "object" && !!e;
376
380
  }
377
381
  //#endregion
378
382
  export { M as t };
379
383
 
380
- //# sourceMappingURL=templates-Dn9QHFSy.js.map
384
+ //# sourceMappingURL=templates-DoDWM68t.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates-DoDWM68t.js","names":[],"sources":["../../src/views/templates/template-name-modal.tsx","../../src/views/templates/TemplatesView.tsx"],"sourcesContent":["'use client';\n\nimport { ChangeEvent, ReactElement, useEffect, useState } from 'react';\nimport { Input, Modal, Select, Typography } from '@mezzanine-ui/react';\nimport { BPMFormField } from '../../components/bpm-form-field';\n\nexport interface TemplateCategoryOption {\n readonly categoryId: string | null;\n readonly id: string;\n readonly name: string;\n}\n\ninterface TemplateNameModalProps {\n readonly confirmText: string;\n readonly categoryOptions: readonly TemplateCategoryOption[];\n readonly initialName: string;\n readonly loading: boolean;\n readonly onClose: () => void;\n readonly onSubmit: (input: {\n readonly categoryId: string | null;\n readonly name: string;\n }) => Promise<void>;\n readonly open: boolean;\n readonly title: string;\n}\n\nexport function TemplateNameModal({\n confirmText,\n categoryOptions,\n initialName,\n loading,\n onClose,\n onSubmit,\n open,\n title,\n}: TemplateNameModalProps): ReactElement {\n const [name, setName] = useState(initialName);\n const [category, setCategory] = useState<TemplateCategoryOption>(\n categoryOptions[0] ?? UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION,\n );\n const [error, setError] = useState<string | null>(null);\n const trimmedName = name.trim();\n\n useEffect((): void => {\n if (!open) {\n return;\n }\n\n setName(initialName);\n setCategory(categoryOptions[0] ?? UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION);\n setError(null);\n }, [categoryOptions, initialName, open]);\n\n async function handleConfirm(): Promise<void> {\n if (!trimmedName) {\n setError('請輸入模板名稱');\n return;\n }\n\n try {\n await onSubmit({ categoryId: category.categoryId, name: trimmedName });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !trimmedName }}\n confirmText={confirmText}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={open}\n showModalFooter\n showModalHeader\n size=\"narrow\"\n title={title}\n >\n <BPMFormField label=\"模板名稱\" name=\"templateName\" 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=\"templateCategory\">\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setCategory(readCategoryOption(option, categoryOptions));\n setError(null);\n }}\n options={[...categoryOptions]}\n placeholder=\"選擇分類\"\n value={category}\n />\n </BPMFormField>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nexport const UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION: TemplateCategoryOption = {\n categoryId: null,\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nfunction readCategoryOption(\n value: unknown,\n options: readonly TemplateCategoryOption[],\n): TemplateCategoryOption {\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION;\n }\n\n const id = typeof value.id === 'string' ? value.id : null;\n\n return (\n options.find((option) => option.id === id) ??\n UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION\n );\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\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 PageHeader,\n Section,\n SectionGroup,\n Select,\n Tab,\n TabItem,\n Table,\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 styles from './templates.module.scss';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { AppLayout } from '../../components/app-navigation';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\nimport {\n TemplateCategoryOption,\n TemplateNameModal,\n UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION,\n} from './template-name-modal';\nimport {\n ApprovalTemplateListStatus,\n ApprovalTemplateRecord,\n ApprovalTemplateCategoryRecord,\n createApprovalTemplate,\n listApprovalTemplateCategoriesPage,\n listApprovalTemplatesPage,\n} from '@rytass/bpm-core-client/template';\nimport { listLaunchableTemplates } from '@rytass/bpm-core-client/workflow';\n\nconst TEMPLATE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst TEMPLATE_STATUS_TABS: readonly {\n readonly key: TemplateStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'PUBLISHED', label: '已發布' },\n { key: 'DRAFT', label: '草稿' },\n];\n\nconst TEMPLATE_CATEGORY_PAGE_SIZE = 100;\n\ntype TemplateStatusTabKey = 'ALL' | ApprovalTemplateListStatus;\n\ntype TemplateRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateRecord & {\n categoryLabel: string;\n key: string;\n status: ApprovalTemplateListStatus;\n }\n>;\n\nexport interface TemplatesViewProps {\n readonly activeHref?: string;\n}\n\nexport function TemplatesView({\n activeHref,\n}: TemplatesViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const resolvedActiveHref = activeHref ?? routes.templates();\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [categoryFilter, setCategoryFilter] = useState<TemplateCategoryOption>(\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n );\n const [categoryOptions, setCategoryOptions] = useState<\n readonly TemplateCategoryOption[]\n >([]);\n const [launchableTemplateIds, setLaunchableTemplateIds] = useState<\n ReadonlySet<string>\n >(new Set());\n const [createModalOpen, setCreateModalOpen] = useState(false);\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [templatePage, setTemplatePage] = useState(1);\n const [templatePageSize, setTemplatePageSize] = useState(10);\n const [templateSearchText, setTemplateSearchText] = useState('');\n const [templateStatus, setTemplateStatus] =\n useState<TemplateStatusTabKey>('ALL');\n const [templateTotalCount, setTemplateTotalCount] = useState(0);\n\n const refreshTemplates = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const [\n templatePageResult,\n nextLaunchableTemplates,\n activeCategoryPageResult,\n ] = await Promise.all([\n listApprovalTemplatesPage({\n categoryId: categoryFilter.categoryId,\n page: templatePage,\n pageSize: templatePageSize,\n searchText: templateSearchText,\n status: templateStatus === 'ALL' ? null : templateStatus,\n }),\n listLaunchableTemplates(),\n listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: TEMPLATE_CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n }),\n ]);\n\n setCategoryOptions([\n ...activeCategoryPageResult.categories.map(readCategoryOption),\n ]);\n setTemplates(templatePageResult.templates);\n setTemplateTotalCount(templatePageResult.totalCount);\n setLaunchableTemplateIds(\n new Set(nextLaunchableTemplates.map((template) => template.id)),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [\n categoryFilter,\n templatePage,\n templatePageSize,\n templateSearchText,\n templateStatus,\n ]);\n\n useEffect((): void => {\n void refreshTemplates();\n }, [refreshTemplates]);\n\n const rows = useMemo(\n (): TemplateRow[] =>\n templates.map((template) => ({\n ...template,\n categoryLabel: readTemplateCategoryLabel(template),\n key: template.id,\n status: template.currentVersionId ? 'PUBLISHED' : 'DRAFT',\n updatedAt: formatDateTime(template.updatedAt),\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<TemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 220 },\n {\n key: 'status',\n render: (record: TemplateRow): ReactElement => (\n <TemplateStatusBadge status={record.status} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'category',\n render: (record: TemplateRow): ReactElement => (\n <TemplateCategoryLabel record={record} />\n ),\n title: '分類',\n width: 160,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<TemplateRow> => ({\n render: (record): ReturnType<TableActions<TemplateRow>['render']> => [\n {\n disabled: (template): boolean =>\n !launchableTemplateIds.has(template.id),\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n {\n name: '設計',\n onClick: (): void => router.push(routes.templateDesigner(record.id)),\n },\n {\n name: '版本',\n onClick: (): void => router.push(routes.templateVersions(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [launchableTemplateIds, router],\n );\n\n async function handleCreateTemplate({\n categoryId,\n name,\n }: {\n readonly categoryId: string | null;\n readonly name: string;\n }): Promise<void> {\n setCreating(true);\n setError(null);\n\n try {\n const templateId = await createApprovalTemplate({ categoryId, name });\n setCreateModalOpen(false);\n router.push(routes.templateDesigner(templateId));\n } finally {\n setCreating(false);\n }\n }\n\n return (\n <>\n <AppLayout activeHref={resolvedActiveHref}>\n <PageHeader>\n <ContentHeader\n description=\"建立流程模板、維護草稿與發布版本。\"\n title=\"簽核模板\"\n >\n <Button\n disabled={creating}\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => setCreateModalOpen(true)}\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=\"templateSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setTemplateSearchText(event.target.value);\n setTemplatePage(1);\n }}\n placeholder=\"關鍵字:搜尋模板名稱、分類或描述\"\n size=\"sub\"\n value={templateSearchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateCategoryFilter\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setCategoryFilter(\n readCategoryFilterOption(option, categoryOptions),\n );\n setTemplatePage(1);\n }}\n options={[\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n ...categoryOptions,\n ]}\n placeholder=\"分類\"\n renderValue={(value): string =>\n `分類:${readTemplateCategoryFilterLabel(value)}`\n }\n size=\"sub\"\n value={categoryFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={templateStatus}\n onChange={(activeKey): void => {\n setTemplateStatus(readTemplateStatusTabKey(activeKey));\n setTemplatePage(1);\n }}\n >\n {TEMPLATE_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}\n pagination={{\n current: templatePage,\n onChange: (page): void => {\n setTemplatePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setTemplatePage(1);\n setTemplatePageSize(pageSize);\n },\n pageSize: templatePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: TEMPLATE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: templateTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </AppLayout>\n\n <TemplateNameModal\n categoryOptions={[\n UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION,\n ...categoryOptions,\n ]}\n confirmText=\"建立\"\n initialName=\"\"\n loading={creating}\n onClose={(): void => setCreateModalOpen(false)}\n onSubmit={handleCreateTemplate}\n open={createModalOpen}\n title=\"建立簽核模板\"\n />\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nfunction readTemplateStatusTabKey(activeKey: Key): TemplateStatusTabKey {\n if (activeKey === 'PUBLISHED' || activeKey === 'DRAFT') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction TemplateStatusBadge({\n status,\n}: {\n readonly status: ApprovalTemplateListStatus;\n}): ReactElement {\n if (status === 'PUBLISHED') {\n return <Badge size=\"sub\" text=\"已發布\" variant=\"dot-success\" />;\n }\n\n return <Badge size=\"sub\" text=\"草稿\" variant=\"dot-inactive\" />;\n}\n\nfunction TemplateCategoryLabel({\n record,\n}: {\n readonly record: TemplateRow;\n}): ReactElement {\n if (record.categoryDetail?.isActive === false) {\n return (\n <Badge\n size=\"sub\"\n text={`${record.categoryLabel}(停用)`}\n variant=\"dot-inactive\"\n />\n );\n }\n\n return (\n <Typography component=\"span\" variant=\"body\">\n {record.categoryLabel}\n </Typography>\n );\n}\n\nconst UNCATEGORIZED_TEMPLATE_FILTER_OPTION: TemplateCategoryOption = {\n categoryId: null,\n id: 'ALL_CATEGORIES',\n name: '全部分類',\n};\n\nfunction readCategoryOption(\n category: ApprovalTemplateCategoryRecord,\n): TemplateCategoryOption {\n return {\n categoryId: category.id,\n id: category.id,\n name: category.name,\n };\n}\n\nfunction readCategoryFilterOption(\n value: unknown,\n options: readonly TemplateCategoryOption[],\n): TemplateCategoryOption {\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n const id = typeof value.id === 'string' ? value.id : null;\n\n if (id === UNCATEGORIZED_TEMPLATE_FILTER_OPTION.id) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n return (\n options.find((option) => option.id === id) ??\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION\n );\n}\n\nfunction readTemplateCategoryFilterLabel(value: unknown): string {\n if (Array.isArray(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n return typeof value.name === 'string'\n ? value.name\n : UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n}\n\nfunction readTemplateCategoryLabel(template: ApprovalTemplateRecord): string {\n return template.categoryDetail?.name ?? template.category ?? '未分類';\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,SAAgB,GAAkB,EAChC,gBACA,oBACA,gBACA,YACA,YACA,aACA,SACA,YACuC;CACvC,IAAM,CAAC,GAAM,KAAW,EAAS,CAAW,GACtC,CAAC,GAAU,KAAe,EAC9B,EAAgB,MAAM,CACxB,GACM,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,IAAc,EAAK,KAAK;CAE9B,QAAsB;EACf,MAIL,EAAQ,CAAW,GACnB,EAAY,EAAgB,MAAM,CAAsC,GACxE,EAAS,IAAI;CACf,GAAG;EAAC;EAAiB;EAAa;CAAI,CAAC;CAEvC,eAAe,IAA+B;EAC5C,IAAI,CAAC,GAAa;GAChB,EAAS,SAAS;GAClB;EACF;EAEA,IAAI;GACF,MAAM,EAAS;IAAE,YAAY,EAAS;IAAY,MAAM;GAAY,CAAC;EACvE,SAAS,GAAsB;GAC7B,EAAS,EAAiB,CAAW,CAAC;EACxC;CACF;CAEA,OACE,kBAAC,GAAD;EACE,YAAW;EACX,oBAAoB,EAAE,UAAU,CAAC,EAAY;EAChC;EACJ;EACT,WAAU;EACV,UAAU;EACD;EACT,iBAAuB,KAAK,EAAc;EACpC;EACN,iBAAA;EACA,iBAAA;EACA,MAAK;EACE;YAbT;GAeE,kBAAC,GAAD;IAAc,OAAM;IAAO,MAAK;IAAe,UAAA;cAC7C,kBAAC,GAAD;KACE,WAAA;KACA,WAAA;KACA,WAAW,MAA+C;MAExD,AADA,EAAQ,EAAM,OAAO,KAAK,GAC1B,EAAS,IAAI;KACf;KACA,aAAY;KACZ,OAAO;KACP,SAAQ;IACT,CAAA;GACW,CAAA;GACd,kBAAC,GAAD;IAAc,OAAM;IAAK,MAAK;cAC5B,kBAAC,GAAD;KACE,WAAW;KACX,WAAA;KACA,WAAW,MAAiB;MAE1B,AADA,EAAY,EAAmB,GAAQ,CAAe,CAAC,GACvD,EAAS,IAAI;KACf;KACA,SAAS,CAAC,GAAG,CAAe;KAC5B,aAAY;KACZ,OAAO;IACR,CAAA;GACW,CAAA;GACb,IACC,kBAAC,GAAD;IAAY,OAAM;IAAa,SAAQ;cACpC;GACS,CAAA,IACV;EACC;;AAEX;AAEA,SAAS,EAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD;AAEA,IAAa,IAAiE;CAC5E,YAAY;CACZ,IAAI;CACJ,MAAM;AACR;AAEA,SAAS,EACP,GACA,GACwB;CACxB,IAAI,CAAC,EAAS,CAAK,GACjB,OAAO;CAGT,IAAM,IAAK,OAAO,EAAM,MAAO,WAAW,EAAM,KAAK;CAErD,OACE,EAAQ,MAAM,MAAW,EAAO,OAAO,CAAE,KACzC;AAEJ;AAEA,SAAS,EAAS,GAA4D;CAC5E,OAAO,OAAO,KAAU,cAAY;AACtC;;;ACpGA,IAAM,KAA6B;CAAC;CAAI;CAAI;AAAE,GACxC,KAGA;CACJ;EAAE,KAAK;EAAO,OAAO;CAAK;CAC1B;EAAE,KAAK;EAAa,OAAO;CAAM;CACjC;EAAE,KAAK;EAAS,OAAO;CAAK;AAC9B,GAEM,KAA8B;AAiBpC,SAAgB,EAAc,EAC5B,kBACsB,CAAC,GAAiB;CACxC,IAAM,IAAS,EAAiB,GAC1B,IAAS,EAAa,GACtB,IAAqB,KAAc,EAAO,UAAU,GACpD,CAAC,GAAW,KAAgB,EAChC,CAAC,CACH,GACM,CAAC,GAAgB,KAAqB,EAC1C,CACF,GACM,CAAC,GAAiB,MAAsB,EAE5C,CAAC,CAAC,GACE,CAAC,GAAuB,MAA4B,kBAExD,IAAI,IAAI,CAAC,GACL,CAAC,IAAiB,KAAsB,EAAS,EAAK,GACtD,CAAC,GAAU,KAAe,EAAS,EAAK,GACxC,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,CAAC,IAAS,KAAc,EAAS,EAAI,GACrC,CAAC,GAAc,KAAmB,EAAS,CAAC,GAC5C,CAAC,GAAkB,MAAuB,EAAS,EAAE,GACrD,CAAC,GAAoB,MAAyB,EAAS,EAAE,GACzD,CAAC,GAAgB,MACrB,EAA+B,KAAK,GAChC,CAAC,GAAoB,MAAyB,EAAS,CAAC,GAExD,IAAmB,EAAY,YAA2B;EAE9D,AADA,EAAW,EAAI,GACf,EAAS,IAAI;EAEb,IAAI;GACF,IAAM,CACJ,GACA,GACA,KACE,MAAM,QAAQ,IAAI;IACpB,GAA0B;KACxB,YAAY,EAAe;KAC3B,MAAM;KACN,UAAU;KACV,YAAY;KACZ,QAAQ,MAAmB,QAAQ,OAAO;IAC5C,CAAC;IACD,GAAwB;IACxB,GAAmC;KACjC,MAAM;KACN,UAAU;KACV,YAAY;KACZ,QAAQ;IACV,CAAC;GACH,CAAC;GAOD,AALA,GAAmB,CACjB,GAAG,EAAyB,WAAW,IAAI,CAAkB,CAC/D,CAAC,GACD,EAAa,EAAmB,SAAS,GACzC,GAAsB,EAAmB,UAAU,GACnD,GACE,IAAI,IAAI,EAAwB,KAAK,MAAa,EAAS,EAAE,CAAC,CAChE;EACF,SAAS,GAAuB;GAC9B,EAAS,GAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAW,EAAK;EAClB;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,QAAsB;EACpB,EAAsB;CACxB,GAAG,CAAC,CAAgB,CAAC;CAErB,IAAM,KAAO,QAET,EAAU,KAAK,OAAc;EAC3B,GAAG;EACH,eAAe,EAA0B,CAAQ;EACjD,KAAK,EAAS;EACd,QAAQ,EAAS,mBAAmB,cAAc;EAClD,WAAW,EAAe,EAAS,SAAS;CAC9C,EAAE,GACJ,CAAC,CAAS,CACZ,GACM,KAAU,QACoB;EAChC;GAAE,WAAW;GAAQ,KAAK;GAAQ,OAAO;GAAQ,OAAO;EAAI;EAC5D;GACE,KAAK;GACL,SAAS,MACP,kBAAC,IAAD,EAAqB,QAAQ,EAAO,OAAS,CAAA;GAE/C,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,MACP,kBAAC,IAAD,EAA+B,UAAS,CAAA;GAE1C,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;CACF,GACA,CAAC,CACH,GACM,KAAe,SACe;EAChC,SAAS,MAA4D;GACnE;IACE,WAAW,MACT,CAAC,EAAsB,IAAI,EAAS,EAAE;IACxC,MAAM;IACN,eACE,EAAO,KAAK,EAAO,QAAQ,EAAO,EAAE,CAAC;IACvC,SAAS;GACX;GACA;IACE,MAAM;IACN,eAAqB,EAAO,KAAK,EAAO,iBAAiB,EAAO,EAAE,CAAC;GACrE;GACA;IACE,MAAM;IACN,eAAqB,EAAO,KAAK,EAAO,iBAAiB,EAAO,EAAE,CAAC;GACrE;EACF;EACA,SAAS;EACT,OAAO;CACT,IACA,CAAC,GAAuB,CAAM,CAChC;CAEA,eAAe,GAAqB,EAClC,eACA,WAIgB;EAEhB,AADA,EAAY,EAAI,GAChB,EAAS,IAAI;EAEb,IAAI;GACF,IAAM,IAAa,MAAM,GAAuB;IAAE;IAAY;GAAK,CAAC;GAEpE,AADA,EAAmB,EAAK,GACxB,EAAO,KAAK,EAAO,iBAAiB,CAAU,CAAC;EACjD,UAAU;GACR,EAAY,EAAK;EACnB;CACF;CAEA,OACE,kBAAA,IAAA,EAAA,UAAA,CACE,kBAAC,GAAD;EAAW,YAAY;YAAvB,CACI,kBAAC,GAAD,EAAA,UACE,kBAAC,IAAD;GACE,aAAY;GACZ,OAAM;aAEN,kBAAC,GAAD;IACE,UAAU;IACV,MAAM;IACN,UAAS;IACT,eAAqB,EAAmB,EAAI;IAC5C,SAAQ;cACT;GAEO,CAAA;EACK,CAAA,EACL,CAAA,GAEZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;GACE,YACE,kBAAC,GAAD;IAAY,WAAW,EAAO;IAAoB,MAAK;cACrD,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;KAAQ,MAAM;eACZ,kBAAC,GAAD;MACE,WAAA;MACA,QAAQ,EAAgB;MACxB,MAAK;gBAEL,kBAAC,GAAD;OACE,WAAA;OACA,WACE,MACS;QAET,AADA,GAAsB,EAAM,OAAO,KAAK,GACxC,EAAgB,CAAC;OACnB;OACA,aAAY;OACZ,MAAK;OACL,OAAO;OACP,SAAQ;MACT,CAAA;KACQ,CAAA;IACL,CAAA,GACR,kBAAC,GAAD;KAAQ,MAAM;eACZ,kBAAC,GAAD;MACE,WAAA;MACA,QAAQ,EAAgB;MACxB,MAAK;gBAEL,kBAAC,GAAD;OACE,WAAW;OACX,WAAA;OACA,WAAW,MAAiB;QAI1B,AAHA,EACE,EAAyB,GAAQ,CAAe,CAClD,GACA,EAAgB,CAAC;OACnB;OACA,SAAS,CACP,GACA,GAAG,CACL;OACA,aAAY;OACZ,cAAc,MACZ,MAAM,EAAgC,CAAK;OAE7C,MAAK;OACL,OAAO;MACR,CAAA;KACQ,CAAA;IACL,CAAA,CACE,EAAA,CAAA;GACF,CAAA;GAEd,KACE,kBAAC,IAAD;IACE,WAAW;IACX,WAAW,MAAoB;KAE7B,AADA,GAAkB,GAAyB,CAAS,CAAC,GACrD,EAAgB,CAAC;IACnB;cAEC,GAAqB,KAAK,MACzB,kBAAC,GAAD,EAAA,UAA8B,EAAU,MAAe,GAAzC,EAAU,GAA+B,CACxD;GACE,CAAA;aAnET,CAsEG,IACC,kBAAC,GAAD;IAAY,OAAM;IAAa,SAAQ;cACpC;GACS,CAAA,IACV,MACJ,kBAAC,GAAD;IACE,SAAS;IACA;IACT,YAAY;IACZ,WAAA;IACS;IACT,YAAY;KACV,SAAS;KACT,WAAW,MAAe;MACxB,EAAgB,CAAI;KACtB;KACA,mBAAmB,MAAmB;MAEpC,AADA,EAAgB,CAAC,GACjB,GAAoB,CAAQ;KAC9B;KACA,UAAU;KACV,eAAe;KACf,iBAAiB;KACjB,sBAAsB,GAAM,GAAI,MAC9B,MAAM,EAAK,GAAG,EAAG,OAAO,EAAM;KAChC,qBAAqB;KACrB,OAAO;IACT;GACD,CAAA,CACM;KACG,CAAA,CACL;KAEb,kBAAC,IAAD;EACE,iBAAiB,CACf,GACA,GAAG,CACL;EACA,aAAY;EACZ,aAAY;EACZ,SAAS;EACT,eAAqB,EAAmB,EAAK;EAC7C,UAAU;EACV,MAAM;EACN,OAAM;CACP,CAAA,CACD,EAAA,CAAA;AAEN;AAEA,SAAS,GAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD;AAEA,SAAS,GAAyB,GAAsC;CAKtE,OAJI,MAAc,eAAe,MAAc,UACtC,IAGF;AACT;AAEA,SAAS,GAAoB,EAC3B,aAGe;CAKf,OAJI,MAAW,cACN,kBAAC,GAAD;EAAO,MAAK;EAAM,MAAK;EAAM,SAAQ;CAAe,CAAA,IAGtD,kBAAC,GAAD;EAAO,MAAK;EAAM,MAAK;EAAK,SAAQ;CAAgB,CAAA;AAC7D;AAEA,SAAS,GAAsB,EAC7B,aAGe;CAWf,OAVI,EAAO,gBAAgB,aAAa,KAEpC,kBAAC,GAAD;EACE,MAAK;EACL,MAAM,GAAG,EAAO,cAAc;EAC9B,SAAQ;CACT,CAAA,IAKH,kBAAC,GAAD;EAAY,WAAU;EAAO,SAAQ;YAClC,EAAO;CACE,CAAA;AAEhB;AAEA,IAAM,IAA+D;CACnE,YAAY;CACZ,IAAI;CACJ,MAAM;AACR;AAEA,SAAS,EACP,GACwB;CACxB,OAAO;EACL,YAAY,EAAS;EACrB,IAAI,EAAS;EACb,MAAM,EAAS;CACjB;AACF;AAEA,SAAS,EACP,GACA,GACwB;CACxB,IAAI,CAAC,EAAS,CAAK,GACjB,OAAO;CAGT,IAAM,IAAK,OAAO,EAAM,MAAO,WAAW,EAAM,KAAK;CAMrD,OAJI,MAAO,EAAqC,KACvC,IAIP,EAAQ,MAAM,MAAW,EAAO,OAAO,CAAE,KACzC;AAEJ;AAEA,SAAS,EAAgC,GAAwB;CAS/D,OARI,MAAM,QAAQ,CAAK,KAInB,CAAC,EAAS,CAAK,IACV,EAAqC,OAGvC,OAAO,EAAM,QAAS,WACzB,EAAM,OACN,EAAqC;AAC3C;AAEA,SAAS,EAA0B,GAA0C;CAC3E,OAAO,EAAS,gBAAgB,QAAQ,EAAS,YAAY;AAC/D;AAEA,SAAS,EAAS,GAA4D;CAC5E,OAAO,OAAO,KAAU,cAAY;AACtC"}
@@ -0,0 +1,2 @@
1
+ "use client";require('../users.css');const e=require("./app-navigation-KnlJCUp1.cjs"),t=require("./routes-config-2aKbWq2H.cjs");let n=require("react"),r=require("@mezzanine-ui/react"),i=require("@rytass/bpm-core-client"),a=require("react/jsx-runtime"),o=require("@mezzanine-ui/react/ContentHeader");o=e.o(o,1);let s=require("@mezzanine-ui/core/form"),c=require("@rytass/bpm-core-client/organization");var l={memberFilterArea:`bpm_memberFilterArea_9RB2k`,header:`bpm_header_sIEtg`,detailFields:`bpm_detailFields_TyKNL`,detailSection:`bpm_detailSection_-iLjy`,membershipList:`bpm_membershipList_5n9iq`},u=[10,20,50];function d({activeHref:d}={}){let p=t.r(),m=d??p.adminUsers(),[h,_]=(0,n.useState)(null),[v,y]=(0,n.useState)([]),[b,x]=(0,n.useState)(null),[S,C]=(0,n.useState)(null),[w,T]=(0,n.useState)(null),[E,D]=(0,n.useState)(!0),[O,k]=(0,n.useState)(1),[A,j]=(0,n.useState)(10),[M,N]=(0,n.useState)(0),[P,F]=(0,n.useState)([]),[I,L]=(0,n.useState)([]),[R,z]=(0,n.useState)([]),[B,V]=(0,n.useState)(``),H=(0,n.useMemo)(()=>new Map(I.map(e=>[e.id,e])),[I]),U=(0,n.useMemo)(()=>new Map(R.map(e=>[e.id,e])),[R]),W=(0,n.useCallback)(async()=>{D(!0),T(null);try{let[e,t]=await Promise.all([(0,i.listMemberDirectoryPage)({page:O,pageSize:A,searchText:B}),(0,c.readOrganizationDashboard)()]);F(e.members),N(e.totalCount),L(t.orgUnits),z(t.positions)}catch(e){T(g(e))}finally{D(!1)}},[O,A,B]);(0,n.useEffect)(()=>{W()},[W]);let G=(0,n.useMemo)(()=>P.map(e=>({...e,key:e.memberId})),[P]),K=(0,n.useCallback)(async e=>{_(e),x(null),T(null);try{let[t,n]=await Promise.all([(0,c.listMemberships)({memberId:e.memberId}),(0,c.readResolvedManager)(e.memberId)]);y(t),C(n),x((await(0,i.resolveMembers)(n.managerMemberId?[n.managerMemberId]:[]))[0]??null)}catch(e){T(g(e))}},[]),q=(0,n.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`姓名`,width:160},{dataIndex:`email`,key:`email`,title:`信箱`,width:260}],[]),J=(0,n.useMemo)(()=>({render:()=>[{name:`檢視`,onClick:e=>{K(e)}}],variant:`base-secondary`,width:88}),[K]);function Y(){_(null),x(null),y([]),C(null)}return(0,a.jsxs)(e.t,{activeHref:m,children:[(0,a.jsx)(r.PageHeader,{children:(0,a.jsx)(o.default,{description:`會員資料由 host member resolver 提供,BPM 僅維護組織歸屬與主管解析。`,title:`會員對照`})}),(0,a.jsx)(r.SectionGroup,{children:(0,a.jsxs)(r.Section,{filterArea:(0,a.jsx)(r.FilterArea,{className:l.memberFilterArea,children:(0,a.jsx)(r.FilterLine,{children:(0,a.jsx)(r.Filter,{span:3,children:(0,a.jsx)(r.FormField,{fullWidth:!0,layout:s.FormFieldLayout.VERTICAL,name:`memberSearchText`,children:(0,a.jsx)(r.Input,{fullWidth:!0,onChange:e=>{V(e.target.value),k(1)},placeholder:`搜尋姓名或信箱`,size:`sub`,value:B,variant:`base`})})})})}),children:[w?(0,a.jsx)(r.Typography,{color:`text-error`,variant:`body`,children:w}):null,(0,a.jsx)(r.Table,{actions:J,columns:q,dataSource:G,fullWidth:!0,loading:E,pagination:{current:O,onChange:e=>{k(e)},onChangePageSize:e=>{k(1),j(e)},pageSize:A,pageSizeLabel:`每頁筆數`,pageSizeOptions:u,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:M}})]})}),(0,a.jsx)(f,{managerProfile:b,member:h,memberships:v,onClose:Y,orgUnitsById:H,positionsById:U,resolvedManager:S})]})}function f({managerProfile:e,member:t,memberships:n,onClose:i,orgUnitsById:o,positionsById:s,resolvedManager:c}){return(0,a.jsx)(r.Modal,{cancelText:`關閉`,confirmText:`關閉`,modalType:`standard`,onCancel:i,onClose:i,onConfirm:i,open:!!t,showModalFooter:!0,showModalHeader:!0,size:`regular`,title:t?.name??`會員明細`,children:t?(0,a.jsxs)(`div`,{className:l.detailFields,children:[(0,a.jsx)(r.BaseCard,{title:`基本資料`,children:(0,a.jsx)(`div`,{className:l.detailSection,children:(0,a.jsxs)(r.Typography,{variant:`body`,children:[`信箱:`,t.email]})})}),(0,a.jsx)(r.BaseCard,{title:`BPM 組織歸屬`,children:(0,a.jsx)(`div`,{className:l.membershipList,children:n.length?n.map(e=>(0,a.jsxs)(r.Typography,{variant:`body`,children:[p(o.get(e.orgUnitId)),` / `,e.positionId?m(s.get(e.positionId)):`未指定職位`,` / `,e.isPrimary?`主要`:`一般`]},e.id)):(0,a.jsx)(r.Typography,{color:`text-neutral`,variant:`body`,children:`尚未建立 BPM 組織歸屬`})})}),(0,a.jsx)(r.BaseCard,{title:`主管解析`,children:(0,a.jsx)(r.Typography,{variant:`body`,children:c?.managerMemberId?h(e):`尚未解析到主管`})})]}):null})}function p(e){return e?`${e.name} · ${e.code}`:`未知組織`}function m(e){return e?`${e.name} · ${e.code}`:`未知職位`}function h(e){return e?`${e.name} · ${e.email}`:`主管資料尚未載入`}function g(e){return e instanceof Error?e.message:`讀取會員資料失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return d}});
2
+ //# sourceMappingURL=users-3ySyUW4u.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users-3ySyUW4u.cjs","names":[],"sources":["../../src/views/admin/users/users.module.scss","../../src/views/admin/users/AdminUsersView.tsx"],"sourcesContent":[".memberFilterArea {\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 :global(.mzn-input),\n :global(.mzn-input-container),\n :global(.mzn-text-field) {\n width: 100%;\n min-width: 0 !important;\n }\n}\n\n.header {\n display: grid;\n gap: 4px;\n padding: 24px 24px 0;\n}\n\n.detailFields {\n display: grid;\n gap: 16px;\n}\n\n.detailSection {\n display: grid;\n gap: 8px;\n}\n\n.membershipList {\n display: grid;\n gap: 8px;\n}\n","'use client';\n\nimport {\n ChangeEvent,\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n BaseCard,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport styles from './users.module.scss';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { AppLayout } from '../../../components/app-navigation';\nimport {\n listMemberDirectoryPage,\n MemberProfileRecord,\n resolveMembers,\n} from '@rytass/bpm-core-client';\nimport {\n listMemberships,\n MembershipRecord,\n OrgUnitRecord,\n PositionRecord,\n readOrganizationDashboard,\n readResolvedManager,\n ResolvedManagerRecord,\n} from '@rytass/bpm-core-client/organization';\n\ntype MemberRow = Readonly<\n Record<string, unknown> &\n MemberProfileRecord & {\n key: string;\n }\n>;\n\nconst MEMBER_PAGE_SIZE_OPTIONS = [10, 20, 50];\n\nexport interface AdminUsersViewProps {\n readonly activeHref?: string;\n}\n\nexport function AdminUsersView({\n activeHref,\n}: AdminUsersViewProps = {}): ReactElement {\n const routes = useBPMRoutes();\n const resolvedActiveHref = activeHref ?? routes.adminUsers();\n const [detailMember, setDetailMember] = useState<MemberProfileRecord | null>(\n null,\n );\n const [detailMemberships, setDetailMemberships] = useState<\n readonly MembershipRecord[]\n >([]);\n const [detailManagerProfile, setDetailManagerProfile] =\n useState<MemberProfileRecord | null>(null);\n const [detailResolvedManager, setDetailResolvedManager] =\n useState<ResolvedManagerRecord | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [memberPage, setMemberPage] = useState(1);\n const [memberPageSize, setMemberPageSize] = useState(10);\n const [memberTotalCount, setMemberTotalCount] = useState(0);\n const [members, setMembers] = useState<readonly MemberProfileRecord[]>([]);\n const [orgUnits, setOrgUnits] = useState<readonly OrgUnitRecord[]>([]);\n const [positions, setPositions] = useState<readonly PositionRecord[]>([]);\n const [searchText, setSearchText] = useState('');\n\n const orgUnitsById = useMemo(\n (): ReadonlyMap<string, OrgUnitRecord> =>\n new Map(orgUnits.map((orgUnit) => [orgUnit.id, orgUnit])),\n [orgUnits],\n );\n const positionsById = useMemo(\n (): ReadonlyMap<string, PositionRecord> =>\n new Map(positions.map((position) => [position.id, position])),\n [positions],\n );\n\n const refreshMembers = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const [memberPageResult, organization] = await Promise.all([\n listMemberDirectoryPage({\n page: memberPage,\n pageSize: memberPageSize,\n searchText,\n }),\n readOrganizationDashboard(),\n ]);\n\n setMembers(memberPageResult.members);\n setMemberTotalCount(memberPageResult.totalCount);\n setOrgUnits(organization.orgUnits);\n setPositions(organization.positions);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [memberPage, memberPageSize, searchText]);\n\n useEffect((): void => {\n void refreshMembers();\n }, [refreshMembers]);\n\n const rows = useMemo(\n (): MemberRow[] =>\n members.map((member) => ({\n ...member,\n key: member.memberId,\n })),\n [members],\n );\n\n const openDetail = useCallback(\n async (member: MemberProfileRecord): Promise<void> => {\n setDetailMember(member);\n setDetailManagerProfile(null);\n setError(null);\n\n try {\n const [memberships, resolvedManager] = await Promise.all([\n listMemberships({ memberId: member.memberId }),\n readResolvedManager(member.memberId),\n ]);\n\n setDetailMemberships(memberships);\n setDetailResolvedManager(resolvedManager);\n setDetailManagerProfile(\n (\n await resolveMembers(\n resolvedManager.managerMemberId\n ? [resolvedManager.managerMemberId]\n : [],\n )\n )[0] ?? null,\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n }\n },\n [],\n );\n\n const columns = useMemo(\n (): TableColumn<MemberRow>[] => [\n { dataIndex: 'name', key: 'name', title: '姓名', width: 160 },\n { dataIndex: 'email', key: 'email', title: '信箱', width: 260 },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<MemberRow> => ({\n render: (): ReturnType<TableActions<MemberRow>['render']> => [\n {\n name: '檢視',\n onClick: (record): void => {\n void openDetail(record);\n },\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [openDetail],\n );\n\n function closeDetail(): void {\n setDetailMember(null);\n setDetailManagerProfile(null);\n setDetailMemberships([]);\n setDetailResolvedManager(null);\n }\n\n return (\n <AppLayout activeHref={resolvedActiveHref}>\n <PageHeader>\n <ContentHeader\n description=\"會員資料由 host member resolver 提供,BPM 僅維護組織歸屬與主管解析。\"\n title=\"會員對照\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.memberFilterArea}>\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"memberSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setMemberPage(1);\n }}\n placeholder=\"搜尋姓名或信箱\"\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\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}\n pagination={{\n current: memberPage,\n onChange: (page): void => {\n setMemberPage(page);\n },\n onChangePageSize: (pageSize): void => {\n setMemberPage(1);\n setMemberPageSize(pageSize);\n },\n pageSize: memberPageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: MEMBER_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: memberTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n\n <MemberDetailModal\n managerProfile={detailManagerProfile}\n member={detailMember}\n memberships={detailMemberships}\n onClose={closeDetail}\n orgUnitsById={orgUnitsById}\n positionsById={positionsById}\n resolvedManager={detailResolvedManager}\n />\n </AppLayout>\n );\n}\n\nfunction MemberDetailModal({\n managerProfile,\n member,\n memberships,\n onClose,\n orgUnitsById,\n positionsById,\n resolvedManager,\n}: {\n readonly managerProfile: MemberProfileRecord | null;\n readonly member: MemberProfileRecord | null;\n readonly memberships: readonly MembershipRecord[];\n readonly onClose: () => void;\n readonly orgUnitsById: ReadonlyMap<string, OrgUnitRecord>;\n readonly positionsById: ReadonlyMap<string, PositionRecord>;\n readonly resolvedManager: ResolvedManagerRecord | null;\n}): ReactElement {\n return (\n <Modal\n cancelText=\"關閉\"\n confirmText=\"關閉\"\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={onClose}\n open={Boolean(member)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={member?.name ?? '會員明細'}\n >\n {member ? (\n <div className={styles.detailFields}>\n <BaseCard title=\"基本資料\">\n <div className={styles.detailSection}>\n <Typography variant=\"body\">信箱:{member.email}</Typography>\n </div>\n </BaseCard>\n <BaseCard title=\"BPM 組織歸屬\">\n <div className={styles.membershipList}>\n {memberships.length ? (\n memberships.map((membership) => (\n <Typography key={membership.id} variant=\"body\">\n {readOrgUnitLabel(orgUnitsById.get(membership.orgUnitId))}\n {' / '}\n {membership.positionId\n ? readPositionLabel(\n positionsById.get(membership.positionId),\n )\n : '未指定職位'}\n {' / '}\n {membership.isPrimary ? '主要' : '一般'}\n </Typography>\n ))\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 尚未建立 BPM 組織歸屬\n </Typography>\n )}\n </div>\n </BaseCard>\n <BaseCard title=\"主管解析\">\n <Typography variant=\"body\">\n {resolvedManager?.managerMemberId\n ? readMemberLabel(managerProfile)\n : '尚未解析到主管'}\n </Typography>\n </BaseCard>\n </div>\n ) : null}\n </Modal>\n );\n}\n\nfunction readOrgUnitLabel(orgUnit: OrgUnitRecord | undefined): string {\n return orgUnit ? `${orgUnit.name} · ${orgUnit.code}` : '未知組織';\n}\n\nfunction readPositionLabel(position: PositionRecord | undefined): string {\n return position ? `${position.name} · ${position.code}` : '未知職位';\n}\n\nfunction readMemberLabel(member: MemberProfileRecord | null): string {\n return member ? `${member.name} · ${member.email}` : '主管資料尚未載入';\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取會員資料失敗。';\n}\n"],"mappings":"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"}