@rytass/bpm-core-react 0.16.2 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +54 -6
  3. package/dist/chunks/{compose-DO6n0NJi.js → compose-Crklayzy.js} +2 -2
  4. package/dist/chunks/{compose-DO6n0NJi.js.map → compose-Crklayzy.js.map} +1 -1
  5. package/dist/chunks/{compose-DUH9cQ-L.cjs → compose-DZ7RKvUp.cjs} +2 -2
  6. package/dist/chunks/{compose-DUH9cQ-L.cjs.map → compose-DZ7RKvUp.cjs.map} +1 -1
  7. package/dist/chunks/{delegations-BLzYnOae.cjs → delegations-V9HIe3_P.cjs} +2 -2
  8. package/dist/chunks/delegations-V9HIe3_P.cjs.map +1 -0
  9. package/dist/chunks/{delegations-_b4_xBit.js → delegations-xUt1tj8d.js} +2 -1
  10. package/dist/chunks/{delegations-_b4_xBit.js.map → delegations-xUt1tj8d.js.map} +1 -1
  11. package/dist/chunks/{designer-B-cfiob9.js → designer-D9eFma1W.js} +1002 -948
  12. package/dist/chunks/designer-D9eFma1W.js.map +1 -0
  13. package/dist/chunks/designer-sJGTGYOf.cjs +65 -0
  14. package/dist/chunks/designer-sJGTGYOf.cjs.map +1 -0
  15. package/dist/chunks/detail-DRCTnuKm.cjs +2 -0
  16. package/dist/chunks/detail-DRCTnuKm.cjs.map +1 -0
  17. package/dist/chunks/{detail-C6NdVijG.js → detail-DScLf42P.js} +183 -156
  18. package/dist/chunks/detail-DScLf42P.js.map +1 -0
  19. package/dist/chunks/{orgs-Bpp1U60k.js → orgs-CY0i1fie.js} +583 -543
  20. package/dist/chunks/orgs-CY0i1fie.js.map +1 -0
  21. package/dist/chunks/orgs-Dr0FFoZo.cjs +2 -0
  22. package/dist/chunks/orgs-Dr0FFoZo.cjs.map +1 -0
  23. package/dist/chunks/users-BCyePbwB.js +422 -0
  24. package/dist/chunks/users-BCyePbwB.js.map +1 -0
  25. package/dist/chunks/users-DVBJluFR.cjs +2 -0
  26. package/dist/chunks/users-DVBJluFR.cjs.map +1 -0
  27. package/dist/pages/admin/delegations/index.cjs +1 -1
  28. package/dist/pages/admin/delegations/index.js +1 -1
  29. package/dist/pages/admin/orgs/index.cjs +1 -1
  30. package/dist/pages/admin/orgs/index.js +1 -1
  31. package/dist/pages/admin/users/index.cjs +1 -1
  32. package/dist/pages/admin/users/index.js +1 -1
  33. package/dist/pages/instances/detail/index.cjs +1 -1
  34. package/dist/pages/instances/detail/index.js +1 -1
  35. package/dist/pages/templates/compose/index.cjs +1 -1
  36. package/dist/pages/templates/compose/index.js +1 -1
  37. package/dist/pages/templates/designer/index.cjs +1 -1
  38. package/dist/pages/templates/designer/index.js +1 -1
  39. package/dist/views/admin/delegations/index.cjs +1 -1
  40. package/dist/views/admin/delegations/index.js +1 -1
  41. package/dist/views/admin/index.cjs +1 -1
  42. package/dist/views/admin/index.js +3 -3
  43. package/dist/views/admin/orgs/index.cjs +1 -1
  44. package/dist/views/admin/orgs/index.js +1 -1
  45. package/dist/views/admin/users/MemberTaskReassignModal.d.ts +13 -0
  46. package/dist/views/admin/users/index.cjs +1 -1
  47. package/dist/views/admin/users/index.js +1 -1
  48. package/dist/views/instances/detail/index.cjs +1 -1
  49. package/dist/views/instances/detail/index.js +1 -1
  50. package/dist/views/templates/compose/index.cjs +1 -1
  51. package/dist/views/templates/compose/index.js +1 -1
  52. package/dist/views/templates/designer/index.cjs +1 -1
  53. package/dist/views/templates/designer/index.js +1 -1
  54. package/package.json +3 -3
  55. package/dist/chunks/delegations-BLzYnOae.cjs.map +0 -1
  56. package/dist/chunks/designer-2YvjP_GU.cjs +0 -65
  57. package/dist/chunks/designer-2YvjP_GU.cjs.map +0 -1
  58. package/dist/chunks/designer-B-cfiob9.js.map +0 -1
  59. package/dist/chunks/detail-C6NdVijG.js.map +0 -1
  60. package/dist/chunks/detail-DKobK4Cg.cjs +0 -2
  61. package/dist/chunks/detail-DKobK4Cg.cjs.map +0 -1
  62. package/dist/chunks/orgs-Bpp1U60k.js.map +0 -1
  63. package/dist/chunks/orgs-ywaE1_02.cjs +0 -2
  64. package/dist/chunks/orgs-ywaE1_02.cjs.map +0 -1
  65. package/dist/chunks/users-BSVo_eNe.js +0 -215
  66. package/dist/chunks/users-BSVo_eNe.js.map +0 -1
  67. package/dist/chunks/users-DFSBTDMy.cjs +0 -2
  68. package/dist/chunks/users-DFSBTDMy.cjs.map +0 -1
@@ -1,215 +0,0 @@
1
- "use client";
2
- import { t as e } from "./format-member-label-DudVI55w.js";
3
- import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
4
- import { BaseCard as a, Filter as o, FilterArea as s, FilterLine as c, FormField as l, Input as u, Modal as d, PageHeader as f, Section as p, SectionGroup as ee, Table as m, Typography as h } from "@mezzanine-ui/react";
5
- import { listMemberDirectoryPage as g, resolveMembers as _ } from "@rytass/bpm-core-client";
6
- import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
7
- import { FormFieldLayout as x } from "@mezzanine-ui/core/form";
8
- import S from "@mezzanine-ui/react/ContentHeader";
9
- import { listMemberships as C, readOrganizationDashboard as w, readResolvedManager as T } from "@rytass/bpm-core-client/organization";
10
- import '../users.css';var E = {
11
- memberFilterArea: "bpm_memberFilterArea_9RB2k",
12
- header: "bpm_header_sIEtg",
13
- detailFields: "bpm_detailFields_TyKNL",
14
- detailSection: "bpm_detailSection_-iLjy",
15
- membershipList: "bpm_membershipList_5n9iq"
16
- }, D = [
17
- 10,
18
- 20,
19
- 50
20
- ];
21
- function O() {
22
- let [e, a] = i(null), [d, O] = i([]), [k, A] = i(null), [j, N] = i(null), [P, F] = i(null), [I, L] = i(!0), [R, z] = i(1), [B, V] = i(10), [H, U] = i(0), [W, G] = i([]), [K, q] = i([]), [J, Y] = i([]), [X, Z] = i(""), ne = r(() => new Map(K.map((e) => [e.id, e])), [K]), re = r(() => new Map(J.map((e) => [e.id, e])), [J]), Q = t(async () => {
23
- L(!0), F(null);
24
- try {
25
- let [e, t] = await Promise.all([g({
26
- page: R,
27
- pageSize: B,
28
- searchText: X
29
- }), w()]);
30
- G(e.members), U(e.totalCount), q(t.orgUnits), Y(t.positions);
31
- } catch (e) {
32
- F(M(e));
33
- } finally {
34
- L(!1);
35
- }
36
- }, [
37
- R,
38
- B,
39
- X
40
- ]);
41
- n(() => {
42
- Q();
43
- }, [Q]);
44
- let ie = r(() => W.map((e) => ({
45
- ...e,
46
- key: e.memberId
47
- })), [W]), $ = t(async (e) => {
48
- a(e), A(null), F(null);
49
- try {
50
- let [t, n] = await Promise.all([C({ memberId: e.memberId }), T(e.memberId)]);
51
- O(t), N(n), A((await _(n.managerMemberId ? [n.managerMemberId] : []))[0] ?? null);
52
- } catch (e) {
53
- F(M(e));
54
- }
55
- }, []), ae = r(() => [{
56
- dataIndex: "name",
57
- key: "name",
58
- title: "姓名",
59
- width: 160
60
- }, {
61
- dataIndex: "email",
62
- key: "email",
63
- title: "信箱",
64
- width: 260
65
- }], []), oe = r(() => ({
66
- render: () => [{
67
- name: "檢視",
68
- onClick: (e) => {
69
- $(e);
70
- }
71
- }],
72
- variant: "base-secondary",
73
- width: 88
74
- }), [$]);
75
- function se() {
76
- a(null), A(null), O([]), N(null);
77
- }
78
- return /* @__PURE__ */ b(v, { children: [
79
- /* @__PURE__ */ y(f, { children: /* @__PURE__ */ y(S, {
80
- description: "會員資料由 host member resolver 提供,BPM 僅維護組織歸屬與主管解析。",
81
- title: "會員對照"
82
- }) }),
83
- /* @__PURE__ */ y(ee, { children: /* @__PURE__ */ b(p, {
84
- filterArea: /* @__PURE__ */ y(s, {
85
- className: E.memberFilterArea,
86
- children: /* @__PURE__ */ y(c, { children: /* @__PURE__ */ y(o, {
87
- span: 3,
88
- children: /* @__PURE__ */ y(l, {
89
- fullWidth: !0,
90
- layout: x.VERTICAL,
91
- name: "memberSearchText",
92
- children: /* @__PURE__ */ y(u, {
93
- fullWidth: !0,
94
- onChange: (e) => {
95
- Z(e.target.value), z(1);
96
- },
97
- placeholder: "搜尋姓名或信箱",
98
- size: "sub",
99
- value: X,
100
- variant: "base"
101
- })
102
- })
103
- }) })
104
- }),
105
- children: [P ? /* @__PURE__ */ y(h, {
106
- color: "text-error",
107
- variant: "body",
108
- children: P
109
- }) : null, /* @__PURE__ */ y(m, {
110
- actions: oe,
111
- columns: ae,
112
- dataSource: ie,
113
- fullWidth: !0,
114
- loading: I,
115
- pagination: {
116
- current: R,
117
- onChange: (e) => {
118
- z(e);
119
- },
120
- onChangePageSize: (e) => {
121
- z(1), V(e);
122
- },
123
- pageSize: B,
124
- pageSizeLabel: "每頁筆數",
125
- pageSizeOptions: D,
126
- renderResultSummary: (e, t, n) => `顯示 ${e}-${t} 筆,共 ${n} 筆`,
127
- showPageSizeOptions: !0,
128
- total: H
129
- }
130
- })]
131
- }) }),
132
- /* @__PURE__ */ y(te, {
133
- managerProfile: k,
134
- member: e,
135
- memberships: d,
136
- onClose: se,
137
- orgUnitsById: ne,
138
- positionsById: re,
139
- resolvedManager: j
140
- })
141
- ] });
142
- }
143
- function te({ managerProfile: e, member: t, memberships: n, onClose: r, orgUnitsById: i, positionsById: o, resolvedManager: s }) {
144
- return /* @__PURE__ */ y(d, {
145
- cancelText: "關閉",
146
- confirmText: "關閉",
147
- modalType: "standard",
148
- onCancel: r,
149
- onClose: r,
150
- onConfirm: r,
151
- open: !!t,
152
- showModalFooter: !0,
153
- showModalHeader: !0,
154
- size: "regular",
155
- title: t?.name ?? "會員明細",
156
- children: t ? /* @__PURE__ */ b("div", {
157
- className: E.detailFields,
158
- children: [
159
- /* @__PURE__ */ y(a, {
160
- title: "基本資料",
161
- children: /* @__PURE__ */ y("div", {
162
- className: E.detailSection,
163
- children: /* @__PURE__ */ b(h, {
164
- variant: "body",
165
- children: ["信箱:", t.email?.trim() ? t.email : "未設定"]
166
- })
167
- })
168
- }),
169
- /* @__PURE__ */ y(a, {
170
- title: "BPM 組織歸屬",
171
- children: /* @__PURE__ */ y("div", {
172
- className: E.membershipList,
173
- children: n.length ? n.map((e) => /* @__PURE__ */ b(h, {
174
- variant: "body",
175
- children: [
176
- k(i.get(e.orgUnitId)),
177
- " / ",
178
- e.positionId ? A(o.get(e.positionId)) : "未指定職位",
179
- " / ",
180
- e.isPrimary ? "主要" : "一般"
181
- ]
182
- }, e.id)) : /* @__PURE__ */ y(h, {
183
- color: "text-neutral",
184
- variant: "body",
185
- children: "尚未建立 BPM 組織歸屬"
186
- })
187
- })
188
- }),
189
- /* @__PURE__ */ y(a, {
190
- title: "主管解析",
191
- children: /* @__PURE__ */ y(h, {
192
- variant: "body",
193
- children: s?.managerMemberId ? j(e) : "尚未解析到主管"
194
- })
195
- })
196
- ]
197
- }) : null
198
- });
199
- }
200
- function k(e) {
201
- return e ? `${e.name} · ${e.code}` : "未知組織";
202
- }
203
- function A(e) {
204
- return e ? `${e.name} · ${e.code}` : "未知職位";
205
- }
206
- function j(t) {
207
- return t ? e(t.name, t.email, "dot") : "主管資料尚未載入";
208
- }
209
- function M(e) {
210
- return e instanceof Error ? e.message : "讀取會員資料失敗。";
211
- }
212
- //#endregion
213
- export { O as t };
214
-
215
- //# sourceMappingURL=users-BSVo_eNe.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"users-BSVo_eNe.js","names":["_Fragment","styles","formatMemberLabel","Fragment$1","ContentHeader","users_module_default","MEMBER_PAGE_SIZE_OPTIONS","AdminUsersView","detailMember","setDetailMember","useState","detailMemberships","setDetailMemberships","detailManagerProfile","setDetailManagerProfile","detailResolvedManager","setDetailResolvedManager","error","setError","loading","setLoading","memberPage","setMemberPage","memberPageSize","setMemberPageSize","memberTotalCount","setMemberTotalCount","members","setMembers","orgUnits","setOrgUnits","positions","setPositions","searchText","setSearchText","orgUnitsById","useMemo","orgUnit","positionsById","position","refreshMembers","useCallback","memberPageResult","organization","listMemberDirectoryPage","readOrganizationDashboard","requestError","readErrorMessage","rows","member","openDetail","memberships","resolvedManager","listMemberships","readResolvedManager","resolveMembers","columns","tableActions","record","closeDetail","PageHeader","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","Typography","Table","page","pageSize","from","to","total","MemberDetailModal","Modal","onClose","BaseCard","readOrgUnitLabel","membership","readPositionLabel","readMemberLabel","managerProfile"],"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 { formatMemberLabel } from '../../../lib/format-member-label';\nimport styles from './users.module.scss';\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 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 [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 <>\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 </>\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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"}
@@ -1,2 +0,0 @@
1
- "use client";require('../users.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./format-member-label-t7ANTF62.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/core/form"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let 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(){let[e,t]=(0,n.useState)(null),[d,p]=(0,n.useState)([]),[m,h]=(0,n.useState)(null),[_,v]=(0,n.useState)(null),[y,b]=(0,n.useState)(null),[x,S]=(0,n.useState)(!0),[C,w]=(0,n.useState)(1),[T,E]=(0,n.useState)(10),[D,O]=(0,n.useState)(0),[k,A]=(0,n.useState)([]),[j,M]=(0,n.useState)([]),[N,P]=(0,n.useState)([]),[F,I]=(0,n.useState)(``),L=(0,n.useMemo)(()=>new Map(j.map(e=>[e.id,e])),[j]),R=(0,n.useMemo)(()=>new Map(N.map(e=>[e.id,e])),[N]),z=(0,n.useCallback)(async()=>{S(!0),b(null);try{let[e,t]=await Promise.all([(0,i.listMemberDirectoryPage)({page:C,pageSize:T,searchText:F}),(0,c.readOrganizationDashboard)()]);A(e.members),O(e.totalCount),M(t.orgUnits),P(t.positions)}catch(e){b(g(e))}finally{S(!1)}},[C,T,F]);(0,n.useEffect)(()=>{z()},[z]);let B=(0,n.useMemo)(()=>k.map(e=>({...e,key:e.memberId})),[k]),V=(0,n.useCallback)(async e=>{t(e),h(null),b(null);try{let[t,n]=await Promise.all([(0,c.listMemberships)({memberId:e.memberId}),(0,c.readResolvedManager)(e.memberId)]);p(t),v(n),h((await(0,i.resolveMembers)(n.managerMemberId?[n.managerMemberId]:[]))[0]??null)}catch(e){b(g(e))}},[]),H=(0,n.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`姓名`,width:160},{dataIndex:`email`,key:`email`,title:`信箱`,width:260}],[]),U=(0,n.useMemo)(()=>({render:()=>[{name:`檢視`,onClick:e=>{V(e)}}],variant:`base-secondary`,width:88}),[V]);function W(){t(null),h(null),p([]),v(null)}return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.PageHeader,{children:(0,a.jsx)(s.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:o.FormFieldLayout.VERTICAL,name:`memberSearchText`,children:(0,a.jsx)(r.Input,{fullWidth:!0,onChange:e=>{I(e.target.value),w(1)},placeholder:`搜尋姓名或信箱`,size:`sub`,value:F,variant:`base`})})})})}),children:[y?(0,a.jsx)(r.Typography,{color:`text-error`,variant:`body`,children:y}):null,(0,a.jsx)(r.Table,{actions:U,columns:H,dataSource:B,fullWidth:!0,loading:x,pagination:{current:C,onChange:e=>{w(e)},onChangePageSize:e=>{w(1),E(e)},pageSize:T,pageSizeLabel:`每頁筆數`,pageSizeOptions:u,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:D}})]})}),(0,a.jsx)(f,{managerProfile:m,member:e,memberships:d,onClose:W,orgUnitsById:L,positionsById:R,resolvedManager:_})]})}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?.trim()?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?t.t(e.name,e.email,`dot`):`主管資料尚未載入`}function g(e){return e instanceof Error?e.message:`讀取會員資料失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return d}});
2
- //# sourceMappingURL=users-DFSBTDMy.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"users-DFSBTDMy.cjs","names":["useState","useMemo","useCallback","listMemberDirectoryPage","readOrganizationDashboard","listMemberships","readResolvedManager","resolveMembers","_Fragment","PageHeader","ContentHeader","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Typography","Table","Modal","BaseCard","formatMemberLabel","require_rolldown_runtime","require_format_member_label","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_rytass_bpm_core_client_organization","users_module_default","MEMBER_PAGE_SIZE_OPTIONS","AdminUsersView","detailMember","setDetailMember","detailMemberships","setDetailMemberships","detailManagerProfile","setDetailManagerProfile","detailResolvedManager","setDetailResolvedManager","error","setError","loading","setLoading","memberPage","setMemberPage","memberPageSize","setMemberPageSize","memberTotalCount","setMemberTotalCount","members","setMembers","orgUnits","setOrgUnits","positions","setPositions","searchText","setSearchText","orgUnitsById","orgUnit","positionsById","position","refreshMembers","memberPageResult","organization","requestError","readErrorMessage","rows","member","openDetail","memberships","resolvedManager","columns","tableActions","record","closeDetail","event","page","pageSize","from","to","total","MemberDetailModal","onClose","readOrgUnitLabel","membership","readPositionLabel","readMemberLabel","managerProfile"],"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 { formatMemberLabel } from '../../../lib/format-member-label';\nimport styles from './users.module.scss';\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 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 [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 <>\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 </>\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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"}