@rytass/bpm-core-react 0.3.1 → 0.3.3

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 (182) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/dist/chunks/app-navigation-BSkMsEhy.js +268 -0
  3. package/dist/chunks/app-navigation-BSkMsEhy.js.map +1 -0
  4. package/dist/chunks/app-navigation-KnlJCUp1.cjs +2 -0
  5. package/dist/chunks/app-navigation-KnlJCUp1.cjs.map +1 -0
  6. package/dist/chunks/approval-instance-list-page-CVXgE2K3.cjs +2 -0
  7. package/dist/chunks/approval-instance-list-page-CVXgE2K3.cjs.map +1 -0
  8. package/dist/chunks/{approval-instance-list-page-nmzMrj0b.js → approval-instance-list-page-CqNdoZqx.js} +73 -72
  9. package/dist/chunks/approval-instance-list-page-CqNdoZqx.js.map +1 -0
  10. package/dist/chunks/builder-CMlJfQHE.cjs +3 -0
  11. package/dist/chunks/builder-CMlJfQHE.cjs.map +1 -0
  12. package/dist/chunks/{builder-DqZskyXC.js → builder-D950gct_.js} +492 -491
  13. package/dist/chunks/builder-D950gct_.js.map +1 -0
  14. package/dist/chunks/categories-5yEM3p3N.cjs +2 -0
  15. package/dist/chunks/categories-5yEM3p3N.cjs.map +1 -0
  16. package/dist/chunks/{categories-DTEl182t.js → categories-BIpOG451.js} +115 -114
  17. package/dist/chunks/categories-BIpOG451.js.map +1 -0
  18. package/dist/chunks/dashboard-page-1K_jQXQk.cjs +2 -0
  19. package/dist/chunks/dashboard-page-1K_jQXQk.cjs.map +1 -0
  20. package/dist/chunks/dashboard-page-R_T2OEiE.js +122 -0
  21. package/dist/chunks/dashboard-page-R_T2OEiE.js.map +1 -0
  22. package/dist/chunks/{delegations-C5PzZ5Kn.js → delegations-B2j-wNEO.js} +193 -192
  23. package/dist/chunks/delegations-B2j-wNEO.js.map +1 -0
  24. package/dist/chunks/delegations-CsB9ozLu.cjs +2 -0
  25. package/dist/chunks/delegations-CsB9ozLu.cjs.map +1 -0
  26. package/dist/chunks/delegations-CvtwTXNP.cjs +2 -0
  27. package/dist/chunks/delegations-CvtwTXNP.cjs.map +1 -0
  28. package/dist/chunks/{delegations-C-ZrwzvU.js → delegations-dKodb0WW.js} +175 -174
  29. package/dist/chunks/delegations-dKodb0WW.js.map +1 -0
  30. package/dist/chunks/{detail-CfFyU5zC.js → detail-BcGAqJ_R.js} +465 -464
  31. package/dist/chunks/detail-BcGAqJ_R.js.map +1 -0
  32. package/dist/chunks/detail-CqjqLd65.cjs +2 -0
  33. package/dist/chunks/detail-CqjqLd65.cjs.map +1 -0
  34. package/dist/chunks/{format-date-time-isOa3e9q.cjs → format-date-time-26_pFvv4.cjs} +2 -2
  35. package/dist/chunks/{format-date-time-isOa3e9q.cjs.map → format-date-time-26_pFvv4.cjs.map} +1 -1
  36. package/dist/chunks/notifications-2swRqDPF.js +198 -0
  37. package/dist/chunks/notifications-2swRqDPF.js.map +1 -0
  38. package/dist/chunks/notifications-BaYDebFt.cjs +2 -0
  39. package/dist/chunks/notifications-BaYDebFt.cjs.map +1 -0
  40. package/dist/chunks/{orgs-xrdhb3hS.js → orgs-CuHxxd_n.js} +608 -607
  41. package/dist/chunks/orgs-CuHxxd_n.js.map +1 -0
  42. package/dist/chunks/orgs-YMiVLNvL.cjs +2 -0
  43. package/dist/chunks/orgs-YMiVLNvL.cjs.map +1 -0
  44. package/dist/chunks/routes-config-2aKbWq2H.cjs +2 -0
  45. package/dist/chunks/routes-config-2aKbWq2H.cjs.map +1 -0
  46. package/dist/chunks/routes-config-dxahImVe.js +43 -0
  47. package/dist/chunks/routes-config-dxahImVe.js.map +1 -0
  48. package/dist/chunks/templates-DTkbSgFY.cjs +2 -0
  49. package/dist/chunks/templates-DTkbSgFY.cjs.map +1 -0
  50. package/dist/chunks/templates-DoDWM68t.js +384 -0
  51. package/dist/chunks/templates-DoDWM68t.js.map +1 -0
  52. package/dist/chunks/users-3ySyUW4u.cjs +2 -0
  53. package/dist/chunks/users-3ySyUW4u.cjs.map +1 -0
  54. package/dist/chunks/{users-CY4-NK3j.js → users-sMfrSjRQ.js} +75 -74
  55. package/dist/chunks/users-sMfrSjRQ.js.map +1 -0
  56. package/dist/components/admin-pickers.d.ts +1 -1
  57. package/dist/components/approval-instance-list-page.d.ts +1 -1
  58. package/dist/components/org-unit-tree-draft-editor.d.ts +1 -1
  59. package/dist/index.cjs +1 -1
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.d.ts +1 -0
  62. package/dist/index.js +101 -99
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib/auth-provider.d.ts +1 -1
  65. package/dist/lib/org-tree-draft.d.ts +1 -1
  66. package/dist/lib/routes-config.d.ts +105 -0
  67. package/dist/next/BPMNextProviders.d.ts +48 -3
  68. package/dist/next/index.cjs +1 -1
  69. package/dist/next/index.cjs.map +1 -1
  70. package/dist/next/index.d.ts +1 -0
  71. package/dist/next/index.js +27 -21
  72. package/dist/next/index.js.map +1 -1
  73. package/dist/pages/admin/delegations/index.cjs +1 -1
  74. package/dist/pages/admin/delegations/index.js +1 -1
  75. package/dist/pages/admin/orgs/index.cjs +1 -1
  76. package/dist/pages/admin/orgs/index.js +1 -1
  77. package/dist/pages/admin/users/index.cjs +1 -1
  78. package/dist/pages/admin/users/index.js +1 -1
  79. package/dist/pages/delegations/index.cjs +1 -1
  80. package/dist/pages/delegations/index.js +1 -1
  81. package/dist/pages/forms/builder/index.cjs +1 -1
  82. package/dist/pages/forms/builder/index.js +1 -1
  83. package/dist/pages/instances/detail/index.cjs +1 -1
  84. package/dist/pages/instances/detail/index.js +1 -1
  85. package/dist/pages/settings/notifications/index.cjs +1 -1
  86. package/dist/pages/settings/notifications/index.js +1 -1
  87. package/dist/pages/templates/categories/index.cjs +1 -1
  88. package/dist/pages/templates/categories/index.js +1 -1
  89. package/dist/pages/templates/index.cjs +1 -1
  90. package/dist/pages/templates/index.js +1 -1
  91. package/dist/views/admin/delegations/index.cjs +1 -1
  92. package/dist/views/admin/delegations/index.js +1 -1
  93. package/dist/views/admin/index.cjs +1 -1
  94. package/dist/views/admin/index.js +3 -3
  95. package/dist/views/admin/orgs/index.cjs +1 -1
  96. package/dist/views/admin/orgs/index.js +1 -1
  97. package/dist/views/admin/users/index.cjs +1 -1
  98. package/dist/views/admin/users/index.js +1 -1
  99. package/dist/views/cc/index.cjs +1 -1
  100. package/dist/views/cc/index.js +1 -1
  101. package/dist/views/dashboard/index.cjs +1 -1
  102. package/dist/views/dashboard/index.js +1 -1
  103. package/dist/views/delegations/index.cjs +1 -1
  104. package/dist/views/delegations/index.js +1 -1
  105. package/dist/views/forms/builder/index.cjs +1 -1
  106. package/dist/views/forms/builder/index.js +1 -1
  107. package/dist/views/forms/index.cjs +1 -1
  108. package/dist/views/forms/index.cjs.map +1 -1
  109. package/dist/views/forms/index.js +78 -77
  110. package/dist/views/forms/index.js.map +1 -1
  111. package/dist/views/forms/renderer/FormRendererView.d.ts +2 -2
  112. package/dist/views/inbox/index.cjs +1 -1
  113. package/dist/views/inbox/index.cjs.map +1 -1
  114. package/dist/views/inbox/index.js +106 -105
  115. package/dist/views/inbox/index.js.map +1 -1
  116. package/dist/views/instances/detail/index.cjs +1 -1
  117. package/dist/views/instances/detail/index.js +1 -1
  118. package/dist/views/instances/new/index.cjs +1 -1
  119. package/dist/views/instances/new/index.cjs.map +1 -1
  120. package/dist/views/instances/new/index.js +90 -89
  121. package/dist/views/instances/new/index.js.map +1 -1
  122. package/dist/views/search/index.cjs +1 -1
  123. package/dist/views/search/index.js +1 -1
  124. package/dist/views/sent/index.cjs +1 -1
  125. package/dist/views/sent/index.js +1 -1
  126. package/dist/views/settings/index.cjs +1 -1
  127. package/dist/views/settings/index.js +1 -1
  128. package/dist/views/settings/notifications/index.cjs +1 -1
  129. package/dist/views/settings/notifications/index.js +1 -1
  130. package/dist/views/templates/categories/index.cjs +1 -1
  131. package/dist/views/templates/categories/index.js +1 -1
  132. package/dist/views/templates/designer/index.cjs +6 -6
  133. package/dist/views/templates/designer/index.cjs.map +1 -1
  134. package/dist/views/templates/designer/index.js +589 -588
  135. package/dist/views/templates/designer/index.js.map +1 -1
  136. package/dist/views/templates/index.cjs +1 -1
  137. package/dist/views/templates/index.js +2 -2
  138. package/dist/views/templates/versions/index.cjs +1 -1
  139. package/dist/views/templates/versions/index.cjs.map +1 -1
  140. package/dist/views/templates/versions/index.js +44 -43
  141. package/dist/views/templates/versions/index.js.map +1 -1
  142. package/package.json +3 -3
  143. package/dist/chunks/app-navigation-C_mbz7jx.cjs +0 -2
  144. package/dist/chunks/app-navigation-C_mbz7jx.cjs.map +0 -1
  145. package/dist/chunks/app-navigation-uwbNEw9P.js +0 -262
  146. package/dist/chunks/app-navigation-uwbNEw9P.js.map +0 -1
  147. package/dist/chunks/approval-instance-list-page-Mo6wpDPb.cjs +0 -2
  148. package/dist/chunks/approval-instance-list-page-Mo6wpDPb.cjs.map +0 -1
  149. package/dist/chunks/approval-instance-list-page-nmzMrj0b.js.map +0 -1
  150. package/dist/chunks/builder-DPhAH381.cjs +0 -3
  151. package/dist/chunks/builder-DPhAH381.cjs.map +0 -1
  152. package/dist/chunks/builder-DqZskyXC.js.map +0 -1
  153. package/dist/chunks/categories-DEijUOnw.cjs +0 -2
  154. package/dist/chunks/categories-DEijUOnw.cjs.map +0 -1
  155. package/dist/chunks/categories-DTEl182t.js.map +0 -1
  156. package/dist/chunks/dashboard-page-DCmuB0Rw.cjs +0 -2
  157. package/dist/chunks/dashboard-page-DCmuB0Rw.cjs.map +0 -1
  158. package/dist/chunks/dashboard-page-Dx5PeEeN.js +0 -117
  159. package/dist/chunks/dashboard-page-Dx5PeEeN.js.map +0 -1
  160. package/dist/chunks/delegations-C-ZrwzvU.js.map +0 -1
  161. package/dist/chunks/delegations-C5PzZ5Kn.js.map +0 -1
  162. package/dist/chunks/delegations-DOGDvybX.cjs +0 -2
  163. package/dist/chunks/delegations-DOGDvybX.cjs.map +0 -1
  164. package/dist/chunks/delegations-DkDBWOQ7.cjs +0 -2
  165. package/dist/chunks/delegations-DkDBWOQ7.cjs.map +0 -1
  166. package/dist/chunks/detail-B2gcOPkd.cjs +0 -2
  167. package/dist/chunks/detail-B2gcOPkd.cjs.map +0 -1
  168. package/dist/chunks/detail-CfFyU5zC.js.map +0 -1
  169. package/dist/chunks/notifications-CPQ-nVar.cjs +0 -2
  170. package/dist/chunks/notifications-CPQ-nVar.cjs.map +0 -1
  171. package/dist/chunks/notifications-DweexUVy.js +0 -197
  172. package/dist/chunks/notifications-DweexUVy.js.map +0 -1
  173. package/dist/chunks/orgs-DgZ0DQ3-.cjs +0 -2
  174. package/dist/chunks/orgs-DgZ0DQ3-.cjs.map +0 -1
  175. package/dist/chunks/orgs-xrdhb3hS.js.map +0 -1
  176. package/dist/chunks/templates-PK_VYvcy.js +0 -383
  177. package/dist/chunks/templates-PK_VYvcy.js.map +0 -1
  178. package/dist/chunks/templates-x1OJZmsG.cjs +0 -2
  179. package/dist/chunks/templates-x1OJZmsG.cjs.map +0 -1
  180. package/dist/chunks/users-CY4-NK3j.js.map +0 -1
  181. package/dist/chunks/users-DHnu_056.cjs +0 -2
  182. package/dist/chunks/users-DHnu_056.cjs.map +0 -1
@@ -1,20 +1,21 @@
1
1
  "use client";
2
2
  import { a as e, n as t } from "../../chunks/auth-provider-Bnox5gsx.js";
3
3
  import { t as n } from "../../chunks/format-date-time-CB-LxzqT.js";
4
- import { t as r } from "../../chunks/app-navigation-uwbNEw9P.js";
5
- import { useEffect as i, useMemo as a, useState as o } from "react";
6
- import { Button as s, PageHeader as c, Section as l, SectionGroup as u, Tab as d, TabItem as f, Table as p, Typography as m } from "@mezzanine-ui/react";
7
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
8
- import { listApprovalHistoryTasks as _, listInboxTasks as v, listTaskDecisions as y, readApprovalInstance as b, readApprovalInstanceCaseTitle as x } from "@rytass/bpm-core-client/workflow";
9
- import { PlusIcon as S } from "@mezzanine-ui/icons";
10
- import C from "@mezzanine-ui/react/ContentHeader";
4
+ import { t as r } from "../../chunks/app-navigation-BSkMsEhy.js";
5
+ import { r as i } from "../../chunks/routes-config-dxahImVe.js";
6
+ import { useEffect as a, useMemo as o, useState as s } from "react";
7
+ import { Button as c, PageHeader as l, Section as u, SectionGroup as d, Tab as f, TabItem as p, Table as m, Typography as h } from "@mezzanine-ui/react";
8
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
9
+ import { listApprovalHistoryTasks as v, listInboxTasks as y, listTaskDecisions as b, readApprovalInstance as x, readApprovalInstanceCaseTitle as S } from "@rytass/bpm-core-client/workflow";
10
+ import { PlusIcon as C } from "@mezzanine-ui/icons";
11
+ import w from "@mezzanine-ui/react/ContentHeader";
11
12
  //#region src/views/inbox/InboxView.tsx
12
- function w(y = {}) {
13
- let b = e(), { member: x } = t(), w = x?.memberId ?? null, [D, O] = o("pending"), [k, A] = o(null), [j, N] = o([]), [F, L] = o(!0), [R, z] = o([]);
14
- i(() => {
15
- w && q();
16
- }, [w]);
17
- let B = a(() => [
13
+ function T(b = {}) {
14
+ let x = e(), S = i(), { member: T } = t(), O = T?.memberId ?? null, [k, A] = s("pending"), [j, M] = s(null), [P, I] = s([]), [R, z] = s(!0), [B, V] = s([]);
15
+ a(() => {
16
+ O && Y();
17
+ }, [O]);
18
+ let U = o(() => [
18
19
  {
19
20
  dataIndex: "caseTitle",
20
21
  key: "caseTitle",
@@ -35,7 +36,7 @@ function w(y = {}) {
35
36
  },
36
37
  {
37
38
  key: "slaDueAt",
38
- render: (e) => /* @__PURE__ */ h(m, {
39
+ render: (e) => /* @__PURE__ */ g(h, {
39
40
  color: e.slaStatusColor,
40
41
  component: "span",
41
42
  variant: "body",
@@ -46,7 +47,7 @@ function w(y = {}) {
46
47
  },
47
48
  {
48
49
  key: "createdAt",
49
- render: (e) => /* @__PURE__ */ h(m, {
50
+ render: (e) => /* @__PURE__ */ g(h, {
50
51
  component: "span",
51
52
  variant: "body",
52
53
  children: n(e.createdAt)
@@ -54,14 +55,14 @@ function w(y = {}) {
54
55
  title: "建立時間",
55
56
  width: 220
56
57
  }
57
- ], []), H = a(() => ({
58
+ ], []), W = o(() => ({
58
59
  render: (e) => [{
59
60
  name: "處理",
60
- onClick: () => b.push(`/instances/${e.instanceId}`)
61
+ onClick: () => x.push(S.caseDetail(e.instanceId))
61
62
  }],
62
63
  variant: "base-secondary",
63
64
  width: 88
64
- }), [b]), U = a(() => [
65
+ }), [x, S]), G = o(() => [
65
66
  {
66
67
  dataIndex: "caseTitle",
67
68
  key: "caseTitle",
@@ -76,8 +77,8 @@ function w(y = {}) {
76
77
  },
77
78
  {
78
79
  key: "decisionLabel",
79
- render: (e) => /* @__PURE__ */ h(m, {
80
- color: M(e.decisionAction),
80
+ render: (e) => /* @__PURE__ */ g(h, {
81
+ color: N(e.decisionAction),
81
82
  component: "span",
82
83
  variant: "body",
83
84
  children: e.decisionLabel
@@ -87,7 +88,7 @@ function w(y = {}) {
87
88
  },
88
89
  {
89
90
  key: "decisionComment",
90
- render: (e) => /* @__PURE__ */ h(m, {
91
+ render: (e) => /* @__PURE__ */ g(h, {
91
92
  component: "span",
92
93
  variant: "body",
93
94
  children: e.decisionCommentText
@@ -97,8 +98,8 @@ function w(y = {}) {
97
98
  },
98
99
  {
99
100
  key: "instanceStateLabel",
100
- render: (e) => /* @__PURE__ */ h(m, {
101
- color: P(e.instanceState),
101
+ render: (e) => /* @__PURE__ */ g(h, {
102
+ color: F(e.instanceState),
102
103
  component: "span",
103
104
  variant: "body",
104
105
  children: e.instanceStateLabel
@@ -108,186 +109,186 @@ function w(y = {}) {
108
109
  },
109
110
  {
110
111
  key: "decidedAt",
111
- render: (e) => /* @__PURE__ */ h(m, {
112
+ render: (e) => /* @__PURE__ */ g(h, {
112
113
  component: "span",
113
114
  variant: "body",
114
- children: I(e.decidedAt)
115
+ children: L(e.decidedAt)
115
116
  }),
116
117
  title: "簽核時間",
117
118
  width: 220
118
119
  }
119
- ], []), W = a(() => ({
120
+ ], []), K = o(() => ({
120
121
  render: (e) => [{
121
122
  name: "查看",
122
- onClick: () => b.push(`/instances/${e.instanceId}`)
123
+ onClick: () => x.push(S.caseDetail(e.instanceId))
123
124
  }],
124
125
  variant: "base-secondary",
125
126
  width: 88
126
- }), [b]), G = a(() => j.filter((e) => e.instanceState === "RUNNING"), [j]);
127
- function K(e) {
127
+ }), [x, S]), q = o(() => P.filter((e) => e.instanceState === "RUNNING"), [P]);
128
+ function J(e) {
128
129
  if (e === "history" || e === "pending" || e === "tracking") {
129
- O(e);
130
+ A(e);
130
131
  return;
131
132
  }
132
- O("pending");
133
+ A("pending");
133
134
  }
134
- async function q() {
135
- L(!0), A(null);
135
+ async function Y() {
136
+ z(!0), M(null);
136
137
  try {
137
- if (!w) {
138
- z([]), N([]);
138
+ if (!O) {
139
+ V([]), I([]);
139
140
  return;
140
141
  }
141
- let [e, t] = await Promise.all([v(w), _(w)]), [n, r] = await Promise.all([T(e), E(t)]);
142
- z(n), N(r);
142
+ let [e, t] = await Promise.all([y(O), v(O)]), [n, r] = await Promise.all([E(e), D(t)]);
143
+ V(n), I(r);
143
144
  } catch (e) {
144
- A(V(e));
145
+ M(H(e));
145
146
  } finally {
146
- L(!1);
147
+ z(!1);
147
148
  }
148
149
  }
149
- return /* @__PURE__ */ g(r, {
150
- activeHref: "/inbox",
151
- children: [/* @__PURE__ */ h(c, { children: /* @__PURE__ */ h(C, {
152
- description: `目前以 ${x?.name ?? w ?? "目前登入會員"} 查詢待處理與歷史簽核任務。`,
150
+ return /* @__PURE__ */ _(r, {
151
+ activeHref: S.inbox(),
152
+ children: [/* @__PURE__ */ g(l, { children: /* @__PURE__ */ g(w, {
153
+ description: `目前以 ${T?.name ?? O ?? "目前登入會員"} 查詢待處理與歷史簽核任務。`,
153
154
  title: "我的待簽",
154
- children: /* @__PURE__ */ h(s, {
155
- icon: S,
155
+ children: /* @__PURE__ */ g(c, {
156
+ icon: C,
156
157
  iconType: "leading",
157
- onClick: () => b.push("/instances/new"),
158
+ onClick: () => x.push(S.caseNew()),
158
159
  variant: "base-primary",
159
160
  children: "發起簽核"
160
161
  })
161
- }) }), /* @__PURE__ */ h(u, { children: /* @__PURE__ */ g(l, { children: [
162
- k ? /* @__PURE__ */ h(m, {
162
+ }) }), /* @__PURE__ */ g(d, { children: /* @__PURE__ */ _(u, { children: [
163
+ j ? /* @__PURE__ */ g(h, {
163
164
  color: "text-error",
164
165
  variant: "body",
165
- children: k
166
+ children: j
166
167
  }) : null,
167
- /* @__PURE__ */ g(d, {
168
- activeKey: D,
169
- onChange: K,
168
+ /* @__PURE__ */ _(f, {
169
+ activeKey: k,
170
+ onChange: J,
170
171
  size: "sub",
171
172
  children: [
172
- /* @__PURE__ */ h(f, {
173
- badgeCount: F ? void 0 : R.length,
173
+ /* @__PURE__ */ g(p, {
174
+ badgeCount: R ? void 0 : B.length,
174
175
  children: "待簽核"
175
176
  }, "pending"),
176
- /* @__PURE__ */ h(f, {
177
- badgeCount: F ? void 0 : G.length,
177
+ /* @__PURE__ */ g(p, {
178
+ badgeCount: R ? void 0 : q.length,
178
179
  children: "已處理未結束"
179
180
  }, "tracking"),
180
- /* @__PURE__ */ h(f, { children: "歷史簽核記錄" }, "history")
181
+ /* @__PURE__ */ g(p, { children: "歷史簽核記錄" }, "history")
181
182
  ]
182
183
  }),
183
- D === "pending" ? /* @__PURE__ */ h(p, {
184
- actions: H,
185
- columns: B,
186
- dataSource: R,
187
- fullWidth: !0,
188
- loading: F
189
- }) : null,
190
- D === "tracking" ? /* @__PURE__ */ h(p, {
184
+ k === "pending" ? /* @__PURE__ */ g(m, {
191
185
  actions: W,
192
186
  columns: U,
193
- dataSource: G,
187
+ dataSource: B,
194
188
  fullWidth: !0,
195
- loading: F
189
+ loading: R
196
190
  }) : null,
197
- D === "history" ? /* @__PURE__ */ h(p, {
198
- actions: W,
199
- columns: U,
200
- dataSource: j,
191
+ k === "tracking" ? /* @__PURE__ */ g(m, {
192
+ actions: K,
193
+ columns: G,
194
+ dataSource: q,
201
195
  fullWidth: !0,
202
- loading: F
196
+ loading: R
197
+ }) : null,
198
+ k === "history" ? /* @__PURE__ */ g(m, {
199
+ actions: K,
200
+ columns: G,
201
+ dataSource: P,
202
+ fullWidth: !0,
203
+ loading: R
203
204
  }) : null
204
205
  ] }) })]
205
206
  });
206
207
  }
207
- async function T(e) {
208
- let t = await D(e);
208
+ async function E(e) {
209
+ let t = await O(e);
209
210
  return e.map((e, n) => ({
210
211
  ...e,
211
- caseTitle: O(e, t[n] ?? null),
212
+ caseTitle: k(e, t[n] ?? null),
212
213
  key: e.id,
213
- slaStatusColor: R(e.slaDueAt),
214
- slaStatusText: L(e.slaDueAt),
215
- statusLabel: B(e.status)
214
+ slaStatusColor: z(e.slaDueAt),
215
+ slaStatusText: R(e.slaDueAt),
216
+ statusLabel: V(e.status)
216
217
  }));
217
218
  }
218
- async function E(e) {
219
- let [t, n] = await Promise.all([Promise.all(e.map((e) => y(e.id))), D(e)]);
219
+ async function D(e) {
220
+ let [t, n] = await Promise.all([Promise.all(e.map((e) => b(e.id))), O(e)]);
220
221
  return e.map((e, r) => {
221
- let i = k(t[r] ?? []), a = n[r] ?? null;
222
+ let i = A(t[r] ?? []), a = n[r] ?? null;
222
223
  return {
223
224
  ...e,
224
- caseTitle: O(e, a),
225
+ caseTitle: k(e, a),
225
226
  decisionAction: i?.action ?? null,
226
227
  decisionComment: i?.comment ?? null,
227
- decisionCommentText: F(i?.comment ?? null),
228
- decisionLabel: j(i?.action ?? null),
228
+ decisionCommentText: I(i?.comment ?? null),
229
+ decisionLabel: M(i?.action ?? null),
229
230
  decidedAt: i?.decidedAt ?? e.completedAt,
230
231
  instanceState: a?.state ?? null,
231
- instanceStateLabel: N(a?.state ?? null),
232
+ instanceStateLabel: P(a?.state ?? null),
232
233
  key: e.id
233
234
  };
234
235
  });
235
236
  }
236
- async function D(e) {
237
+ async function O(e) {
237
238
  return Promise.all(e.map(async (e) => {
238
239
  try {
239
- return (await b(e.instanceId)).instance;
240
+ return (await x(e.instanceId)).instance;
240
241
  } catch {
241
242
  return null;
242
243
  }
243
244
  }));
244
245
  }
245
- function O(e, t) {
246
- return t ? x(t) : e.instanceId;
246
+ function k(e, t) {
247
+ return t ? S(t) : e.instanceId;
247
248
  }
248
- function k(e) {
249
- return [...e].sort(A)[0] ?? null;
249
+ function A(e) {
250
+ return [...e].sort(j)[0] ?? null;
250
251
  }
251
- function A(e, t) {
252
+ function j(e, t) {
252
253
  return new Date(t.decidedAt).getTime() - new Date(e.decidedAt).getTime();
253
254
  }
254
- function j(e) {
255
+ function M(e) {
255
256
  return e === "APPROVED" ? "同意" : e === "REJECTED" ? "拒絕" : e === "RETURNED" ? "退回" : e === "TRANSFERRED" ? "轉派" : "未記錄";
256
257
  }
257
- function M(e) {
258
+ function N(e) {
258
259
  return e === "APPROVED" ? "text-success" : e === "REJECTED" || e === "RETURNED" ? "text-error" : "text-neutral";
259
260
  }
260
- function N(e) {
261
+ function P(e) {
261
262
  return e === "RUNNING" ? "進行中" : e === "APPROVED" ? "已通過" : e === "REJECTED" ? "已拒絕" : e === "RETURNED" ? "已退回" : e === "CANCELLED" ? "已取消" : e === "EXPIRED" ? "已逾期" : e === "DRAFT" ? "草稿" : "-";
262
263
  }
263
- function P(e) {
264
+ function F(e) {
264
265
  return e === "APPROVED" ? "text-success" : e === "REJECTED" || e === "CANCELLED" || e === "EXPIRED" ? "text-error" : "text-neutral";
265
266
  }
266
- function F(e) {
267
+ function I(e) {
267
268
  return (e?.trim() ?? "") || "-";
268
269
  }
269
- function I(e) {
270
+ function L(e) {
270
271
  return n(e);
271
272
  }
272
- function L(e) {
273
+ function R(e) {
273
274
  if (!e) return "-";
274
- let t = new Date(e).getTime(), n = Date.now(), r = z(Math.abs(t - n));
275
+ let t = new Date(e).getTime(), n = Date.now(), r = B(Math.abs(t - n));
275
276
  return t < n ? `已逾期 ${r}` : `剩餘 ${r}`;
276
277
  }
277
- function R(e) {
278
+ function z(e) {
278
279
  return e ? new Date(e).getTime() < Date.now() ? "text-error" : "text-success" : "text-neutral";
279
280
  }
280
- function z(e) {
281
+ function B(e) {
281
282
  let t = Math.max(1, Math.ceil(e / 6e4)), n = Math.floor(t / 1440), r = Math.floor(t % 1440 / 60), i = t % 60;
282
283
  return n > 0 ? `${n}天 ${r}小時` : r > 0 ? `${r}小時 ${i}分鐘` : `${i}分鐘`;
283
284
  }
284
- function B(e) {
285
+ function V(e) {
285
286
  return e === "PENDING" ? "待處理" : e === "IN_PROGRESS" ? "處理中" : e === "COMPLETED" ? "已完成" : e === "TRANSFERRED" ? "已轉派" : e === "CANCELLED" ? "已取消" : e;
286
287
  }
287
- function V(e) {
288
+ function H(e) {
288
289
  return e instanceof Error ? e.message : "發生未知錯誤";
289
290
  }
290
291
  //#endregion
291
- export { w as InboxView };
292
+ export { T as InboxView };
292
293
 
293
294
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n ApprovalInstanceRecord,\n listApprovalHistoryTasks,\n listInboxTasks,\n listTaskDecisions,\n readApprovalInstance,\n readApprovalInstanceCaseTitle,\n TaskDecisionRecord,\n TaskRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useAuth } from '../../lib/auth-provider';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { AppLayout } from '../../components/app-navigation';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n slaStatusColor: 'text-error' | 'text-neutral' | 'text-success';\n slaStatusText: string;\n statusLabel: string;\n }\n>;\n\ntype ApprovalHistoryRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n decisionAction: TaskDecisionRecord['action'] | null;\n decisionComment: string | null;\n decisionCommentText: string;\n decisionLabel: string;\n decidedAt: string | null;\n instanceState: ApprovalInstanceRecord['state'] | null;\n instanceStateLabel: string;\n key: string;\n }\n>;\n\nexport interface InboxViewProps {}\n\n/**\n * Framework-agnostic view for the BPM \"我的待簽\" inbox. Mechanical port of\n * `apps/client/src/app/inbox/page.tsx` — renders pending tasks, tracking,\n * and history tabs.\n */\nexport function InboxView(_props: InboxViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activeTab, setActiveTab] = useState<InboxTabKey>('pending');\n const [error, setError] = useState<string | null>(null);\n const [historyRows, setHistoryRows] = useState<ApprovalHistoryRow[]>([]);\n const [loading, setLoading] = useState(true);\n const [pendingRows, setPendingRows] = useState<InboxTaskRow[]>([]);\n\n useEffect((): void => {\n if (!currentMemberId) {\n return;\n }\n\n void refreshTasks();\n }, [currentMemberId]);\n\n const pendingColumns = useMemo(\n (): TableColumn<InboxTaskRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeId', key: 'nodeId', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'slaDueAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography\n color={record.slaStatusColor}\n component=\"span\"\n variant=\"body\"\n >\n {record.slaStatusText}\n </Typography>\n ),\n title: 'SLA',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n const pendingTableActions = useMemo(\n (): TableActions<InboxTaskRow> => ({\n render: (record): ReturnType<TableActions<InboxTaskRow>['render']> => [\n {\n name: '處理',\n onClick: (): void => router.push(`/instances/${record.instanceId}`),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n const historyColumns = useMemo(\n (): TableColumn<ApprovalHistoryRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeId', key: 'nodeId', title: '節點', width: 180 },\n {\n key: 'decisionLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readTaskDecisionColor(record.decisionAction)}\n component=\"span\"\n variant=\"body\"\n >\n {record.decisionLabel}\n </Typography>\n ),\n title: '決議',\n width: 120,\n },\n {\n key: 'decisionComment',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.decisionCommentText}\n </Typography>\n ),\n title: '意見',\n width: 240,\n },\n {\n key: 'instanceStateLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.instanceState)}\n component=\"span\"\n variant=\"body\"\n >\n {record.instanceStateLabel}\n </Typography>\n ),\n title: '流程狀態',\n width: 140,\n },\n {\n key: 'decidedAt',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatHistoryDateTime(record.decidedAt)}\n </Typography>\n ),\n title: '簽核時間',\n width: 220,\n },\n ],\n [],\n );\n const historyTableActions = useMemo(\n (): TableActions<ApprovalHistoryRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalHistoryRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(`/instances/${record.instanceId}`),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n const trackingRows = useMemo(\n (): ApprovalHistoryRow[] =>\n historyRows.filter((row) => row.instanceState === 'RUNNING'),\n [historyRows],\n );\n\n function handleTabChange(activeKey: Key): void {\n if (\n activeKey === 'history' ||\n activeKey === 'pending' ||\n activeKey === 'tracking'\n ) {\n setActiveTab(activeKey);\n return;\n }\n\n setActiveTab('pending');\n }\n\n async function refreshTasks(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n if (!currentMemberId) {\n setPendingRows([]);\n setHistoryRows([]);\n return;\n }\n\n const [nextPendingTasks, nextHistoryTasks] = await Promise.all([\n listInboxTasks(currentMemberId),\n listApprovalHistoryTasks(currentMemberId),\n ]);\n const [nextPendingRows, nextHistoryRows] = await Promise.all([\n readInboxTaskRows(nextPendingTasks),\n readApprovalHistoryRows(nextHistoryTasks),\n ]);\n\n setPendingRows(nextPendingRows);\n setHistoryRows(nextHistoryRows);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <AppLayout activeHref=\"/inbox\">\n <PageHeader>\n <ContentHeader\n description={`目前以 ${member?.name ?? currentMemberId ?? '目前登入會員'} 查詢待處理與歷史簽核任務。`}\n title=\"我的待簽\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push('/instances/new')}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Tab activeKey={activeTab} onChange={handleTabChange} size=\"sub\">\n <TabItem\n badgeCount={loading ? undefined : pendingRows.length}\n key=\"pending\"\n >\n 待簽核\n </TabItem>\n <TabItem\n badgeCount={loading ? undefined : trackingRows.length}\n key=\"tracking\"\n >\n 已處理未結束\n </TabItem>\n <TabItem key=\"history\">歷史簽核記錄</TabItem>\n </Tab>\n\n {activeTab === 'pending' ? (\n <Table\n actions={pendingTableActions}\n columns={pendingColumns}\n dataSource={pendingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'tracking' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={trackingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'history' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={historyRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n </Section>\n </SectionGroup>\n </AppLayout>\n );\n}\n\nasync function readInboxTaskRows(\n tasks: readonly TaskRecord[],\n): Promise<InboxTaskRow[]> {\n const instances = await readTaskInstances(tasks);\n\n return tasks.map(\n (task, index): InboxTaskRow => ({\n ...task,\n caseTitle: readTaskCaseTitle(task, instances[index] ?? null),\n key: task.id,\n slaStatusColor: readSlaStatusColor(task.slaDueAt),\n slaStatusText: readSlaStatusText(task.slaDueAt),\n statusLabel: readTaskStatusLabel(task.status),\n }),\n );\n}\n\nasync function readApprovalHistoryRows(\n tasks: readonly TaskRecord[],\n): Promise<ApprovalHistoryRow[]> {\n const [decisionLists, instances] = await Promise.all([\n Promise.all(tasks.map((task) => listTaskDecisions(task.id))),\n readTaskInstances(tasks),\n ]);\n\n return tasks.map((task, index): ApprovalHistoryRow => {\n const decision = readLatestTaskDecision(decisionLists[index] ?? []);\n const instance = instances[index] ?? null;\n\n return {\n ...task,\n caseTitle: readTaskCaseTitle(task, instance),\n decisionAction: decision?.action ?? null,\n decisionComment: decision?.comment ?? null,\n decisionCommentText: readDecisionCommentText(decision?.comment ?? null),\n decisionLabel: readTaskDecisionLabel(decision?.action ?? null),\n decidedAt: decision?.decidedAt ?? task.completedAt,\n instanceState: instance?.state ?? null,\n instanceStateLabel: readInstanceStateLabel(instance?.state ?? null),\n key: task.id,\n };\n });\n}\n\nasync function readTaskInstances(\n tasks: readonly TaskRecord[],\n): Promise<readonly (ApprovalInstanceRecord | null)[]> {\n return Promise.all(\n tasks.map(async (task): Promise<ApprovalInstanceRecord | null> => {\n try {\n return (await readApprovalInstance(task.instanceId)).instance;\n } catch {\n return null;\n }\n }),\n );\n}\n\nfunction readTaskCaseTitle(\n task: TaskRecord,\n instance: ApprovalInstanceRecord | null,\n): string {\n return instance ? readApprovalInstanceCaseTitle(instance) : task.instanceId;\n}\n\nfunction readLatestTaskDecision(\n decisions: readonly TaskDecisionRecord[],\n): TaskDecisionRecord | null {\n return [...decisions].sort(compareTaskDecisionDesc)[0] ?? null;\n}\n\nfunction compareTaskDecisionDesc(\n left: TaskDecisionRecord,\n right: TaskDecisionRecord,\n): number {\n return (\n new Date(right.decidedAt).getTime() - new Date(left.decidedAt).getTime()\n );\n}\n\nfunction readTaskDecisionLabel(\n action: TaskDecisionRecord['action'] | null,\n): string {\n if (action === 'APPROVED') {\n return '同意';\n }\n\n if (action === 'REJECTED') {\n return '拒絕';\n }\n\n if (action === 'RETURNED') {\n return '退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '轉派';\n }\n\n return '未記錄';\n}\n\nfunction readTaskDecisionColor(\n action: TaskDecisionRecord['action'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (action === 'APPROVED') {\n return 'text-success';\n }\n\n if (action === 'REJECTED' || action === 'RETURNED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readInstanceStateLabel(\n state: ApprovalInstanceRecord['state'] | null,\n): string {\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n if (state === 'APPROVED') {\n return '已通過';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n return '-';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceRecord['state'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') {\n return 'text-success';\n }\n\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readDecisionCommentText(comment: string | null): string {\n const trimmedComment = comment?.trim() ?? '';\n\n return trimmedComment || '-';\n}\n\nfunction formatHistoryDateTime(value: string | null): string {\n return formatDateTime(value);\n}\n\nfunction readSlaStatusText(value: string | null): string {\n if (!value) {\n return '-';\n }\n\n const dueAt = new Date(value).getTime();\n const now = Date.now();\n const diffMs = Math.abs(dueAt - now);\n const label = formatDuration(diffMs);\n\n return dueAt < now ? `已逾期 ${label}` : `剩餘 ${label}`;\n}\n\nfunction readSlaStatusColor(\n value: string | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (!value) {\n return 'text-neutral';\n }\n\n return new Date(value).getTime() < Date.now() ? 'text-error' : 'text-success';\n}\n\nfunction formatDuration(value: number): string {\n const totalMinutes = Math.max(1, Math.ceil(value / 60_000));\n const days = Math.floor(totalMinutes / 1440);\n const hours = Math.floor((totalMinutes % 1440) / 60);\n const minutes = totalMinutes % 60;\n\n if (days > 0) {\n return `${days}天 ${hours}小時`;\n }\n\n if (hours > 0) {\n return `${hours}小時 ${minutes}分鐘`;\n }\n\n return `${minutes}分鐘`;\n}\n\nfunction readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') {\n return '待處理';\n }\n\n if (status === 'IN_PROGRESS') {\n return '處理中';\n }\n\n if (status === 'COMPLETED') {\n return '已完成';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n if (status === 'CANCELLED') {\n return '已取消';\n }\n\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n ApprovalInstanceRecord,\n listApprovalHistoryTasks,\n listInboxTasks,\n listTaskDecisions,\n readApprovalInstance,\n readApprovalInstanceCaseTitle,\n TaskDecisionRecord,\n TaskRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useAuth } from '../../lib/auth-provider';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\nimport { AppLayout } from '../../components/app-navigation';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n slaStatusColor: 'text-error' | 'text-neutral' | 'text-success';\n slaStatusText: string;\n statusLabel: string;\n }\n>;\n\ntype ApprovalHistoryRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n decisionAction: TaskDecisionRecord['action'] | null;\n decisionComment: string | null;\n decisionCommentText: string;\n decisionLabel: string;\n decidedAt: string | null;\n instanceState: ApprovalInstanceRecord['state'] | null;\n instanceStateLabel: string;\n key: string;\n }\n>;\n\nexport interface InboxViewProps {}\n\n/**\n * Framework-agnostic view for the BPM \"我的待簽\" inbox. Mechanical port of\n * `apps/client/src/app/inbox/page.tsx` — renders pending tasks, tracking,\n * and history tabs.\n */\nexport function InboxView(_props: InboxViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activeTab, setActiveTab] = useState<InboxTabKey>('pending');\n const [error, setError] = useState<string | null>(null);\n const [historyRows, setHistoryRows] = useState<ApprovalHistoryRow[]>([]);\n const [loading, setLoading] = useState(true);\n const [pendingRows, setPendingRows] = useState<InboxTaskRow[]>([]);\n\n useEffect((): void => {\n if (!currentMemberId) {\n return;\n }\n\n void refreshTasks();\n }, [currentMemberId]);\n\n const pendingColumns = useMemo(\n (): TableColumn<InboxTaskRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeId', key: 'nodeId', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'slaDueAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography\n color={record.slaStatusColor}\n component=\"span\"\n variant=\"body\"\n >\n {record.slaStatusText}\n </Typography>\n ),\n title: 'SLA',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n const pendingTableActions = useMemo(\n (): TableActions<InboxTaskRow> => ({\n render: (record): ReturnType<TableActions<InboxTaskRow>['render']> => [\n {\n name: '處理',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const historyColumns = useMemo(\n (): TableColumn<ApprovalHistoryRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeId', key: 'nodeId', title: '節點', width: 180 },\n {\n key: 'decisionLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readTaskDecisionColor(record.decisionAction)}\n component=\"span\"\n variant=\"body\"\n >\n {record.decisionLabel}\n </Typography>\n ),\n title: '決議',\n width: 120,\n },\n {\n key: 'decisionComment',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.decisionCommentText}\n </Typography>\n ),\n title: '意見',\n width: 240,\n },\n {\n key: 'instanceStateLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.instanceState)}\n component=\"span\"\n variant=\"body\"\n >\n {record.instanceStateLabel}\n </Typography>\n ),\n title: '流程狀態',\n width: 140,\n },\n {\n key: 'decidedAt',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatHistoryDateTime(record.decidedAt)}\n </Typography>\n ),\n title: '簽核時間',\n width: 220,\n },\n ],\n [],\n );\n const historyTableActions = useMemo(\n (): TableActions<ApprovalHistoryRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalHistoryRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const trackingRows = useMemo(\n (): ApprovalHistoryRow[] =>\n historyRows.filter((row) => row.instanceState === 'RUNNING'),\n [historyRows],\n );\n\n function handleTabChange(activeKey: Key): void {\n if (\n activeKey === 'history' ||\n activeKey === 'pending' ||\n activeKey === 'tracking'\n ) {\n setActiveTab(activeKey);\n return;\n }\n\n setActiveTab('pending');\n }\n\n async function refreshTasks(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n if (!currentMemberId) {\n setPendingRows([]);\n setHistoryRows([]);\n return;\n }\n\n const [nextPendingTasks, nextHistoryTasks] = await Promise.all([\n listInboxTasks(currentMemberId),\n listApprovalHistoryTasks(currentMemberId),\n ]);\n const [nextPendingRows, nextHistoryRows] = await Promise.all([\n readInboxTaskRows(nextPendingTasks),\n readApprovalHistoryRows(nextHistoryTasks),\n ]);\n\n setPendingRows(nextPendingRows);\n setHistoryRows(nextHistoryRows);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <AppLayout activeHref={routes.inbox()}>\n <PageHeader>\n <ContentHeader\n description={`目前以 ${member?.name ?? currentMemberId ?? '目前登入會員'} 查詢待處理與歷史簽核任務。`}\n title=\"我的待簽\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Tab activeKey={activeTab} onChange={handleTabChange} size=\"sub\">\n <TabItem\n badgeCount={loading ? undefined : pendingRows.length}\n key=\"pending\"\n >\n 待簽核\n </TabItem>\n <TabItem\n badgeCount={loading ? undefined : trackingRows.length}\n key=\"tracking\"\n >\n 已處理未結束\n </TabItem>\n <TabItem key=\"history\">歷史簽核記錄</TabItem>\n </Tab>\n\n {activeTab === 'pending' ? (\n <Table\n actions={pendingTableActions}\n columns={pendingColumns}\n dataSource={pendingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'tracking' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={trackingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'history' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={historyRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n </Section>\n </SectionGroup>\n </AppLayout>\n );\n}\n\nasync function readInboxTaskRows(\n tasks: readonly TaskRecord[],\n): Promise<InboxTaskRow[]> {\n const instances = await readTaskInstances(tasks);\n\n return tasks.map(\n (task, index): InboxTaskRow => ({\n ...task,\n caseTitle: readTaskCaseTitle(task, instances[index] ?? null),\n key: task.id,\n slaStatusColor: readSlaStatusColor(task.slaDueAt),\n slaStatusText: readSlaStatusText(task.slaDueAt),\n statusLabel: readTaskStatusLabel(task.status),\n }),\n );\n}\n\nasync function readApprovalHistoryRows(\n tasks: readonly TaskRecord[],\n): Promise<ApprovalHistoryRow[]> {\n const [decisionLists, instances] = await Promise.all([\n Promise.all(tasks.map((task) => listTaskDecisions(task.id))),\n readTaskInstances(tasks),\n ]);\n\n return tasks.map((task, index): ApprovalHistoryRow => {\n const decision = readLatestTaskDecision(decisionLists[index] ?? []);\n const instance = instances[index] ?? null;\n\n return {\n ...task,\n caseTitle: readTaskCaseTitle(task, instance),\n decisionAction: decision?.action ?? null,\n decisionComment: decision?.comment ?? null,\n decisionCommentText: readDecisionCommentText(decision?.comment ?? null),\n decisionLabel: readTaskDecisionLabel(decision?.action ?? null),\n decidedAt: decision?.decidedAt ?? task.completedAt,\n instanceState: instance?.state ?? null,\n instanceStateLabel: readInstanceStateLabel(instance?.state ?? null),\n key: task.id,\n };\n });\n}\n\nasync function readTaskInstances(\n tasks: readonly TaskRecord[],\n): Promise<readonly (ApprovalInstanceRecord | null)[]> {\n return Promise.all(\n tasks.map(async (task): Promise<ApprovalInstanceRecord | null> => {\n try {\n return (await readApprovalInstance(task.instanceId)).instance;\n } catch {\n return null;\n }\n }),\n );\n}\n\nfunction readTaskCaseTitle(\n task: TaskRecord,\n instance: ApprovalInstanceRecord | null,\n): string {\n return instance ? readApprovalInstanceCaseTitle(instance) : task.instanceId;\n}\n\nfunction readLatestTaskDecision(\n decisions: readonly TaskDecisionRecord[],\n): TaskDecisionRecord | null {\n return [...decisions].sort(compareTaskDecisionDesc)[0] ?? null;\n}\n\nfunction compareTaskDecisionDesc(\n left: TaskDecisionRecord,\n right: TaskDecisionRecord,\n): number {\n return (\n new Date(right.decidedAt).getTime() - new Date(left.decidedAt).getTime()\n );\n}\n\nfunction readTaskDecisionLabel(\n action: TaskDecisionRecord['action'] | null,\n): string {\n if (action === 'APPROVED') {\n return '同意';\n }\n\n if (action === 'REJECTED') {\n return '拒絕';\n }\n\n if (action === 'RETURNED') {\n return '退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '轉派';\n }\n\n return '未記錄';\n}\n\nfunction readTaskDecisionColor(\n action: TaskDecisionRecord['action'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (action === 'APPROVED') {\n return 'text-success';\n }\n\n if (action === 'REJECTED' || action === 'RETURNED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readInstanceStateLabel(\n state: ApprovalInstanceRecord['state'] | null,\n): string {\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n if (state === 'APPROVED') {\n return '已通過';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n return '-';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceRecord['state'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') {\n return 'text-success';\n }\n\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readDecisionCommentText(comment: string | null): string {\n const trimmedComment = comment?.trim() ?? '';\n\n return trimmedComment || '-';\n}\n\nfunction formatHistoryDateTime(value: string | null): string {\n return formatDateTime(value);\n}\n\nfunction readSlaStatusText(value: string | null): string {\n if (!value) {\n return '-';\n }\n\n const dueAt = new Date(value).getTime();\n const now = Date.now();\n const diffMs = Math.abs(dueAt - now);\n const label = formatDuration(diffMs);\n\n return dueAt < now ? `已逾期 ${label}` : `剩餘 ${label}`;\n}\n\nfunction readSlaStatusColor(\n value: string | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (!value) {\n return 'text-neutral';\n }\n\n return new Date(value).getTime() < Date.now() ? 'text-error' : 'text-success';\n}\n\nfunction formatDuration(value: number): string {\n const totalMinutes = Math.max(1, Math.ceil(value / 60_000));\n const days = Math.floor(totalMinutes / 1440);\n const hours = Math.floor((totalMinutes % 1440) / 60);\n const minutes = totalMinutes % 60;\n\n if (days > 0) {\n return `${days}天 ${hours}小時`;\n }\n\n if (hours > 0) {\n return `${hours}小時 ${minutes}分鐘`;\n }\n\n return `${minutes}分鐘`;\n}\n\nfunction readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') {\n return '待處理';\n }\n\n if (status === 'IN_PROGRESS') {\n return '處理中';\n }\n\n if (status === 'COMPLETED') {\n return '已完成';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n if (status === 'CANCELLED') {\n return '已取消';\n }\n\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-B2gcOPkd.cjs");exports.InstanceDetailView=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-CqjqLd65.cjs");exports.InstanceDetailView=e.t;
@@ -1,2 +1,2 @@
1
- import { t as e } from "../../../chunks/detail-CfFyU5zC.js";
1
+ import { t as e } from "../../../chunks/detail-BcGAqJ_R.js";
2
2
  export { e as InstanceDetailView };
@@ -1,2 +1,2 @@
1
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/app-navigation-C_mbz7jx.cjs"),t=require("../../../chunks/auth-provider-BV8Iiwfb.cjs"),n=require("../../../chunks/format-date-time-isOa3e9q.cjs"),r=require("../../../chunks/FormRendererView-BwVsH2eX.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("react/jsx-runtime"),s=require("@rytass/bpm-core-client/workflow"),c=require("@mezzanine-ui/icons"),l=require("@mezzanine-ui/react/ContentHeader");l=e.o(l,1);let u=require("@rytass/bpm-core-client/form");var d={display:`grid`,gap:16};function f(e={}){return(0,o.jsx)(i.Suspense,{fallback:(0,o.jsx)(m,{}),children:(0,o.jsx)(p,{templateId:e.templateId??void 0})})}function p({templateId:f}){let p=t.a(),{member:m}=t.n(),g=m?.memberId??null,_=f??null,[v,y]=(0,i.useState)(null),[b,x]=(0,i.useState)({}),[S,C]=(0,i.useState)([]),[w,T]=(0,i.useState)(null),[E,D]=(0,i.useState)({}),[O,k]=(0,i.useState)(!0),[A,j]=(0,i.useState)(!1);(0,i.useEffect)(()=>{if(!_){F();return}I(_)},[_]);let M=(0,i.useMemo)(()=>S.map(e=>({...e,key:e.id,updatedAt:n.t(e.updatedAt),versionLabel:`v${e.version}`})),[S]),N=(0,i.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`模板名稱`,width:240},{dataIndex:`versionLabel`,key:`versionLabel`,title:`發布版本`,width:120},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:220}],[]),P=(0,i.useMemo)(()=>({render:e=>[{name:`發起`,onClick:()=>p.push(`/instances/new?templateId=${e.id}`),variant:`base-primary`}],variant:`base-secondary`,width:88}),[p]);async function F(){k(!0),T(null),y(null);try{C(await(0,s.listLaunchableTemplates)())}catch(e){T(h(e))}finally{k(!1)}}async function I(e){k(!0),T(null),C([]);try{y(await(0,s.readLaunchContext)(e))}catch(e){T(h(e))}finally{k(!1)}}async function L(){if(!v||!g)return;j(!0),T(null),D({});let e=(0,u.validateFormRendererValues)({schema:v.formVersion.schema,uiSchema:v.formVersion.uiSchema,values:b});if(!e.valid){D(e.errors),T(`請先補齊必填欄位。`),e.firstInvalidFieldKey&&(0,u.focusFormRendererField)(e.firstInvalidFieldKey),j(!1);return}try{let e=await(0,s.submitApprovalInstance)({formData:b,initiatorMemberId:g,templateId:v.template.id,title:(0,s.readFormDataCaseTitle)({fallbackTitle:v.template.name,formData:b,schema:v.formVersion.schema,uiSchema:v.formVersion.uiSchema})});p.push(`/instances/${e}`)}catch(e){T(h(e))}finally{j(!1)}}async function R(e,t){if(!g)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,s.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}return(0,o.jsxs)(e.t,{activeHref:`/`,children:[(0,o.jsx)(a.PageHeader,{children:(0,o.jsx)(l.default,{description:v?`${v.template.name} · 表單 v${v.formVersion.version}`:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`,children:v?(0,o.jsx)(a.Button,{disabled:O||A,icon:c.CheckedIcon,iconType:`leading`,onClick:L,variant:`base-primary`,children:`送出`}):null})}),(0,o.jsx)(a.SectionGroup,{children:(0,o.jsx)(a.Section,{children:(0,o.jsxs)(`div`,{style:d,children:[w?(0,o.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:w}):null,O?(0,o.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,v?(0,o.jsx)(r.t,{errors:E,maxWidth:480,onChange:e=>{x(e),D({})},onUploadAttachment:R,schema:v.formVersion.schema,singleColumn:!0,uiSchema:v.formVersion.uiSchema,value:b}):null,!_&&!O?M.length>0?(0,o.jsx)(a.Table,{actions:P,columns:N,dataSource:M,fullWidth:!0}):(0,o.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:`目前沒有可發起的已發布模板。`}):null]})})})]})}function m(){return(0,o.jsxs)(e.t,{activeHref:`/`,children:[(0,o.jsx)(a.PageHeader,{children:(0,o.jsx)(l.default,{description:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`})}),(0,o.jsx)(a.SectionGroup,{children:(0,o.jsx)(a.Section,{children:(0,o.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`})})})]})}function h(e){return e instanceof Error?e.message:`發生未知錯誤`}exports.InstanceNewView=f;
1
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/app-navigation-KnlJCUp1.cjs"),t=require("../../../chunks/auth-provider-BV8Iiwfb.cjs"),n=require("../../../chunks/format-date-time-26_pFvv4.cjs"),r=require("../../../chunks/routes-config-2aKbWq2H.cjs"),i=require("../../../chunks/FormRendererView-BwVsH2eX.cjs");let a=require("react"),o=require("@mezzanine-ui/react"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/icons"),u=require("@mezzanine-ui/react/ContentHeader");u=e.o(u,1);let d=require("@rytass/bpm-core-client/form");var f={display:`grid`,gap:16};function p(e={}){return(0,s.jsx)(a.Suspense,{fallback:(0,s.jsx)(h,{}),children:(0,s.jsx)(m,{templateId:e.templateId??void 0})})}function m({templateId:p}){let m=t.a(),h=r.r(),{member:_}=t.n(),v=_?.memberId??null,y=p??null,[b,x]=(0,a.useState)(null),[S,C]=(0,a.useState)({}),[w,T]=(0,a.useState)([]),[E,D]=(0,a.useState)(null),[O,k]=(0,a.useState)({}),[A,j]=(0,a.useState)(!0),[M,N]=(0,a.useState)(!1);(0,a.useEffect)(()=>{if(!y){L();return}R(y)},[y]);let P=(0,a.useMemo)(()=>w.map(e=>({...e,key:e.id,updatedAt:n.t(e.updatedAt),versionLabel:`v${e.version}`})),[w]),F=(0,a.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`模板名稱`,width:240},{dataIndex:`versionLabel`,key:`versionLabel`,title:`發布版本`,width:120},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:220}],[]),I=(0,a.useMemo)(()=>({render:e=>[{name:`發起`,onClick:()=>m.push(h.caseNew(e.id)),variant:`base-primary`}],variant:`base-secondary`,width:88}),[m]);async function L(){j(!0),D(null),x(null);try{T(await(0,c.listLaunchableTemplates)())}catch(e){D(g(e))}finally{j(!1)}}async function R(e){j(!0),D(null),T([]);try{x(await(0,c.readLaunchContext)(e))}catch(e){D(g(e))}finally{j(!1)}}async function z(){if(!b||!v)return;N(!0),D(null),k({});let e=(0,d.validateFormRendererValues)({schema:b.formVersion.schema,uiSchema:b.formVersion.uiSchema,values:S});if(!e.valid){k(e.errors),D(`請先補齊必填欄位。`),e.firstInvalidFieldKey&&(0,d.focusFormRendererField)(e.firstInvalidFieldKey),N(!1);return}try{let e=await(0,c.submitApprovalInstance)({formData:S,initiatorMemberId:v,templateId:b.template.id,title:(0,c.readFormDataCaseTitle)({fallbackTitle:b.template.name,formData:S,schema:b.formVersion.schema,uiSchema:b.formVersion.uiSchema})});m.push(h.caseDetail(e))}catch(e){D(g(e))}finally{N(!1)}}async function B(e,t){if(!v)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,c.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}return(0,s.jsxs)(e.t,{activeHref:`/`,children:[(0,s.jsx)(o.PageHeader,{children:(0,s.jsx)(u.default,{description:b?`${b.template.name} · 表單 v${b.formVersion.version}`:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`,children:b?(0,s.jsx)(o.Button,{disabled:A||M,icon:l.CheckedIcon,iconType:`leading`,onClick:z,variant:`base-primary`,children:`送出`}):null})}),(0,s.jsx)(o.SectionGroup,{children:(0,s.jsx)(o.Section,{children:(0,s.jsxs)(`div`,{style:f,children:[E?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:E}):null,A?(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,b?(0,s.jsx)(i.t,{errors:O,maxWidth:480,onChange:e=>{C(e),k({})},onUploadAttachment:B,schema:b.formVersion.schema,singleColumn:!0,uiSchema:b.formVersion.uiSchema,value:S}):null,!y&&!A?P.length>0?(0,s.jsx)(o.Table,{actions:I,columns:F,dataSource:P,fullWidth:!0}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`目前沒有可發起的已發布模板。`}):null]})})})]})}function h(){return(0,s.jsxs)(e.t,{activeHref:`/`,children:[(0,s.jsx)(o.PageHeader,{children:(0,s.jsx)(u.default,{description:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`})}),(0,s.jsx)(o.SectionGroup,{children:(0,s.jsx)(o.Section,{children:(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`})})})]})}function g(e){return e instanceof Error?e.message:`發生未知錯誤`}exports.InstanceNewView=p;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n focusFormRendererField,\n FormRendererValues,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { AppLayout } from '../../../components/app-navigation';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(`/instances/new?templateId=${record.id}`),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const validation = validateFormRendererValues({\n schema: context.formVersion.schema,\n uiSchema: context.formVersion.uiSchema,\n values: formValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setSubmitting(false);\n\n return;\n }\n\n try {\n const instanceId = await submitApprovalInstance({\n formData: formValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: formValues,\n schema: context.formVersion.schema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(`/instances/${instanceId}`);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n return (\n <AppLayout activeHref=\"/\">\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context ? (\n <FormRenderer\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onUploadAttachment={handleUploadAttachment}\n schema={context.formVersion.schema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </AppLayout>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <AppLayout activeHref=\"/\">\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </AppLayout>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n focusFormRendererField,\n FormRendererValues,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { AppLayout } from '../../../components/app-navigation';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const validation = validateFormRendererValues({\n schema: context.formVersion.schema,\n uiSchema: context.formVersion.uiSchema,\n values: formValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setSubmitting(false);\n\n return;\n }\n\n try {\n const instanceId = await submitApprovalInstance({\n formData: formValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: formValues,\n schema: context.formVersion.schema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n return (\n <AppLayout activeHref=\"/\">\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context ? (\n <FormRenderer\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onUploadAttachment={handleUploadAttachment}\n schema={context.formVersion.schema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </AppLayout>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <AppLayout activeHref=\"/\">\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </AppLayout>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}