@rytass/bpm-core-react 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +1 -0
  3. package/dist/chunks/{FormBuilderView-bm8P55hp.cjs → FormBuilderView-Bg9ftYz-.cjs} +2 -2
  4. package/dist/chunks/{FormBuilderView-bm8P55hp.cjs.map → FormBuilderView-Bg9ftYz-.cjs.map} +1 -1
  5. package/dist/chunks/{FormBuilderView-D_bN9gzT.js → FormBuilderView-CBvdcg_t.js} +2 -2
  6. package/dist/chunks/{FormBuilderView-D_bN9gzT.js.map → FormBuilderView-CBvdcg_t.js.map} +1 -1
  7. package/dist/chunks/FormRendererView-D-p6GDQB.cjs +6 -0
  8. package/dist/chunks/FormRendererView-D-p6GDQB.cjs.map +1 -0
  9. package/dist/chunks/FormRendererView-DHXmekC3.js +1319 -0
  10. package/dist/chunks/FormRendererView-DHXmekC3.js.map +1 -0
  11. package/dist/chunks/{approval-instance-list-page-Cv5I1YPX.cjs → approval-instance-list-page-BqkG9jiR.cjs} +2 -2
  12. package/dist/chunks/{approval-instance-list-page-Cv5I1YPX.cjs.map → approval-instance-list-page-BqkG9jiR.cjs.map} +1 -1
  13. package/dist/chunks/{approval-instance-list-page-BI5fIXc-.js → approval-instance-list-page-CsSpIN4C.js} +2 -2
  14. package/dist/chunks/{approval-instance-list-page-BI5fIXc-.js.map → approval-instance-list-page-CsSpIN4C.js.map} +1 -1
  15. package/dist/chunks/{compose-CdKVQfjB.cjs → compose-B43jtdyL.cjs} +2 -2
  16. package/dist/chunks/{compose-CdKVQfjB.cjs.map → compose-B43jtdyL.cjs.map} +1 -1
  17. package/dist/chunks/{compose-N9657E5u.js → compose-C7yS6bJm.js} +5 -5
  18. package/dist/chunks/{compose-N9657E5u.js.map → compose-C7yS6bJm.js.map} +1 -1
  19. package/dist/chunks/{dashboard-page-BoqNhjT_.js → dashboard-page-DBJCsPya.js} +2 -2
  20. package/dist/chunks/{dashboard-page-BoqNhjT_.js.map → dashboard-page-DBJCsPya.js.map} +1 -1
  21. package/dist/chunks/{dashboard-page-D7YJ3udk.cjs → dashboard-page-lqlLELKs.cjs} +2 -2
  22. package/dist/chunks/{dashboard-page-D7YJ3udk.cjs.map → dashboard-page-lqlLELKs.cjs.map} +1 -1
  23. package/dist/chunks/{designer-CKwG_vM5.js → designer-B9Ut4xze.js} +1736 -1611
  24. package/dist/chunks/designer-B9Ut4xze.js.map +1 -0
  25. package/dist/chunks/designer-eXw7R9ug.cjs +69 -0
  26. package/dist/chunks/designer-eXw7R9ug.cjs.map +1 -0
  27. package/dist/chunks/{detail-fW0vJudE.js → detail-BB_uYaoM.js} +7 -6
  28. package/dist/chunks/detail-BB_uYaoM.js.map +1 -0
  29. package/dist/chunks/detail-DN8pEzUJ.cjs +5 -0
  30. package/dist/chunks/detail-DN8pEzUJ.cjs.map +1 -0
  31. package/dist/chunks/member-profile-resolution-CJlgVdTR.js +44 -0
  32. package/dist/chunks/member-profile-resolution-CJlgVdTR.js.map +1 -0
  33. package/dist/chunks/member-profile-resolution-DiH-P-Vh.cjs +2 -0
  34. package/dist/chunks/member-profile-resolution-DiH-P-Vh.cjs.map +1 -0
  35. package/dist/chunks/{providers-CQWekD7_.js → providers-D35lBOTd.js} +2 -2
  36. package/dist/chunks/{providers-CQWekD7_.js.map → providers-D35lBOTd.js.map} +1 -1
  37. package/dist/chunks/{providers-VUOh6i0i.cjs → providers-Dz4Wqxr6.cjs} +2 -2
  38. package/dist/chunks/{providers-VUOh6i0i.cjs.map → providers-Dz4Wqxr6.cjs.map} +1 -1
  39. package/dist/chunks/{routes-config-C1j_vFKo.cjs → routes-config-BWjZDAU3.cjs} +2 -2
  40. package/dist/chunks/{routes-config-C1j_vFKo.cjs.map → routes-config-BWjZDAU3.cjs.map} +1 -1
  41. package/dist/chunks/{routes-config-BcNaWJWJ.js → routes-config-DjEOE9eP.js} +3 -2
  42. package/dist/chunks/{routes-config-BcNaWJWJ.js.map → routes-config-DjEOE9eP.js.map} +1 -1
  43. package/dist/chunks/users-C_Dtw_sR.cjs +2 -0
  44. package/dist/chunks/users-C_Dtw_sR.cjs.map +1 -0
  45. package/dist/chunks/users-wgM3TqU3.js +513 -0
  46. package/dist/chunks/users-wgM3TqU3.js.map +1 -0
  47. package/dist/index.cjs +1 -1
  48. package/dist/index.js +4 -4
  49. package/dist/lib/routes-config.d.cts +2 -0
  50. package/dist/lib/routes-config.d.ts +2 -0
  51. package/dist/next/index.cjs +1 -1
  52. package/dist/next/index.js +2 -2
  53. package/dist/pages/admin/stuck-instances/index.cjs +2 -0
  54. package/dist/pages/admin/stuck-instances/index.cjs.map +1 -0
  55. package/dist/pages/admin/stuck-instances/index.d.cts +4 -0
  56. package/dist/pages/admin/stuck-instances/index.d.ts +4 -0
  57. package/dist/pages/admin/stuck-instances/index.js +13 -0
  58. package/dist/pages/admin/stuck-instances/index.js.map +1 -0
  59. package/dist/pages/admin/users/index.cjs +1 -1
  60. package/dist/pages/admin/users/index.js +1 -1
  61. package/dist/pages/instances/detail/index.cjs +1 -1
  62. package/dist/pages/instances/detail/index.js +1 -1
  63. package/dist/pages/templates/compose/index.cjs +1 -1
  64. package/dist/pages/templates/compose/index.js +1 -1
  65. package/dist/pages/templates/designer/index.cjs +1 -1
  66. package/dist/pages/templates/designer/index.js +1 -1
  67. package/dist/views/admin/index.cjs +1 -1
  68. package/dist/views/admin/index.d.cts +1 -0
  69. package/dist/views/admin/index.d.ts +1 -0
  70. package/dist/views/admin/index.js +3 -2
  71. package/dist/views/admin/stuck-instances/AdminStuckInstancesView.d.cts +10 -0
  72. package/dist/views/admin/stuck-instances/AdminStuckInstancesView.d.ts +10 -0
  73. package/dist/views/admin/stuck-instances/StuckInstanceCancelModal.d.cts +14 -0
  74. package/dist/views/admin/stuck-instances/StuckInstanceCancelModal.d.ts +14 -0
  75. package/dist/views/admin/stuck-instances/index.cjs +2 -0
  76. package/dist/views/admin/stuck-instances/index.cjs.map +1 -0
  77. package/dist/views/admin/stuck-instances/index.d.cts +2 -0
  78. package/dist/views/admin/stuck-instances/index.d.ts +2 -0
  79. package/dist/views/admin/stuck-instances/index.js +237 -0
  80. package/dist/views/admin/stuck-instances/index.js.map +1 -0
  81. package/dist/views/admin/users/index.cjs +1 -1
  82. package/dist/views/admin/users/index.js +1 -1
  83. package/dist/views/cc/index.cjs +1 -1
  84. package/dist/views/cc/index.js +1 -1
  85. package/dist/views/dashboard/index.cjs +1 -1
  86. package/dist/views/dashboard/index.js +1 -1
  87. package/dist/views/forms/builder/index.cjs +1 -1
  88. package/dist/views/forms/builder/index.js +1 -1
  89. package/dist/views/forms/renderer/index.cjs +1 -1
  90. package/dist/views/forms/renderer/index.js +1 -1
  91. package/dist/views/inbox/index.cjs +1 -1
  92. package/dist/views/inbox/index.js +1 -1
  93. package/dist/views/instances/detail/index.cjs +1 -1
  94. package/dist/views/instances/detail/index.js +1 -1
  95. package/dist/views/instances/new/index.cjs +1 -1
  96. package/dist/views/instances/new/index.js +4 -4
  97. package/dist/views/instances/new/index.js.map +1 -1
  98. package/dist/views/search/index.cjs +1 -1
  99. package/dist/views/search/index.js +1 -1
  100. package/dist/views/sent/index.cjs +1 -1
  101. package/dist/views/sent/index.js +1 -1
  102. package/dist/views/templates/compose/index.cjs +1 -1
  103. package/dist/views/templates/compose/index.js +1 -1
  104. package/dist/views/templates/designer/approver-resolver-model.d.cts +31 -0
  105. package/dist/views/templates/designer/approver-resolver-model.d.ts +31 -0
  106. package/dist/views/templates/designer/index.cjs +1 -1
  107. package/dist/views/templates/designer/index.js +1 -1
  108. package/dist/views/templates/designer/node-actor-resolver-options.d.cts +30 -3
  109. package/dist/views/templates/designer/node-actor-resolver-options.d.ts +30 -3
  110. package/dist/views/templates/index.cjs +1 -1
  111. package/dist/views/templates/index.js +1 -1
  112. package/dist/views/templates/versions/index.cjs +1 -1
  113. package/dist/views/templates/versions/index.js +1 -1
  114. package/package.json +23 -3
  115. package/dist/chunks/FormRendererView-BlQgJOkI.cjs +0 -6
  116. package/dist/chunks/FormRendererView-BlQgJOkI.cjs.map +0 -1
  117. package/dist/chunks/FormRendererView-CemHvfAT.js +0 -1359
  118. package/dist/chunks/FormRendererView-CemHvfAT.js.map +0 -1
  119. package/dist/chunks/designer-CKwG_vM5.js.map +0 -1
  120. package/dist/chunks/designer-JPs7EijM.cjs +0 -69
  121. package/dist/chunks/designer-JPs7EijM.cjs.map +0 -1
  122. package/dist/chunks/detail-Dqu0K9QM.cjs +0 -5
  123. package/dist/chunks/detail-Dqu0K9QM.cjs.map +0 -1
  124. package/dist/chunks/detail-fW0vJudE.js.map +0 -1
  125. package/dist/chunks/users-BBtiZ9QQ.js +0 -486
  126. package/dist/chunks/users-BBtiZ9QQ.js.map +0 -1
  127. package/dist/chunks/users-EqSzDhuj.cjs +0 -2
  128. package/dist/chunks/users-EqSzDhuj.cjs.map +0 -1
@@ -0,0 +1,513 @@
1
+ "use client";
2
+ import { t as e } from "./format-member-label-C73FuP-d.js";
3
+ import { t } from "./bpm-form-field-9B-Det0u.js";
4
+ import { t as n } from "./admin-pickers-DfGxsjpp.js";
5
+ import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
6
+ import { BaseCard as c, Button as ee, Filter as l, FilterArea as u, FilterLine as d, FormField as f, Input as te, Modal as p, PageHeader as m, Section as h, SectionGroup as g, Table as _, Typography as v } from "@mezzanine-ui/react";
7
+ import { listMemberDirectoryPage as y, resolveMembers as b } from "@rytass/bpm-core-client";
8
+ import { Fragment as ne, jsx as x, jsxs as S } from "react/jsx-runtime";
9
+ import { listInactiveMembersWithOpenTasks as C, listMemberOpenTasks as re, reassignMemberTasks as w } from "@rytass/bpm-core-client/workflow";
10
+ import { FormFieldLayout as T } from "@mezzanine-ui/core/form";
11
+ import E from "@mezzanine-ui/react/ContentHeader";
12
+ import { listMemberships as D, readOrganizationDashboard as O, readResolvedManager as k } from "@rytass/bpm-core-client/organization";
13
+ import '../users.css';var A = {
14
+ memberFilterArea: "bpm_memberFilterArea_9RB2k",
15
+ header: "bpm_header_sIEtg",
16
+ detailFields: "bpm_detailFields_TyKNL",
17
+ detailSection: "bpm_detailSection_-iLjy",
18
+ membershipList: "bpm_membershipList_5n9iq"
19
+ }, j = "已不在此人的待辦中";
20
+ function M({ member: e, onClose: c }) {
21
+ let [l, u] = s([]), [d, f] = s(!1), [m, h] = s([]), [g, y] = s(null), [b, C] = s(""), [T, E] = s(null), [D, O] = s(null), [k, M] = s(!1), [F, I] = s(null), L = a(() => {
22
+ let e = new Set(m);
23
+ return l.filter((t) => e.has(t.taskId)).map((e) => e.taskId);
24
+ }, [l, m]), R = [...L].sort().join(","), z = b.trim(), B = `${g?.id ?? ""}|${z}|${R}`, V = T !== null && T.inputKey === B, H = T !== null && V && L.length > 0 && T.results.some((e) => e.outcome === "WOULD_REASSIGN"), U = o(0), W = o(null), G = r(async (e, t) => {
25
+ let n = U.current + 1;
26
+ U.current = n, f(!0);
27
+ try {
28
+ let r = await re(e);
29
+ if (U.current === n) {
30
+ let e = t ? new Set(t) : null;
31
+ u(r), h(r.map((e) => e.taskId).filter((t) => !e || e.has(t)));
32
+ }
33
+ } catch (e) {
34
+ U.current === n && I(P(e));
35
+ } finally {
36
+ U.current === n && f(!1);
37
+ }
38
+ }, []);
39
+ i(() => {
40
+ W.current = e?.memberId ?? null, y(null), C(""), E(null), O(null), I(null), e ? (u([]), h([]), G(e.memberId)) : (U.current += 1, u([]), f(!1));
41
+ }, [e, G]);
42
+ let ie = a(() => new Map(l.map((e) => [e.taskId, e.instanceTitle])), [l]);
43
+ async function K(t) {
44
+ if (!e || !g || !z || L.length === 0) return;
45
+ let n = L, r = ie, i = e.memberId;
46
+ M(!0), I(null);
47
+ try {
48
+ let e = await w({
49
+ dryRun: t,
50
+ fromMemberId: i,
51
+ reason: z,
52
+ taskIds: n,
53
+ toMemberId: g.id
54
+ });
55
+ if (W.current !== i) return;
56
+ t ? (E({
57
+ inputKey: B,
58
+ results: e,
59
+ sentTaskIds: n,
60
+ titleById: r
61
+ }), O(null)) : (O({
62
+ results: e,
63
+ sentTaskIds: n,
64
+ titleById: r
65
+ }), E(null), await G(i, n));
66
+ } catch (e) {
67
+ W.current === i && I(P(e));
68
+ } finally {
69
+ M(!1);
70
+ }
71
+ }
72
+ let q = a(() => {
73
+ let e = D ?? T;
74
+ if (!e) return [];
75
+ let t = new Set(e.results.map((e) => e.taskId)), n = e.results.map((t) => ({
76
+ instanceTitle: e.titleById.get(t.taskId) ?? t.taskId,
77
+ key: t.taskId,
78
+ message: t.message,
79
+ outcomeLabel: N(t.outcome)
80
+ })), r = e.sentTaskIds.filter((e) => !t.has(e)).map((t) => ({
81
+ instanceTitle: e.titleById.get(t) ?? t,
82
+ key: `gone:${t}`,
83
+ message: null,
84
+ outcomeLabel: j
85
+ }));
86
+ return [...n, ...r];
87
+ }, [D, T]), J = a(() => [
88
+ {
89
+ dataIndex: "instanceTitle",
90
+ key: "instanceTitle",
91
+ title: "案件",
92
+ width: 220
93
+ },
94
+ {
95
+ dataIndex: "nodeLabel",
96
+ key: "nodeLabel",
97
+ title: "節點",
98
+ width: 160
99
+ },
100
+ {
101
+ key: "memberRole",
102
+ render: (e) => e.memberRole === "ASSIGNEE" ? "指派人" : "會簽候選人",
103
+ title: "身分",
104
+ width: 120
105
+ }
106
+ ], []), ae = a(() => [
107
+ {
108
+ dataIndex: "instanceTitle",
109
+ key: "instanceTitle",
110
+ title: "案件",
111
+ width: 220
112
+ },
113
+ {
114
+ dataIndex: "outcomeLabel",
115
+ key: "outcomeLabel",
116
+ title: "結果",
117
+ width: 100
118
+ },
119
+ {
120
+ dataIndex: "message",
121
+ key: "message",
122
+ title: "說明",
123
+ width: 160
124
+ }
125
+ ], []), Y = () => {
126
+ k || c();
127
+ };
128
+ return /* @__PURE__ */ x(p, {
129
+ cancelText: "關閉",
130
+ confirmButtonProps: { disabled: !H || k },
131
+ confirmText: "確認改派",
132
+ loading: k,
133
+ modalType: "standard",
134
+ onCancel: Y,
135
+ onClose: Y,
136
+ onConfirm: () => {
137
+ K(!1);
138
+ },
139
+ open: !!e,
140
+ showModalFooter: !0,
141
+ showModalHeader: !0,
142
+ size: "regular",
143
+ title: e ? `改派待辦:${e.name}` : "改派待辦",
144
+ children: e ? /* @__PURE__ */ S("div", {
145
+ className: A.detailFields,
146
+ children: [
147
+ /* @__PURE__ */ x(v, {
148
+ variant: "body",
149
+ children: "改派會保留任務編號,但不產生簽核紀錄;原簽核人的待辦會結案為已轉交, 接手人會收到新的待辦通知。"
150
+ }),
151
+ F ? /* @__PURE__ */ x(v, {
152
+ color: "text-error",
153
+ variant: "body",
154
+ children: F
155
+ }) : null,
156
+ l.length ? /* @__PURE__ */ S(ne, { children: [/* @__PURE__ */ x(v, {
157
+ color: "text-neutral",
158
+ variant: "caption",
159
+ children: `已選 ${L.length}/${l.length} 筆`
160
+ }), /* @__PURE__ */ x(_, {
161
+ columns: J,
162
+ dataSource: l.map((e) => ({
163
+ ...e,
164
+ key: e.taskId
165
+ })),
166
+ fullWidth: !0,
167
+ loading: d,
168
+ rowSelection: {
169
+ hideSelectAll: k,
170
+ mode: "checkbox",
171
+ onChange: (e) => {
172
+ k || (h(e), E(null), O(null));
173
+ },
174
+ selectedRowKeys: [...L]
175
+ }
176
+ })] }) : /* @__PURE__ */ x(v, {
177
+ color: "text-neutral",
178
+ variant: "body",
179
+ children: d ? "載入待辦中…" : "此成員目前沒有待簽任務。"
180
+ }),
181
+ /* @__PURE__ */ x(t, {
182
+ label: "接手人",
183
+ name: "reassignTarget",
184
+ children: /* @__PURE__ */ x(n, {
185
+ name: "reassignTarget",
186
+ onChange: (e) => {
187
+ y(e), E(null), O(null);
188
+ },
189
+ placeholder: "搜尋接手人姓名或信箱",
190
+ value: g
191
+ })
192
+ }),
193
+ /* @__PURE__ */ x(t, {
194
+ label: "改派原因",
195
+ name: "reassignReason",
196
+ children: /* @__PURE__ */ x(te, {
197
+ fullWidth: !0,
198
+ name: "reassignReason",
199
+ onChange: (e) => {
200
+ C(e.target.value), E(null), O(null);
201
+ },
202
+ placeholder: "例如:原簽核人已離職",
203
+ value: b
204
+ })
205
+ }),
206
+ /* @__PURE__ */ S("div", {
207
+ className: A.membershipList,
208
+ children: [/* @__PURE__ */ x(v, {
209
+ color: "text-neutral",
210
+ variant: "caption",
211
+ children: "先按「預覽」確認每筆任務的結果,確認無誤後再按「確認改派」。"
212
+ }), /* @__PURE__ */ x("div", { children: /* @__PURE__ */ x(ee, {
213
+ disabled: k || !g || !z || L.length === 0,
214
+ onClick: () => {
215
+ K(!0);
216
+ },
217
+ variant: "base-secondary",
218
+ children: "預覽"
219
+ }) })]
220
+ }),
221
+ q.length ? /* @__PURE__ */ x(_, {
222
+ columns: ae,
223
+ dataSource: q,
224
+ fullWidth: !0
225
+ }) : null
226
+ ]
227
+ }) : null
228
+ });
229
+ }
230
+ function N(e) {
231
+ return e === "WOULD_REASSIGN" ? "會改派" : e === "REASSIGNED" ? "已改派" : "會被拒";
232
+ }
233
+ function P(e) {
234
+ return e instanceof Error ? e.message : "改派待辦失敗。";
235
+ }
236
+ // src/views/admin/users/AdminUsersView.tsx
237
+ var F = [
238
+ 10,
239
+ 20,
240
+ 50
241
+ ];
242
+ function I() {
243
+ let [e, t] = s(null), [n, c] = s([]), [ee, p] = s(null), [re, w] = s(null), [j, N] = s(null), [P, I] = s([]), [R, z] = s(null), [B, H] = s(!0), [U, W] = s(1), [G, ie] = s(10), [K, q] = s(0), [J, ae] = s([]), [Y, oe] = s([]), [se, ce] = s([]), [le, X] = s(null), [Z, ue] = s(""), de = a(() => new Map(Y.map((e) => [e.id, e])), [Y]), fe = a(() => new Map(se.map((e) => [e.id, e])), [se]), pe = r(async () => {
244
+ H(!0), N(null);
245
+ try {
246
+ let [e, t] = await Promise.all([y({
247
+ page: U,
248
+ pageSize: G,
249
+ searchText: Z
250
+ }), O()]);
251
+ ae(e.members), q(e.totalCount), oe(t.orgUnits), ce(t.positions);
252
+ } catch (e) {
253
+ N(V(e));
254
+ } finally {
255
+ H(!1);
256
+ }
257
+ }, [
258
+ U,
259
+ G,
260
+ Z
261
+ ]);
262
+ i(() => {
263
+ pe();
264
+ }, [pe]);
265
+ let Q = o(0), $ = r(async () => {
266
+ let e = Q.current + 1;
267
+ Q.current = e;
268
+ try {
269
+ let t = await C();
270
+ Q.current === e && (I(t), z(null));
271
+ } catch (t) {
272
+ Q.current === e && z(V(t));
273
+ }
274
+ }, []);
275
+ i(() => {
276
+ $();
277
+ }, [$]);
278
+ let me = a(() => P.map((e) => ({
279
+ ...e,
280
+ key: e.memberId
281
+ })), [P]), he = a(() => [
282
+ {
283
+ dataIndex: "name",
284
+ key: "name",
285
+ title: "姓名",
286
+ width: 160
287
+ },
288
+ {
289
+ dataIndex: "email",
290
+ key: "email",
291
+ title: "信箱",
292
+ width: 260
293
+ },
294
+ {
295
+ dataIndex: "openTaskCount",
296
+ key: "openTaskCount",
297
+ title: "待簽數",
298
+ width: 96
299
+ }
300
+ ], []), ge = a(() => ({
301
+ render: () => [{
302
+ name: "改派待辦",
303
+ onClick: (e) => {
304
+ X({
305
+ customFieldsJson: "{}",
306
+ email: e.email,
307
+ memberId: e.memberId,
308
+ name: e.name
309
+ });
310
+ }
311
+ }],
312
+ variant: "base-secondary",
313
+ width: 112
314
+ }), []), _e = a(() => J.map((e) => ({
315
+ ...e,
316
+ key: e.memberId
317
+ })), [J]), ve = r(async (e) => {
318
+ t(e), p(null), N(null);
319
+ try {
320
+ let [t, n] = await Promise.all([D({ memberId: e.memberId }), k(e.memberId)]);
321
+ c(t), w(n), p((await b(n.managerMemberId ? [n.managerMemberId] : []))[0] ?? null);
322
+ } catch (e) {
323
+ N(V(e));
324
+ }
325
+ }, []), ye = a(() => [{
326
+ dataIndex: "name",
327
+ key: "name",
328
+ title: "姓名",
329
+ width: 160
330
+ }, {
331
+ dataIndex: "email",
332
+ key: "email",
333
+ title: "信箱",
334
+ width: 260
335
+ }], []), be = a(() => ({
336
+ render: () => [{
337
+ name: "檢視",
338
+ onClick: (e) => {
339
+ ve(e);
340
+ }
341
+ }, {
342
+ name: "改派待辦",
343
+ onClick: (e) => {
344
+ X(e);
345
+ }
346
+ }],
347
+ variant: "base-secondary",
348
+ width: 176
349
+ }), [ve]);
350
+ function xe() {
351
+ t(null), p(null), c([]), w(null);
352
+ }
353
+ return /* @__PURE__ */ S(ne, { children: [
354
+ /* @__PURE__ */ x(m, { children: /* @__PURE__ */ x(E, {
355
+ description: "會員資料由 host member resolver 提供,BPM 僅維護組織歸屬與主管解析。",
356
+ title: "會員對照"
357
+ }) }),
358
+ /* @__PURE__ */ S(g, { children: [me.length || R ? /* @__PURE__ */ x(h, {
359
+ contentHeader: /* @__PURE__ */ x(E, {
360
+ description: "這些會員已停用,身上仍有待簽,請改派給在職的人。",
361
+ title: "已停用、仍有待簽的會員"
362
+ }),
363
+ children: /* @__PURE__ */ x("div", {
364
+ "data-inactive-members": "",
365
+ children: R ? /* @__PURE__ */ x(v, {
366
+ color: "text-error",
367
+ variant: "body",
368
+ children: R
369
+ }) : /* @__PURE__ */ x(_, {
370
+ actions: ge,
371
+ columns: he,
372
+ dataSource: me,
373
+ fullWidth: !0
374
+ })
375
+ })
376
+ }) : null, /* @__PURE__ */ S(h, {
377
+ filterArea: /* @__PURE__ */ x(u, {
378
+ className: A.memberFilterArea,
379
+ children: /* @__PURE__ */ x(d, { children: /* @__PURE__ */ x(l, {
380
+ span: 3,
381
+ children: /* @__PURE__ */ x(f, {
382
+ fullWidth: !0,
383
+ layout: T.VERTICAL,
384
+ name: "memberSearchText",
385
+ children: /* @__PURE__ */ x(te, {
386
+ fullWidth: !0,
387
+ onChange: (e) => {
388
+ ue(e.target.value), W(1);
389
+ },
390
+ placeholder: "搜尋姓名或信箱",
391
+ size: "sub",
392
+ value: Z,
393
+ variant: "base"
394
+ })
395
+ })
396
+ }) })
397
+ }),
398
+ children: [j ? /* @__PURE__ */ x(v, {
399
+ color: "text-error",
400
+ variant: "body",
401
+ children: j
402
+ }) : null, /* @__PURE__ */ x(_, {
403
+ actions: be,
404
+ columns: ye,
405
+ dataSource: _e,
406
+ fullWidth: !0,
407
+ loading: B,
408
+ pagination: {
409
+ current: U,
410
+ onChange: (e) => {
411
+ W(e);
412
+ },
413
+ onChangePageSize: (e) => {
414
+ W(1), ie(e);
415
+ },
416
+ pageSize: G,
417
+ pageSizeLabel: "每頁筆數",
418
+ pageSizeOptions: F,
419
+ renderResultSummary: (e, t, n) => `顯示 ${e}-${t} 筆,共 ${n} 筆`,
420
+ showPageSizeOptions: !0,
421
+ total: K
422
+ }
423
+ })]
424
+ })] }),
425
+ /* @__PURE__ */ x(M, {
426
+ member: le,
427
+ onClose: () => {
428
+ X(null), $();
429
+ }
430
+ }),
431
+ /* @__PURE__ */ x(L, {
432
+ managerProfile: ee,
433
+ member: e,
434
+ memberships: n,
435
+ onClose: xe,
436
+ orgUnitsById: de,
437
+ positionsById: fe,
438
+ resolvedManager: re
439
+ })
440
+ ] });
441
+ }
442
+ function L({ managerProfile: e, member: t, memberships: n, onClose: r, orgUnitsById: i, positionsById: a, resolvedManager: o }) {
443
+ return /* @__PURE__ */ x(p, {
444
+ cancelText: "關閉",
445
+ confirmText: "關閉",
446
+ modalType: "standard",
447
+ onCancel: r,
448
+ onClose: r,
449
+ onConfirm: r,
450
+ open: !!t,
451
+ showModalFooter: !0,
452
+ showModalHeader: !0,
453
+ size: "regular",
454
+ title: t?.name ?? "會員明細",
455
+ children: t ? /* @__PURE__ */ S("div", {
456
+ className: A.detailFields,
457
+ children: [
458
+ /* @__PURE__ */ x(c, {
459
+ title: "基本資料",
460
+ children: /* @__PURE__ */ x("div", {
461
+ className: A.detailSection,
462
+ children: /* @__PURE__ */ S(v, {
463
+ variant: "body",
464
+ children: ["信箱:", t.email?.trim() ? t.email : "未設定"]
465
+ })
466
+ })
467
+ }),
468
+ /* @__PURE__ */ x(c, {
469
+ title: "BPM 組織歸屬",
470
+ children: /* @__PURE__ */ x("div", {
471
+ className: A.membershipList,
472
+ children: n.length ? n.map((e) => /* @__PURE__ */ S(v, {
473
+ variant: "body",
474
+ children: [
475
+ R(i.get(e.orgUnitId)),
476
+ " / ",
477
+ e.positionId ? z(a.get(e.positionId)) : "未指定職位",
478
+ " / ",
479
+ e.isPrimary ? "主要" : "一般"
480
+ ]
481
+ }, e.id)) : /* @__PURE__ */ x(v, {
482
+ color: "text-neutral",
483
+ variant: "body",
484
+ children: "尚未建立 BPM 組織歸屬"
485
+ })
486
+ })
487
+ }),
488
+ /* @__PURE__ */ x(c, {
489
+ title: "主管解析",
490
+ children: /* @__PURE__ */ x(v, {
491
+ variant: "body",
492
+ children: o?.managerMemberId ? B(e) : "尚未解析到主管"
493
+ })
494
+ })
495
+ ]
496
+ }) : null
497
+ });
498
+ }
499
+ function R(e) {
500
+ return e ? `${e.name} · ${e.code}` : "未知組織";
501
+ }
502
+ function z(e) {
503
+ return e ? `${e.name} · ${e.code}` : "未知職位";
504
+ }
505
+ function B(t) {
506
+ return t ? e(t.name, t.email, "dot") : "主管資料尚未載入";
507
+ }
508
+ function V(e) {
509
+ return e instanceof Error ? e.message : "讀取會員資料失敗。";
510
+ }
511
+ export { I as t };
512
+
513
+ //# sourceMappingURL=users-wgM3TqU3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users-wgM3TqU3.js","names":["readErrorMessage","styles","_Fragment","_Fragment","styles","formatMemberLabel","MemberPicker","Fragment$1","ContentHeader","users_module_default","TASK_GONE_LABEL","MemberTaskReassignModal","tasks","setTasks","useState","tasksLoading","setTasksLoading","checkedIds","setCheckedIds","target","setTarget","reason","setReason","preview","setPreview","committed","setCommitted","busy","setBusy","error","setError","selectedIds","useMemo","checked","task","selectionKey","trimmedReason","inputKey","previewIsCurrent","canConfirm","result","latestRequestRef","useRef","shownMemberIdRef","loadTasks","useCallback","request","loaded","listMemberOpenTasks","memberId","kept","keepCheckedIds","taskId","requestError","readErrorMessage$1","member","titleById","runReassignment","sentTaskIds","sentTitleById","sentMemberId","outcomes","reassignMemberTasks","dryRun","shownResultRows","shown","returnedIds","returnedRows","readOutcomeLabel","goneRows","taskColumns","record","resultColumns","handleClose","onClose","Modal","Typography","Table","selectedRowKeys","BPMFormField","option","Input","event","Button","outcome","MEMBER_PAGE_SIZE_OPTIONS","AdminUsersView","detailMember","setDetailMember","detailMemberships","setDetailMemberships","detailManagerProfile","setDetailManagerProfile","detailResolvedManager","setDetailResolvedManager","inactiveMembers","setInactiveMembers","inactiveMembersError","setInactiveMembersError","loading","setLoading","memberPage","setMemberPage","memberPageSize","setMemberPageSize","memberTotalCount","setMemberTotalCount","members","setMembers","orgUnits","setOrgUnits","positions","setPositions","reassignMember","setReassignMember","searchText","setSearchText","orgUnitsById","orgUnit","positionsById","position","refreshMembers","memberPageResult","organization","listMemberDirectoryPage","readOrganizationDashboard","readErrorMessage","latestInactiveRequestRef","refreshInactiveMembers","listInactiveMembersWithOpenTasks","inactiveMemberRows","inactiveMemberColumns","inactiveMemberActions","rows","openDetail","memberships","resolvedManager","listMemberships","readResolvedManager","resolveMembers","columns","tableActions","closeDetail","PageHeader","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","page","pageSize","from","to","total","MemberDetailModal","BaseCard","readOrgUnitLabel","membership","readPositionLabel","readMemberLabel","managerProfile"],"sources":["../../src/views/admin/users/MemberTaskReassignModal.tsx","../../src/views/admin/users/AdminUsersView.tsx"],"sourcesContent":["'use client';\n\nimport {\n ChangeEvent,\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Button, Input, Modal, Table, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type { MemberProfileRecord } from '@rytass/bpm-core-client';\nimport {\n listMemberOpenTasks,\n type MemberOpenTaskRecord,\n reassignMemberTasks,\n type TaskReassignmentResultRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { MemberOption, MemberPicker } from '../../../components/admin-pickers';\nimport styles from './users.module.scss';\n\ntype TaskRow = Readonly<\n Record<string, unknown> &\n MemberOpenTaskRecord & {\n key: string;\n }\n>;\n\ntype ResultRow = Readonly<\n Record<string, unknown> & {\n instanceTitle: string;\n key: string;\n message: string | null;\n outcomeLabel: string;\n }\n>;\n\n/**\n * Both states keep what was sent and the titles it was sent with: the server\n * skips an id the member no longer holds (no result row for it), and a commit\n * reloads the task list, so neither can be recovered from the current list.\n */\ninterface PreviewState {\n readonly inputKey: string;\n readonly results: readonly TaskReassignmentResultRecord[];\n readonly sentTaskIds: readonly string[];\n readonly titleById: ReadonlyMap<string, string>;\n}\n\ninterface CommittedState {\n readonly results: readonly TaskReassignmentResultRecord[];\n readonly sentTaskIds: readonly string[];\n readonly titleById: ReadonlyMap<string, string>;\n}\n\nconst TASK_GONE_LABEL = '已不在此人的待辦中';\n\n/**\n * Administrator reassignment of a member's open tasks. Lists what the member\n * holds, takes a target and a reason, previews every task's outcome (dry run),\n * and only then commits. Confirm stays disabled until the preview matches the\n * current target and reason. Replacing a seat is not a decision: no signature\n * is written, and the task keeps its id.\n */\nexport function MemberTaskReassignModal({\n member,\n onClose,\n}: {\n readonly member: MemberProfileRecord | null;\n readonly onClose: () => void;\n}): ReactElement {\n const [tasks, setTasks] = useState<readonly MemberOpenTaskRecord[]>([]);\n const [tasksLoading, setTasksLoading] = useState(false);\n const [checkedIds, setCheckedIds] = useState<readonly string[]>([]);\n const [target, setTarget] = useState<MemberOption | null>(null);\n const [reason, setReason] = useState('');\n const [preview, setPreview] = useState<PreviewState | null>(null);\n const [committed, setCommitted] = useState<CommittedState | null>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // The ids to send are the checked ones that the current list still holds, so\n // a stale check (other member, reloaded list) never reaches the server.\n const selectedIds = useMemo((): readonly string[] => {\n const checked = new Set(checkedIds);\n\n return tasks\n .filter((task) => checked.has(task.taskId))\n .map((task) => task.taskId);\n }, [tasks, checkedIds]);\n const selectionKey = [...selectedIds].sort().join(',');\n const trimmedReason = reason.trim();\n const inputKey = `${target?.id ?? ''}|${trimmedReason}|${selectionKey}`;\n const previewIsCurrent = preview !== null && preview.inputKey === inputKey;\n const canConfirm =\n preview !== null &&\n previewIsCurrent &&\n selectedIds.length > 0 &&\n preview.results.some((result) => result.outcome === 'WOULD_REASSIGN');\n\n // Only the latest request may write: switching members while an earlier\n // listing is in flight must not let its late answer replace the current one.\n const latestRequestRef = useRef(0);\n // The member on screen now. A reassignment that answers after the member\n // changed belongs to the earlier one and must not write: the counter above\n // only orders requests, and the commit's reload would be the latest one.\n const shownMemberIdRef = useRef<string | null>(null);\n\n // `keepCheckedIds` is the selection to carry over after a reassignment;\n // without it (a fresh member) every task starts selected.\n const loadTasks = useCallback(\n async (\n memberId: string,\n keepCheckedIds?: readonly string[],\n ): Promise<void> => {\n const request = latestRequestRef.current + 1;\n\n latestRequestRef.current = request;\n setTasksLoading(true);\n\n try {\n const loaded = await listMemberOpenTasks(memberId);\n\n if (latestRequestRef.current === request) {\n const kept = keepCheckedIds ? new Set(keepCheckedIds) : null;\n\n setTasks(loaded);\n // Never select a task the administrator had left out: after a partial\n // reassignment only what they chose and still holds stays selected.\n setCheckedIds(\n loaded\n .map((task) => task.taskId)\n .filter((taskId) => !kept || kept.has(taskId)),\n );\n }\n } catch (requestError: unknown) {\n if (latestRequestRef.current === request) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (latestRequestRef.current === request) {\n setTasksLoading(false);\n }\n }\n },\n [],\n );\n\n useEffect((): void => {\n shownMemberIdRef.current = member?.memberId ?? null;\n setTarget(null);\n setReason('');\n setPreview(null);\n setCommitted(null);\n setError(null);\n\n if (!member) {\n latestRequestRef.current += 1;\n setTasks([]);\n setTasksLoading(false);\n\n return;\n }\n\n setTasks([]);\n // Only clears; selecting everything again happens inside loadTasks (its\n // latest-request guard), once the new member's list has arrived.\n setCheckedIds([]);\n void loadTasks(member.memberId);\n }, [member, loadTasks]);\n\n const titleById = useMemo(\n (): ReadonlyMap<string, string> =>\n new Map(tasks.map((task) => [task.taskId, task.instanceTitle])),\n [tasks],\n );\n\n async function runReassignment(dryRun: boolean): Promise<void> {\n if (!member || !target || !trimmedReason || selectedIds.length === 0) {\n return;\n }\n\n // Snapshot at click time: the request, the preview key and the titles all\n // describe the same selection even if the list reloads while we wait.\n const sentTaskIds = selectedIds;\n const sentTitleById = titleById;\n const sentMemberId = member.memberId;\n\n setBusy(true);\n setError(null);\n\n try {\n const outcomes = await reassignMemberTasks({\n dryRun,\n fromMemberId: sentMemberId,\n reason: trimmedReason,\n taskIds: sentTaskIds,\n toMemberId: target.id,\n });\n\n if (shownMemberIdRef.current !== sentMemberId) {\n return;\n }\n\n if (dryRun) {\n setPreview({\n inputKey,\n results: outcomes,\n sentTaskIds,\n titleById: sentTitleById,\n });\n setCommitted(null);\n } else {\n setCommitted({\n results: outcomes,\n sentTaskIds,\n titleById: sentTitleById,\n });\n setPreview(null);\n await loadTasks(sentMemberId, sentTaskIds);\n }\n } catch (requestError: unknown) {\n if (shownMemberIdRef.current === sentMemberId) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n setBusy(false);\n }\n }\n\n const shownResultRows = useMemo((): ResultRow[] => {\n const shown = committed ?? preview;\n\n if (!shown) {\n return [];\n }\n\n const returnedIds = new Set(shown.results.map((result) => result.taskId));\n const returnedRows = shown.results.map(\n (result): ResultRow => ({\n instanceTitle: shown.titleById.get(result.taskId) ?? result.taskId,\n key: result.taskId,\n message: result.message,\n outcomeLabel: readOutcomeLabel(result.outcome),\n }),\n );\n // Sent but not answered: the member no longer holds it, so the server\n // returns no row. Show it instead of letting the selection silently shrink.\n const goneRows = shown.sentTaskIds\n .filter((taskId) => !returnedIds.has(taskId))\n .map(\n (taskId): ResultRow => ({\n instanceTitle: shown.titleById.get(taskId) ?? taskId,\n key: `gone:${taskId}`,\n message: null,\n outcomeLabel: TASK_GONE_LABEL,\n }),\n );\n\n return [...returnedRows, ...goneRows];\n }, [committed, preview]);\n\n const taskColumns = useMemo(\n (): TableColumn<TaskRow>[] => [\n {\n dataIndex: 'instanceTitle',\n key: 'instanceTitle',\n title: '案件',\n width: 220,\n },\n {\n dataIndex: 'nodeLabel',\n key: 'nodeLabel',\n title: '節點',\n width: 160,\n },\n {\n key: 'memberRole',\n render: (record: TaskRow): string =>\n record.memberRole === 'ASSIGNEE' ? '指派人' : '會簽候選人',\n title: '身分',\n width: 120,\n },\n ],\n [],\n );\n const resultColumns = useMemo(\n (): TableColumn<ResultRow>[] => [\n {\n dataIndex: 'instanceTitle',\n key: 'instanceTitle',\n title: '案件',\n width: 220,\n },\n {\n dataIndex: 'outcomeLabel',\n key: 'outcomeLabel',\n title: '結果',\n width: 100,\n },\n {\n dataIndex: 'message',\n key: 'message',\n title: '說明',\n width: 160,\n },\n ],\n [],\n );\n\n // The backdrop hides the member table, so closing is the only way `member`\n // changes. While a request is in flight every close path is a no-op, which\n // closes the window where a late answer writes into another member's view.\n const handleClose = (): void => {\n if (busy) {\n return;\n }\n\n onClose();\n };\n\n return (\n <Modal\n cancelText=\"關閉\"\n confirmButtonProps={{ disabled: !canConfirm || busy }}\n confirmText=\"確認改派\"\n loading={busy}\n modalType=\"standard\"\n onCancel={handleClose}\n onClose={handleClose}\n onConfirm={(): void => {\n void runReassignment(false);\n }}\n open={Boolean(member)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={member ? `改派待辦:${member.name}` : '改派待辦'}\n >\n {member ? (\n <div className={styles.detailFields}>\n <Typography variant=\"body\">\n 改派會保留任務編號,但不產生簽核紀錄;原簽核人的待辦會結案為已轉交,\n 接手人會收到新的待辦通知。\n </Typography>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {tasks.length ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n {`已選 ${selectedIds.length}/${tasks.length} 筆`}\n </Typography>\n <Table\n columns={taskColumns}\n dataSource={tasks.map((task): TaskRow => ({\n ...task,\n key: task.taskId,\n }))}\n fullWidth\n loading={tasksLoading}\n rowSelection={{\n hideSelectAll: busy,\n mode: 'checkbox',\n onChange: (selectedRowKeys: string[]): void => {\n if (busy) {\n return;\n }\n\n setCheckedIds(selectedRowKeys);\n setPreview(null);\n setCommitted(null);\n },\n selectedRowKeys: [...selectedIds],\n }}\n />\n </>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n {tasksLoading ? '載入待辦中…' : '此成員目前沒有待簽任務。'}\n </Typography>\n )}\n <BPMFormField label=\"接手人\" name=\"reassignTarget\">\n <MemberPicker\n name=\"reassignTarget\"\n onChange={(option): void => {\n setTarget(option);\n setPreview(null);\n setCommitted(null);\n }}\n placeholder=\"搜尋接手人姓名或信箱\"\n value={target}\n />\n </BPMFormField>\n <BPMFormField label=\"改派原因\" name=\"reassignReason\">\n <Input\n fullWidth\n name=\"reassignReason\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setReason(event.target.value);\n setPreview(null);\n setCommitted(null);\n }}\n placeholder=\"例如:原簽核人已離職\"\n value={reason}\n />\n </BPMFormField>\n <div className={styles.membershipList}>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先按「預覽」確認每筆任務的結果,確認無誤後再按「確認改派」。\n </Typography>\n <div>\n <Button\n disabled={\n busy ||\n !target ||\n !trimmedReason ||\n selectedIds.length === 0\n }\n onClick={(): void => {\n void runReassignment(true);\n }}\n variant=\"base-secondary\"\n >\n 預覽\n </Button>\n </div>\n </div>\n {shownResultRows.length ? (\n <Table\n columns={resultColumns}\n dataSource={shownResultRows}\n fullWidth\n />\n ) : null}\n </div>\n ) : null}\n </Modal>\n );\n}\n\nfunction readOutcomeLabel(\n outcome: TaskReassignmentResultRecord['outcome'],\n): string {\n if (outcome === 'WOULD_REASSIGN') {\n return '會改派';\n }\n\n if (outcome === 'REASSIGNED') {\n return '已改派';\n }\n\n return '會被拒';\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '改派待辦失敗。';\n}\n","'use client';\n\nimport {\n ChangeEvent,\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\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 { formatMemberLabel } from '../../../lib/format-member-label';\nimport styles from './users.module.scss';\nimport { MemberTaskReassignModal } from './MemberTaskReassignModal';\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';\nimport {\n type InactiveMemberWithOpenTasksRecord,\n listInactiveMembersWithOpenTasks,\n} from '@rytass/bpm-core-client/workflow';\n\ntype MemberRow = Readonly<\n Record<string, unknown> &\n MemberProfileRecord & {\n key: string;\n }\n>;\n\ntype InactiveMemberRow = Readonly<\n Record<string, unknown> &\n InactiveMemberWithOpenTasksRecord & {\n key: string;\n }\n>;\n\nconst MEMBER_PAGE_SIZE_OPTIONS = [10, 20, 50];\n\nexport function AdminUsersView(): ReactElement {\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 [inactiveMembers, setInactiveMembers] = useState<\n readonly InactiveMemberWithOpenTasksRecord[]\n >([]);\n const [inactiveMembersError, setInactiveMembersError] = useState<\n string | null\n >(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 [reassignMember, setReassignMember] =\n useState<MemberProfileRecord | null>(null);\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 latestInactiveRequestRef = useRef(0);\n\n // Loaded on its own so a failure here leaves the member directory usable.\n // Only the latest request may write: a reload started when the reassignment\n // closes must not be overwritten by an earlier one answering late.\n const refreshInactiveMembers = useCallback(async (): Promise<void> => {\n const request = latestInactiveRequestRef.current + 1;\n\n latestInactiveRequestRef.current = request;\n\n try {\n const loaded = await listInactiveMembersWithOpenTasks();\n\n if (latestInactiveRequestRef.current === request) {\n setInactiveMembers(loaded);\n setInactiveMembersError(null);\n }\n } catch (requestError: unknown) {\n if (latestInactiveRequestRef.current === request) {\n setInactiveMembersError(readErrorMessage(requestError));\n }\n }\n }, []);\n\n useEffect((): void => {\n void refreshInactiveMembers();\n }, [refreshInactiveMembers]);\n\n const inactiveMemberRows = useMemo(\n (): InactiveMemberRow[] =>\n inactiveMembers.map(\n (member): InactiveMemberRow => ({ ...member, key: member.memberId }),\n ),\n [inactiveMembers],\n );\n const inactiveMemberColumns = useMemo(\n (): TableColumn<InactiveMemberRow>[] => [\n { dataIndex: 'name', key: 'name', title: '姓名', width: 160 },\n { dataIndex: 'email', key: 'email', title: '信箱', width: 260 },\n {\n dataIndex: 'openTaskCount',\n key: 'openTaskCount',\n title: '待簽數',\n width: 96,\n },\n ],\n [],\n );\n const inactiveMemberActions = useMemo(\n (): TableActions<InactiveMemberRow> => ({\n render: (): ReturnType<TableActions<InactiveMemberRow>['render']> => [\n {\n name: '改派待辦',\n onClick: (record): void => {\n setReassignMember({\n customFieldsJson: '{}',\n email: record.email,\n memberId: record.memberId,\n name: record.name,\n });\n },\n },\n ],\n variant: 'base-secondary',\n width: 112,\n }),\n [],\n );\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 name: '改派待辦',\n onClick: (record): void => {\n setReassignMember(record);\n },\n },\n ],\n variant: 'base-secondary',\n width: 176,\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 <>\n <PageHeader>\n <ContentHeader\n description=\"會員資料由 host member resolver 提供,BPM 僅維護組織歸屬與主管解析。\"\n title=\"會員對照\"\n />\n </PageHeader>\n\n <SectionGroup>\n {inactiveMemberRows.length || inactiveMembersError ? (\n <Section\n contentHeader={\n <ContentHeader\n description=\"這些會員已停用,身上仍有待簽,請改派給在職的人。\"\n title=\"已停用、仍有待簽的會員\"\n />\n }\n >\n <div data-inactive-members=\"\">\n {inactiveMembersError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {inactiveMembersError}\n </Typography>\n ) : (\n <Table\n actions={inactiveMemberActions}\n columns={inactiveMemberColumns}\n dataSource={inactiveMemberRows}\n fullWidth\n />\n )}\n </div>\n </Section>\n ) : null}\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 <MemberTaskReassignModal\n member={reassignMember}\n onClose={(): void => {\n setReassignMember(null);\n // A reassignment may have cleared someone off the list.\n void refreshInactiveMembers();\n }}\n />\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 </>\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\">\n 信箱:{member.email?.trim() ? member.email : '未設定'}\n </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\n ? formatMemberLabel(member.name, member.email, 'dot')\n : '主管資料尚未載入';\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取會員資料失敗。';\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});require('./index.css');const e=require("./chunks/auth-provider-4BeCw7cI.cjs"),t=require("./chunks/format-date-time-D-cx5M8z.cjs"),n=require("./chunks/organization-time-zone-provider-B7CXQril.cjs"),r=require("./chunks/providers-VUOh6i0i.cjs"),i=require("./chunks/router-adapter--gYs13E8.cjs"),a=require("./chunks/routes-config-C1j_vFKo.cjs"),o=require("./chunks/use-bpm-member-DpNAQtNC.cjs"),s=require("./chunks/admin-pickers-BjbkBpSJ.cjs"),c=require("./chunks/approval-instance-list-page-Cv5I1YPX.cjs"),l=require("./chunks/bpm-form-field-Bc6k4ZEO.cjs"),u=require("./chunks/dashboard-page-D7YJ3udk.cjs");let d=require("@mezzanine-ui/react"),f=require("react/jsx-runtime"),p=require("@mezzanine-ui/icons");function m(){let{logout:t}=e.n();return t}var h={root:`bpm_root_jl5S-`,badge:`bpm_badge_SIKJk`};function g({label:e=`通知中心`}={}){let{open:t}=r.o(),{unreadCount:n}=r.i(),i=n>0?`${e},${n} 則未讀`:e;return(0,f.jsxs)(`span`,{className:h.root,children:[(0,f.jsx)(d.NavigationIconButton,{"aria-label":i,icon:p.NotificationUnreadIcon,onClick:()=>{t()},title:e,type:`button`}),n>0?(0,f.jsx)(`span`,{className:h.badge,children:n>99?`99+`:n}):null]})}exports.ApprovalInstanceListPage=c.t,exports.AuthProvider=e.t,exports.BPMFormField=l.t,exports.BPMLanguageProvider=n.r,exports.BPMNotificationBellButton=g,exports.BPMOrganizationTimeZoneProvider=n.t,exports.BPMRoutesProvider=a.t,exports.BPM_LANGUAGES=n.i,exports.DEFAULT_BPM_LANGUAGE=n.a,exports.DashboardPage=u.t,exports.MemberPicker=s.t,exports.NotificationDrawer=r.n,exports.NotificationDrawerProvider=r.a,exports.NotificationUnreadProvider=r.r,exports.OrgUnitPicker=s.n,exports.PositionPicker=s.r,exports.Providers=r.t,exports.RouterAdapterProvider=i.t,exports.createDefaultBPMRoutes=a.n,exports.defaultBrowserSearchParams=i.n,exports.formatDateTime=t.t,exports.isBPMAdminMember=o.t,exports.readMemberOption=s.i,exports.readOrgUnitOption=s.a,exports.readPositionOption=s.o,exports.useAuth=e.n,exports.useBPMLanguage=n.o,exports.useBPMLogout=m,exports.useBPMMember=o.n,exports.useBPMOrganizationTimeZone=n.n,exports.useBPMRoutes=a.r,exports.useNotificationDrawer=r.o,exports.useNotificationUnread=r.i,exports.useRouterAdapter=i.r;
1
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});require('./index.css');const e=require("./chunks/auth-provider-4BeCw7cI.cjs"),t=require("./chunks/format-date-time-D-cx5M8z.cjs"),n=require("./chunks/organization-time-zone-provider-B7CXQril.cjs"),r=require("./chunks/providers-Dz4Wqxr6.cjs"),i=require("./chunks/router-adapter--gYs13E8.cjs"),a=require("./chunks/routes-config-BWjZDAU3.cjs"),o=require("./chunks/use-bpm-member-DpNAQtNC.cjs"),s=require("./chunks/admin-pickers-BjbkBpSJ.cjs"),c=require("./chunks/approval-instance-list-page-BqkG9jiR.cjs"),l=require("./chunks/bpm-form-field-Bc6k4ZEO.cjs"),u=require("./chunks/dashboard-page-lqlLELKs.cjs");let d=require("@mezzanine-ui/react"),f=require("react/jsx-runtime"),p=require("@mezzanine-ui/icons");function m(){let{logout:t}=e.n();return t}var h={root:`bpm_root_jl5S-`,badge:`bpm_badge_SIKJk`};function g({label:e=`通知中心`}={}){let{open:t}=r.o(),{unreadCount:n}=r.i(),i=n>0?`${e},${n} 則未讀`:e;return(0,f.jsxs)(`span`,{className:h.root,children:[(0,f.jsx)(d.NavigationIconButton,{"aria-label":i,icon:p.NotificationUnreadIcon,onClick:()=>{t()},title:e,type:`button`}),n>0?(0,f.jsx)(`span`,{className:h.badge,children:n>99?`99+`:n}):null]})}exports.ApprovalInstanceListPage=c.t,exports.AuthProvider=e.t,exports.BPMFormField=l.t,exports.BPMLanguageProvider=n.r,exports.BPMNotificationBellButton=g,exports.BPMOrganizationTimeZoneProvider=n.t,exports.BPMRoutesProvider=a.t,exports.BPM_LANGUAGES=n.i,exports.DEFAULT_BPM_LANGUAGE=n.a,exports.DashboardPage=u.t,exports.MemberPicker=s.t,exports.NotificationDrawer=r.n,exports.NotificationDrawerProvider=r.a,exports.NotificationUnreadProvider=r.r,exports.OrgUnitPicker=s.n,exports.PositionPicker=s.r,exports.Providers=r.t,exports.RouterAdapterProvider=i.t,exports.createDefaultBPMRoutes=a.n,exports.defaultBrowserSearchParams=i.n,exports.formatDateTime=t.t,exports.isBPMAdminMember=o.t,exports.readMemberOption=s.i,exports.readOrgUnitOption=s.a,exports.readPositionOption=s.o,exports.useAuth=e.n,exports.useBPMLanguage=n.o,exports.useBPMLogout=m,exports.useBPMMember=o.n,exports.useBPMOrganizationTimeZone=n.n,exports.useBPMRoutes=a.r,exports.useNotificationDrawer=r.o,exports.useNotificationUnread=r.i,exports.useRouterAdapter=i.r;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.js CHANGED
@@ -2,14 +2,14 @@
2
2
  import { n as e, t } from "./chunks/auth-provider-C2b-5mGt.js";
3
3
  import { t as n } from "./chunks/format-date-time-B0LdmWg4.js";
4
4
  import { a as r, i, n as a, o, r as s, t as c } from "./chunks/organization-time-zone-provider-DNL8yo4-.js";
5
- import { a as l, i as u, n as d, o as f, r as p, t as m } from "./chunks/providers-CQWekD7_.js";
5
+ import { a as l, i as u, n as d, o as f, r as p, t as m } from "./chunks/providers-D35lBOTd.js";
6
6
  import { n as h, r as g, t as _ } from "./chunks/router-adapter-CkxCyzf5.js";
7
- import { n as v, r as y, t as b } from "./chunks/routes-config-BcNaWJWJ.js";
7
+ import { n as v, r as y, t as b } from "./chunks/routes-config-DjEOE9eP.js";
8
8
  import { n as x, t as S } from "./chunks/use-bpm-member-BPzcNU1g.js";
9
9
  import { a as C, i as w, n as T, o as E, r as D, t as O } from "./chunks/admin-pickers-DfGxsjpp.js";
10
- import { t as k } from "./chunks/approval-instance-list-page-BI5fIXc-.js";
10
+ import { t as k } from "./chunks/approval-instance-list-page-CsSpIN4C.js";
11
11
  import { t as A } from "./chunks/bpm-form-field-9B-Det0u.js";
12
- import { t as j } from "./chunks/dashboard-page-BoqNhjT_.js";
12
+ import { t as j } from "./chunks/dashboard-page-DBJCsPya.js";
13
13
  import { NavigationIconButton as M } from "@mezzanine-ui/react";
14
14
  import { jsx as N, jsxs as P } from "react/jsx-runtime";
15
15
  import { NotificationUnreadIcon as F } from "@mezzanine-ui/icons";
@@ -80,6 +80,8 @@ export interface BPMRoutes {
80
80
  adminDelegations(): string;
81
81
  /** Admin: database-managed notify webhook endpoints (ADR 18). */
82
82
  adminWebhookEndpoints(): string;
83
+ /** Admin: approval instances stuck after a failed advance, with cancel. */
84
+ adminStuckInstances(): string;
83
85
  }
84
86
  /**
85
87
  * Factory for the default `BPMRoutes` value. Reproduces the exact path
@@ -80,6 +80,8 @@ export interface BPMRoutes {
80
80
  adminDelegations(): string;
81
81
  /** Admin: database-managed notify webhook endpoints (ADR 18). */
82
82
  adminWebhookEndpoints(): string;
83
+ /** Admin: approval instances stuck after a failed advance, with cancel. */
84
+ adminStuckInstances(): string;
83
85
  }
84
86
  /**
85
87
  * Factory for the default `BPMRoutes` value. Reproduces the exact path