@rytass/bpm-core-react 0.17.8 → 0.18.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.
- package/CHANGELOG.md +58 -0
- package/README.md +8 -0
- package/dist/chunks/{FormBuilderView-ClLnQ1e_.js → FormBuilderView-BVKY1j_0.js} +504 -452
- package/dist/chunks/FormBuilderView-BVKY1j_0.js.map +1 -0
- package/dist/chunks/FormBuilderView-SrGltzFT.cjs +3 -0
- package/dist/chunks/FormBuilderView-SrGltzFT.cjs.map +1 -0
- package/dist/chunks/approver-filled-form-Dm3Iw7iw.cjs +2 -0
- package/dist/chunks/approver-filled-form-Dm3Iw7iw.cjs.map +1 -0
- package/dist/chunks/{approver-filled-form-DuQGPtNB.js → approver-filled-form-ZEwpmsHJ.js} +21 -8
- package/dist/chunks/approver-filled-form-ZEwpmsHJ.js.map +1 -0
- package/dist/chunks/{compose-jnvnnVfN.js → compose-B1GlrZW9.js} +3 -3
- package/dist/chunks/{compose-jnvnnVfN.js.map → compose-B1GlrZW9.js.map} +1 -1
- package/dist/chunks/{compose-Cock_B2Q.cjs → compose-DZk-SfHT.cjs} +2 -2
- package/dist/chunks/{compose-Cock_B2Q.cjs.map → compose-DZk-SfHT.cjs.map} +1 -1
- package/dist/chunks/{designer-B8Gvew_k.js → designer-BCLrjb4H.js} +886 -851
- package/dist/chunks/designer-BCLrjb4H.js.map +1 -0
- package/dist/chunks/designer-BYYxEN9L.cjs +65 -0
- package/dist/chunks/designer-BYYxEN9L.cjs.map +1 -0
- package/dist/chunks/{detail-D6X61pkg.js → detail-4F39ggBn.js} +883 -827
- package/dist/chunks/detail-4F39ggBn.js.map +1 -0
- package/dist/chunks/detail-BkMtA_0K.cjs +2 -0
- package/dist/chunks/detail-BkMtA_0K.cjs.map +1 -0
- package/dist/chunks/{orgs-Lg7tXv2u.js → orgs-8hje_l2n.js} +9 -4
- package/dist/chunks/orgs-8hje_l2n.js.map +1 -0
- package/dist/chunks/{orgs-C8usknWb.cjs → orgs-BeeDDWL1.cjs} +2 -2
- package/dist/chunks/orgs-BeeDDWL1.cjs.map +1 -0
- package/dist/chunks/users-O2L_M3BK.cjs +2 -0
- package/dist/chunks/users-O2L_M3BK.cjs.map +1 -0
- package/dist/chunks/{users-DRbuDYF1.js → users-Pl6hY5Y5.js} +160 -93
- package/dist/chunks/users-Pl6hY5Y5.js.map +1 -0
- package/dist/pages/admin/orgs/index.cjs +1 -1
- package/dist/pages/admin/orgs/index.js +1 -1
- package/dist/pages/admin/users/index.cjs +1 -1
- package/dist/pages/admin/users/index.js +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.js +2 -2
- package/dist/views/admin/orgs/index.cjs +1 -1
- package/dist/views/admin/orgs/index.js +1 -1
- package/dist/views/admin/users/index.cjs +1 -1
- package/dist/views/admin/users/index.js +1 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/inbox/index.cjs +1 -1
- package/dist/views/inbox/index.cjs.map +1 -1
- package/dist/views/inbox/index.js +159 -78
- package/dist/views/inbox/index.js.map +1 -1
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +9 -1
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +9 -1
- package/dist/views/instances/detail/use-resubmit-comment-draft.d.cts +18 -0
- package/dist/views/instances/detail/use-resubmit-comment-draft.d.ts +18 -0
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.cjs.map +1 -1
- package/dist/views/instances/new/index.js +15 -11
- package/dist/views/instances/new/index.js.map +1 -1
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunks/FormBuilderView-CUOyS07f.cjs +0 -3
- package/dist/chunks/FormBuilderView-CUOyS07f.cjs.map +0 -1
- package/dist/chunks/FormBuilderView-ClLnQ1e_.js.map +0 -1
- package/dist/chunks/approver-filled-form-D1DmqDVP.cjs +0 -2
- package/dist/chunks/approver-filled-form-D1DmqDVP.cjs.map +0 -1
- package/dist/chunks/approver-filled-form-DuQGPtNB.js.map +0 -1
- package/dist/chunks/designer-B8Gvew_k.js.map +0 -1
- package/dist/chunks/designer-CAEFV1ve.cjs +0 -65
- package/dist/chunks/designer-CAEFV1ve.cjs.map +0 -1
- package/dist/chunks/detail-COh5sjAt.cjs +0 -2
- package/dist/chunks/detail-COh5sjAt.cjs.map +0 -1
- package/dist/chunks/detail-D6X61pkg.js.map +0 -1
- package/dist/chunks/orgs-C8usknWb.cjs.map +0 -1
- package/dist/chunks/orgs-Lg7tXv2u.js.map +0 -1
- package/dist/chunks/users-DRbuDYF1.js.map +0 -1
- package/dist/chunks/users-DVQicZIo.cjs +0 -2
- package/dist/chunks/users-DVQicZIo.cjs.map +0 -1
|
@@ -7,16 +7,21 @@ import { t as i } from "../../chunks/task-node-label-CWZgOBj0.js";
|
|
|
7
7
|
import { useEffect as a, useMemo as o, useState as s } from "react";
|
|
8
8
|
import { Badge as c, Button as l, PageHeader as u, Section as d, SectionGroup as f, Tab as p, TabItem as m, Table as h, Typography as g } from "@mezzanine-ui/react";
|
|
9
9
|
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
10
|
-
import { listApprovalHistoryTasks as b,
|
|
10
|
+
import { listApprovalHistoryTasks as b, listApprovalInstancesPage as x, listInboxTasks as ee, listTaskDecisions as S, readApprovalInstance as C, readApprovalInstanceCaseTitle as w } from "@rytass/bpm-core-client/workflow";
|
|
11
11
|
import T from "@mezzanine-ui/react/ContentHeader";
|
|
12
12
|
import { PlusIcon as E } from "@mezzanine-ui/icons";
|
|
13
13
|
//#region src/views/inbox/InboxView.tsx
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
var D = 100, O = {
|
|
15
|
+
display: "grid",
|
|
16
|
+
gap: "var(--mzn-spacing-gap-base)",
|
|
17
|
+
marginBottom: "var(--mzn-spacing-padding-vertical-spacious)"
|
|
18
|
+
};
|
|
19
|
+
function k() {
|
|
20
|
+
let i = e(), x = r(), { member: S } = t(), C = S?.memberId ?? null, [w, D] = s("pending"), [k, M] = s(null), [N, P] = s([]), [F, I] = s(!0), [L, z] = s([]), [V, U] = s([]), [W, G] = s(!1);
|
|
16
21
|
a(() => {
|
|
17
|
-
|
|
18
|
-
}, [
|
|
19
|
-
let
|
|
22
|
+
C && ie();
|
|
23
|
+
}, [C]);
|
|
24
|
+
let K = o(() => [
|
|
20
25
|
{
|
|
21
26
|
dataIndex: "caseTitle",
|
|
22
27
|
key: "caseTitle",
|
|
@@ -66,14 +71,35 @@ function D() {
|
|
|
66
71
|
title: "建立時間",
|
|
67
72
|
width: 220
|
|
68
73
|
}
|
|
69
|
-
], []),
|
|
74
|
+
], []), J = o(() => ({
|
|
70
75
|
render: (e) => [{
|
|
71
76
|
name: "處理",
|
|
72
|
-
onClick: () => i.push(
|
|
77
|
+
onClick: () => i.push(x.caseDetail(e.instanceId))
|
|
73
78
|
}],
|
|
74
79
|
variant: "base-secondary",
|
|
75
80
|
width: 88
|
|
76
|
-
}), [i,
|
|
81
|
+
}), [i, x]), Y = o(() => [{
|
|
82
|
+
dataIndex: "caseTitle",
|
|
83
|
+
key: "caseTitle",
|
|
84
|
+
title: "案件",
|
|
85
|
+
width: 280
|
|
86
|
+
}, {
|
|
87
|
+
key: "startedAt",
|
|
88
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
89
|
+
component: "span",
|
|
90
|
+
variant: "body",
|
|
91
|
+
children: n(e.startedAt)
|
|
92
|
+
}),
|
|
93
|
+
title: "發起時間",
|
|
94
|
+
width: 220
|
|
95
|
+
}], []), X = o(() => ({
|
|
96
|
+
render: (e) => [{
|
|
97
|
+
name: "重新送出",
|
|
98
|
+
onClick: () => i.push(x.caseDetail(e.id))
|
|
99
|
+
}],
|
|
100
|
+
variant: "base-secondary",
|
|
101
|
+
width: 120
|
|
102
|
+
}), [i, x]), Z = o(() => [
|
|
77
103
|
{
|
|
78
104
|
dataIndex: "caseTitle",
|
|
79
105
|
key: "caseTitle",
|
|
@@ -89,7 +115,7 @@ function D() {
|
|
|
89
115
|
{
|
|
90
116
|
key: "decisionLabel",
|
|
91
117
|
render: (e) => /* @__PURE__ */ v(g, {
|
|
92
|
-
color:
|
|
118
|
+
color: R(e.decisionAction),
|
|
93
119
|
component: "span",
|
|
94
120
|
variant: "body",
|
|
95
121
|
children: e.decisionLabel
|
|
@@ -110,7 +136,7 @@ function D() {
|
|
|
110
136
|
{
|
|
111
137
|
key: "instanceStateLabel",
|
|
112
138
|
render: (e) => /* @__PURE__ */ v(g, {
|
|
113
|
-
color:
|
|
139
|
+
color: B(e.instanceState),
|
|
114
140
|
component: "span",
|
|
115
141
|
variant: "body",
|
|
116
142
|
children: e.instanceStateLabel
|
|
@@ -123,124 +149,179 @@ function D() {
|
|
|
123
149
|
render: (e) => /* @__PURE__ */ v(g, {
|
|
124
150
|
component: "span",
|
|
125
151
|
variant: "body",
|
|
126
|
-
children:
|
|
152
|
+
children: H(e.decidedAt)
|
|
127
153
|
}),
|
|
128
154
|
title: "簽核時間",
|
|
129
155
|
width: 220
|
|
130
156
|
}
|
|
131
|
-
], []),
|
|
157
|
+
], []), Q = o(() => ({
|
|
132
158
|
render: (e) => [{
|
|
133
159
|
name: "查看",
|
|
134
|
-
onClick: () => i.push(
|
|
160
|
+
onClick: () => i.push(x.caseDetail(e.instanceId))
|
|
135
161
|
}],
|
|
136
162
|
variant: "base-secondary",
|
|
137
163
|
width: 88
|
|
138
|
-
}), [i,
|
|
139
|
-
function
|
|
140
|
-
|
|
164
|
+
}), [i, x]), $ = o(() => N.filter((e) => e.instanceState === "RUNNING"), [N]);
|
|
165
|
+
function re(e) {
|
|
166
|
+
D(e === "history" || e === "pending" || e === "tracking" ? e : "pending");
|
|
141
167
|
}
|
|
142
|
-
async function
|
|
143
|
-
|
|
168
|
+
async function ie() {
|
|
169
|
+
I(!0), M(null);
|
|
144
170
|
try {
|
|
145
|
-
if (!
|
|
146
|
-
|
|
171
|
+
if (!C) {
|
|
172
|
+
z([]), P([]), U([]), G(!1);
|
|
147
173
|
return;
|
|
148
174
|
}
|
|
149
|
-
let [e, t
|
|
150
|
-
|
|
175
|
+
let [e, t, n] = await Promise.all([
|
|
176
|
+
ee(C),
|
|
177
|
+
b(C),
|
|
178
|
+
j(C)
|
|
179
|
+
]), [r, i] = await Promise.all([te(e), ne(t)]);
|
|
180
|
+
z(r), P(i), U(n?.rows ?? []), G(n?.truncated ?? !1);
|
|
151
181
|
} catch (e) {
|
|
152
|
-
M(
|
|
182
|
+
M(q(e));
|
|
153
183
|
} finally {
|
|
154
|
-
|
|
184
|
+
I(!1);
|
|
155
185
|
}
|
|
156
186
|
}
|
|
157
187
|
return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(u, { children: /* @__PURE__ */ v(T, {
|
|
158
|
-
description: `目前以 ${
|
|
188
|
+
description: `目前以 ${S?.name ?? C ?? "目前登入會員"} 查詢待處理與歷史簽核任務。`,
|
|
159
189
|
title: "我的待簽",
|
|
160
190
|
children: /* @__PURE__ */ v(l, {
|
|
161
191
|
icon: E,
|
|
162
192
|
iconType: "leading",
|
|
163
|
-
onClick: () => i.push(
|
|
193
|
+
onClick: () => i.push(x.caseNew()),
|
|
164
194
|
variant: "base-primary",
|
|
165
195
|
children: "發起簽核"
|
|
166
196
|
})
|
|
167
197
|
}) }), /* @__PURE__ */ v(f, { children: /* @__PURE__ */ y(d, { children: [
|
|
168
|
-
|
|
198
|
+
k ? /* @__PURE__ */ v(g, {
|
|
169
199
|
color: "text-error",
|
|
170
200
|
variant: "body",
|
|
171
|
-
children:
|
|
201
|
+
children: k
|
|
172
202
|
}) : null,
|
|
173
203
|
/* @__PURE__ */ y(p, {
|
|
174
|
-
activeKey:
|
|
175
|
-
onChange:
|
|
204
|
+
activeKey: w,
|
|
205
|
+
onChange: re,
|
|
176
206
|
size: "sub",
|
|
177
207
|
children: [
|
|
178
208
|
/* @__PURE__ */ v(m, {
|
|
179
|
-
badgeCount:
|
|
209
|
+
badgeCount: F ? void 0 : L.length,
|
|
180
210
|
children: "待簽核"
|
|
181
211
|
}, "pending"),
|
|
182
212
|
/* @__PURE__ */ v(m, {
|
|
183
|
-
badgeCount:
|
|
213
|
+
badgeCount: F ? void 0 : $.length,
|
|
184
214
|
children: "已處理未結束"
|
|
185
215
|
}, "tracking"),
|
|
186
216
|
/* @__PURE__ */ v(m, { children: "歷史簽核記錄" }, "history")
|
|
187
217
|
]
|
|
188
218
|
}),
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
219
|
+
w === "pending" && (V.length > 0 || W) ? /* @__PURE__ */ y("div", {
|
|
220
|
+
"data-returned-instances": "",
|
|
221
|
+
style: O,
|
|
222
|
+
children: [
|
|
223
|
+
V.length > 0 ? /* @__PURE__ */ v(g, {
|
|
224
|
+
component: "h2",
|
|
225
|
+
variant: "label-primary",
|
|
226
|
+
children: "被退回待重送"
|
|
227
|
+
}) : null,
|
|
228
|
+
/* @__PURE__ */ v(g, {
|
|
229
|
+
color: "text-neutral",
|
|
230
|
+
variant: "caption",
|
|
231
|
+
children: A(V.length > 0, W)
|
|
232
|
+
}),
|
|
233
|
+
V.length > 0 ? /* @__PURE__ */ v(h, {
|
|
234
|
+
actions: X,
|
|
235
|
+
columns: Y,
|
|
236
|
+
dataSource: [...V],
|
|
237
|
+
fullWidth: !0
|
|
238
|
+
}) : null
|
|
239
|
+
]
|
|
240
|
+
}) : null,
|
|
241
|
+
w === "pending" ? /* @__PURE__ */ v(h, {
|
|
242
|
+
actions: J,
|
|
243
|
+
columns: K,
|
|
244
|
+
dataSource: L,
|
|
193
245
|
fullWidth: !0,
|
|
194
|
-
loading:
|
|
246
|
+
loading: F
|
|
195
247
|
}) : null,
|
|
196
|
-
|
|
197
|
-
actions:
|
|
198
|
-
columns:
|
|
199
|
-
dataSource:
|
|
248
|
+
w === "tracking" ? /* @__PURE__ */ v(h, {
|
|
249
|
+
actions: Q,
|
|
250
|
+
columns: Z,
|
|
251
|
+
dataSource: $,
|
|
200
252
|
fullWidth: !0,
|
|
201
|
-
loading:
|
|
253
|
+
loading: F
|
|
202
254
|
}) : null,
|
|
203
|
-
|
|
204
|
-
actions:
|
|
205
|
-
columns:
|
|
255
|
+
w === "history" ? /* @__PURE__ */ v(h, {
|
|
256
|
+
actions: Q,
|
|
257
|
+
columns: Z,
|
|
206
258
|
dataSource: N,
|
|
207
259
|
fullWidth: !0,
|
|
208
|
-
loading:
|
|
260
|
+
loading: F
|
|
209
261
|
}) : null
|
|
210
262
|
] }) })] });
|
|
211
263
|
}
|
|
212
|
-
|
|
213
|
-
|
|
264
|
+
function A(e, t) {
|
|
265
|
+
return e ? t ? "你發起的案件被退回,請修改後重新送出。可能還有其他被退回的案件,請到「我發起的」查看。" : "你發起的案件被退回,請修改後重新送出。" : `前 ${D} 筆被退回的案件中沒有你發起的,可能還有其他被退回的案件,請到「我發起的」查看。`;
|
|
266
|
+
}
|
|
267
|
+
async function j(e) {
|
|
268
|
+
try {
|
|
269
|
+
let t = await x({
|
|
270
|
+
page: 1,
|
|
271
|
+
pageSize: D,
|
|
272
|
+
searchText: null,
|
|
273
|
+
state: "RETURNED",
|
|
274
|
+
templateId: null,
|
|
275
|
+
view: "SENT"
|
|
276
|
+
});
|
|
277
|
+
return {
|
|
278
|
+
rows: M(t.instances, e),
|
|
279
|
+
truncated: t.totalCount > t.instances.length
|
|
280
|
+
};
|
|
281
|
+
} catch {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function M(e, t) {
|
|
286
|
+
return e.filter((e) => e.initiatorMemberId === t).map((e) => ({
|
|
287
|
+
caseTitle: w(e),
|
|
288
|
+
id: e.id,
|
|
289
|
+
key: e.id,
|
|
290
|
+
startedAt: e.startedAt
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
async function te(e) {
|
|
294
|
+
let t = await N(e);
|
|
214
295
|
return e.map((e, n) => ({
|
|
215
296
|
...e,
|
|
216
|
-
caseTitle:
|
|
297
|
+
caseTitle: P(e, t[n] ?? null),
|
|
217
298
|
key: e.id,
|
|
218
299
|
nodeText: i(e),
|
|
219
|
-
slaStatusColor:
|
|
220
|
-
slaStatusText:
|
|
221
|
-
statusLabel:
|
|
300
|
+
slaStatusColor: W(e.slaDueAt),
|
|
301
|
+
slaStatusText: U(e.slaDueAt),
|
|
302
|
+
statusLabel: K(e.status)
|
|
222
303
|
}));
|
|
223
304
|
}
|
|
224
|
-
async function
|
|
225
|
-
let [t, n] = await Promise.all([Promise.all(e.map((e) => S(e.id))),
|
|
305
|
+
async function ne(e) {
|
|
306
|
+
let [t, n] = await Promise.all([Promise.all(e.map((e) => S(e.id))), N(e)]);
|
|
226
307
|
return e.map((e, r) => {
|
|
227
|
-
let a =
|
|
308
|
+
let a = F(t[r] ?? []), o = n[r] ?? null;
|
|
228
309
|
return {
|
|
229
310
|
...e,
|
|
230
|
-
caseTitle:
|
|
311
|
+
caseTitle: P(e, o),
|
|
231
312
|
decisionAction: a?.action ?? null,
|
|
232
313
|
decisionComment: a?.comment ?? null,
|
|
233
|
-
decisionCommentText:
|
|
234
|
-
decisionLabel:
|
|
314
|
+
decisionCommentText: V(a?.comment ?? null),
|
|
315
|
+
decisionLabel: L(a?.action ?? null),
|
|
235
316
|
decidedAt: a?.decidedAt ?? e.completedAt,
|
|
236
317
|
instanceState: o?.state ?? null,
|
|
237
|
-
instanceStateLabel:
|
|
318
|
+
instanceStateLabel: z(o?.state ?? null),
|
|
238
319
|
key: e.id,
|
|
239
320
|
nodeText: i(e)
|
|
240
321
|
};
|
|
241
322
|
});
|
|
242
323
|
}
|
|
243
|
-
async function
|
|
324
|
+
async function N(e) {
|
|
244
325
|
return Promise.all(e.map(async (e) => {
|
|
245
326
|
try {
|
|
246
327
|
return (await C(e.instanceId)).instance;
|
|
@@ -249,52 +330,52 @@ async function A(e) {
|
|
|
249
330
|
}
|
|
250
331
|
}));
|
|
251
332
|
}
|
|
252
|
-
function
|
|
333
|
+
function P(e, t) {
|
|
253
334
|
return t ? w(t) : e.instanceId;
|
|
254
335
|
}
|
|
255
|
-
function
|
|
256
|
-
return [...e].sort(
|
|
336
|
+
function F(e) {
|
|
337
|
+
return [...e].sort(I)[0] ?? null;
|
|
257
338
|
}
|
|
258
|
-
function
|
|
339
|
+
function I(e, t) {
|
|
259
340
|
return new Date(t.decidedAt).getTime() - new Date(e.decidedAt).getTime();
|
|
260
341
|
}
|
|
261
|
-
function
|
|
342
|
+
function L(e) {
|
|
262
343
|
return e === "APPROVED" ? "同意" : e === "REJECTED" ? "拒絕" : e === "RETURNED" ? "退回" : e === "TRANSFERRED" ? "轉派" : "未記錄";
|
|
263
344
|
}
|
|
264
|
-
function
|
|
345
|
+
function R(e) {
|
|
265
346
|
return e === "APPROVED" ? "text-success" : e === "REJECTED" || e === "RETURNED" ? "text-error" : "text-neutral";
|
|
266
347
|
}
|
|
267
|
-
function
|
|
348
|
+
function z(e) {
|
|
268
349
|
return e === "RUNNING" ? "進行中" : e === "APPROVED" ? "已通過" : e === "REJECTED" ? "已拒絕" : e === "RETURNED" ? "已退回" : e === "CANCELLED" ? "已取消" : e === "EXPIRED" ? "已逾期" : e === "DRAFT" ? "草稿" : "-";
|
|
269
350
|
}
|
|
270
|
-
function
|
|
351
|
+
function B(e) {
|
|
271
352
|
return e === "APPROVED" ? "text-success" : e === "REJECTED" || e === "CANCELLED" || e === "EXPIRED" ? "text-error" : "text-neutral";
|
|
272
353
|
}
|
|
273
|
-
function
|
|
354
|
+
function V(e) {
|
|
274
355
|
return (e?.trim() ?? "") || "-";
|
|
275
356
|
}
|
|
276
|
-
function
|
|
357
|
+
function H(e) {
|
|
277
358
|
return n(e);
|
|
278
359
|
}
|
|
279
|
-
function
|
|
360
|
+
function U(e) {
|
|
280
361
|
if (!e) return "-";
|
|
281
|
-
let t = new Date(e).getTime(), n = Date.now(), r =
|
|
362
|
+
let t = new Date(e).getTime(), n = Date.now(), r = G(Math.abs(t - n));
|
|
282
363
|
return t < n ? `已逾期 ${r}` : `剩餘 ${r}`;
|
|
283
364
|
}
|
|
284
|
-
function
|
|
365
|
+
function W(e) {
|
|
285
366
|
return e ? new Date(e).getTime() < Date.now() ? "text-error" : "text-success" : "text-neutral";
|
|
286
367
|
}
|
|
287
|
-
function
|
|
368
|
+
function G(e) {
|
|
288
369
|
let t = Math.max(1, Math.ceil(e / 6e4)), n = Math.floor(t / 1440), r = Math.floor(t % 1440 / 60), i = t % 60;
|
|
289
370
|
return n > 0 ? `${n}天 ${r}小時` : r > 0 ? `${r}小時 ${i}分鐘` : `${i}分鐘`;
|
|
290
371
|
}
|
|
291
|
-
function
|
|
372
|
+
function K(e) {
|
|
292
373
|
return e === "PENDING" ? "待處理" : e === "IN_PROGRESS" ? "處理中" : e === "COMPLETED" ? "已完成" : e === "TRANSFERRED" ? "已轉派" : e === "CANCELLED" ? "已取消" : e;
|
|
293
374
|
}
|
|
294
|
-
function
|
|
375
|
+
function q(e) {
|
|
295
376
|
return e instanceof Error ? e.message : "發生未知錯誤";
|
|
296
377
|
}
|
|
297
378
|
//#endregion
|
|
298
|
-
export {
|
|
379
|
+
export { k as InboxView };
|
|
299
380
|
|
|
300
381
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readTaskNodeText","Fragment$1","ContentHeader","InboxView","router","routes","useBPMRoutes","currentMemberId","member","activeTab","setActiveTab","useState","error","setError","historyRows","setHistoryRows","loading","setLoading","pendingRows","setPendingRows","refreshTasks","pendingColumns","useMemo","record","Badge","Typography","pendingTableActions","historyColumns","readTaskDecisionColor","readInstanceStateColor","formatHistoryDateTime","historyTableActions","trackingRows","row","handleTabChange","activeKey","nextPendingTasks","nextHistoryTasks","listInboxTasks","listApprovalHistoryTasks","nextPendingRows","nextHistoryRows","readInboxTaskRows","readApprovalHistoryRows","requestError","readErrorMessage","PageHeader","Button","PlusIcon","SectionGroup","Section","Tab","TabItem","Table","instances","readTaskInstances","tasks","task","readTaskCaseTitle","index","readSlaStatusColor","readSlaStatusText","readTaskStatusLabel","decisionLists","listTaskDecisions","decision","readLatestTaskDecision","instance","readDecisionCommentText","readTaskDecisionLabel","readInstanceStateLabel","readApprovalInstance","readApprovalInstanceCaseTitle","decisions","compareTaskDecisionDesc","right","left","action","state","comment","value","dueAt","now","label","formatDuration","totalMinutes","days","hours","minutes","status"],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\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 { readTaskNodeText } from '../../lib/task-node-label';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n nodeText: 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 nodeText: string;\n }\n>;\n\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(): 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: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'fill',\n // Approving one of these needs the case page, where the fill is entered.\n render: (record: InboxTaskRow): ReactElement | null =>\n record.hasFillableFields ? (\n <Badge size=\"sub\" text=\"需補填\" variant=\"dot-warning\" />\n ) : null,\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: 'nodeText', key: 'nodeText', 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 <>\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 </>\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 nodeText: readTaskNodeText(task),\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 nodeText: readTaskNodeText(task),\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":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readTaskNodeText","Fragment$1","ContentHeader","RETURNED_INSTANCE_PAGE_SIZE","RETURNED_SECTION_STYLE","InboxView","router","routes","useBPMRoutes","currentMemberId","member","activeTab","setActiveTab","useState","error","setError","historyRows","setHistoryRows","loading","setLoading","pendingRows","setPendingRows","returnedRows","setReturnedRows","returnedTruncated","setReturnedTruncated","refreshTasks","pendingColumns","useMemo","record","Badge","Typography","pendingTableActions","returnedColumns","returnedTableActions","historyColumns","readTaskDecisionColor","readInstanceStateColor","formatHistoryDateTime","historyTableActions","trackingRows","row","handleTabChange","activeKey","nextPendingTasks","nextHistoryTasks","returned","listInboxTasks","listApprovalHistoryTasks","readReturnedInstances","nextPendingRows","nextHistoryRows","readInboxTaskRows","readApprovalHistoryRows","requestError","readErrorMessage","PageHeader","Button","PlusIcon","SectionGroup","Section","Tab","TabItem","readReturnedSectionHint","Table","hasRows","truncated","page","listApprovalInstancesPage","readReturnedInstanceRows","instances","instance","readApprovalInstanceCaseTitle","readTaskInstances","tasks","task","readTaskCaseTitle","index","readSlaStatusColor","readSlaStatusText","readTaskStatusLabel","decisionLists","listTaskDecisions","decision","readLatestTaskDecision","readDecisionCommentText","readTaskDecisionLabel","readInstanceStateLabel","readApprovalInstance","decisions","compareTaskDecisionDesc","right","left","action","state","comment","value","dueAt","now","label","formatDuration","totalMinutes","days","hours","minutes","status"],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport {\n type CSSProperties,\n type Key,\n ReactElement,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Badge,\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 type ApprovalInstancesPageResult,\n listApprovalHistoryTasks,\n listApprovalInstancesPage,\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 { readTaskNodeText } from '../../lib/task-node-label';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n nodeText: string;\n slaStatusColor: 'text-error' | 'text-neutral' | 'text-success';\n slaStatusText: string;\n statusLabel: string;\n }\n>;\n\ntype ReturnedInstanceRow = Readonly<{\n caseTitle: string;\n id: string;\n key: string;\n startedAt: string | null;\n}>;\n\n/** The server caps a page at 100; more than that is left to 我發起的. */\nconst RETURNED_INSTANCE_PAGE_SIZE = 100;\n\nconst RETURNED_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 'var(--mzn-spacing-gap-base)',\n marginBottom: 'var(--mzn-spacing-padding-vertical-spacious)',\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 nodeText: string;\n }\n>;\n\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(): 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 const [returnedRows, setReturnedRows] = useState<\n readonly ReturnedInstanceRow[]\n >([]);\n const [returnedTruncated, setReturnedTruncated] = useState(false);\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: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'fill',\n // Approving one of these needs the case page, where the fill is entered.\n render: (record: InboxTaskRow): ReactElement | null =>\n record.hasFillableFields ? (\n <Badge size=\"sub\" text=\"需補填\" variant=\"dot-warning\" />\n ) : null,\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 returnedColumns = useMemo(\n (): TableColumn<ReturnedInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n {\n key: 'startedAt',\n render: (record: ReturnedInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n ],\n [],\n );\n const returnedTableActions = useMemo(\n (): TableActions<ReturnedInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ReturnedInstanceRow>['render']> => [\n {\n name: '重新送出',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 120,\n }),\n [router, routes],\n );\n const historyColumns = useMemo(\n (): TableColumn<ApprovalHistoryRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', 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 setReturnedRows([]);\n setReturnedTruncated(false);\n return;\n }\n\n const [nextPendingTasks, nextHistoryTasks, returned] =\n await Promise.all([\n listInboxTasks(currentMemberId),\n listApprovalHistoryTasks(currentMemberId),\n readReturnedInstances(currentMemberId),\n ]);\n const [nextPendingRows, nextHistoryRows] = await Promise.all([\n readInboxTaskRows(nextPendingTasks),\n readApprovalHistoryRows(nextHistoryTasks),\n ]);\n\n setPendingRows(nextPendingRows);\n setHistoryRows(nextHistoryRows);\n setReturnedRows(returned?.rows ?? []);\n setReturnedTruncated(returned?.truncated ?? false);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\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 {/* A truncated page with none of the member's own cases still\n points to 我發起的: theirs may sit past the first page. */}\n {activeTab === 'pending' &&\n (returnedRows.length > 0 || returnedTruncated) ? (\n <div data-returned-instances=\"\" style={RETURNED_SECTION_STYLE}>\n {/* Without rows there is nothing here to resubmit, only the\n pointer to 我發起的. */}\n {returnedRows.length > 0 ? (\n <Typography component=\"h2\" variant=\"label-primary\">\n 被退回待重送\n </Typography>\n ) : null}\n <Typography color=\"text-neutral\" variant=\"caption\">\n {readReturnedSectionHint(\n returnedRows.length > 0,\n returnedTruncated,\n )}\n </Typography>\n {returnedRows.length > 0 ? (\n <Table\n actions={returnedTableActions}\n columns={returnedColumns}\n dataSource={[...returnedRows]}\n fullWidth\n />\n ) : null}\n </div>\n ) : null}\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 </>\n );\n}\n\nfunction readReturnedSectionHint(\n hasRows: boolean,\n truncated: boolean,\n): string {\n if (!hasRows) {\n return `前 ${RETURNED_INSTANCE_PAGE_SIZE} 筆被退回的案件中沒有你發起的,可能還有其他被退回的案件,請到「我發起的」查看。`;\n }\n\n return truncated\n ? '你發起的案件被退回,請修改後重新送出。可能還有其他被退回的案件,請到「我發起的」查看。'\n : '你發起的案件被退回,請修改後重新送出。';\n}\n\n/**\n * Returned cases are a side list: a failure here, in the request or in reading\n * its rows, hides that section instead of taking the pending and history tasks\n * down with it.\n */\nasync function readReturnedInstances(\n currentMemberId: string,\n): Promise<Readonly<{\n rows: readonly ReturnedInstanceRow[];\n truncated: boolean;\n}> | null> {\n try {\n // SENT also lists cases filed on someone else's behalf; only the\n // initiator may resubmit, so those are filtered out here.\n const page: ApprovalInstancesPageResult = await listApprovalInstancesPage({\n page: 1,\n pageSize: RETURNED_INSTANCE_PAGE_SIZE,\n searchText: null,\n state: 'RETURNED',\n templateId: null,\n view: 'SENT',\n });\n\n return {\n rows: readReturnedInstanceRows(page.instances, currentMemberId),\n // The total includes cases filed for someone else, so compare it with\n // what this page fetched rather than with the rows kept.\n truncated: page.totalCount > page.instances.length,\n };\n } catch {\n return null;\n }\n}\n\nfunction readReturnedInstanceRows(\n instances: readonly ApprovalInstanceRecord[],\n currentMemberId: string,\n): readonly ReturnedInstanceRow[] {\n return instances\n .filter(\n (instance): boolean => instance.initiatorMemberId === currentMemberId,\n )\n .map(\n (instance): ReturnedInstanceRow => ({\n caseTitle: readApprovalInstanceCaseTitle(instance),\n id: instance.id,\n key: instance.id,\n startedAt: instance.startedAt,\n }),\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 nodeText: readTaskNodeText(task),\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 nodeText: readTaskNodeText(task),\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-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-BkMtA_0K.cjs");exports.InstanceAttachmentsSection=e.o,exports.InstanceDetailView=e.t,exports.InstanceFormSection=e.s,exports.InstanceHistorySection=e.r,exports.InstanceSignaturesSection=e.i,exports.InstanceTasksSection=e.a,exports.InstanceWebhookDeliveriesSection=e.n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { o as InstanceAttachmentsSection, t as InstanceDetailView, s as InstanceFormSection, r as InstanceHistorySection, i as InstanceSignaturesSection, a as InstanceTasksSection, n as InstanceWebhookDeliveriesSection } from "../../../chunks/detail-
|
|
1
|
+
export { o as InstanceAttachmentsSection, t as InstanceDetailView, s as InstanceFormSection, r as InstanceHistorySection, i as InstanceSignaturesSection, a as InstanceTasksSection, n as InstanceWebhookDeliveriesSection } from "../../../chunks/detail-4F39ggBn.js";
|
|
@@ -51,6 +51,14 @@ export interface InstanceFormSectionProps {
|
|
|
51
51
|
readonly onDataSourceStateChange: (fieldKey: string, state: Pick<FormDataSourceFieldState, 'hasValue' | 'invalidValues' | 'status'>) => void;
|
|
52
52
|
/** Called when the user clicks "重新送出". */
|
|
53
53
|
readonly onResubmitInstance: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* The applicant's comment for the resubmission. The comment box shows only
|
|
56
|
+
* when the case can be resubmitted (`canResubmitInstance`) and
|
|
57
|
+
* `onResubmitCommentChange` is given.
|
|
58
|
+
*/
|
|
59
|
+
readonly resubmitComment?: string;
|
|
60
|
+
/** Called when the applicant edits the resubmission comment. */
|
|
61
|
+
readonly onResubmitCommentChange?: ((value: string) => void) | null;
|
|
54
62
|
/** Called when an attachment upload is requested via the form field. */
|
|
55
63
|
readonly onUploadAttachment: (field: FormFieldDefinition, file: File) => Promise<{
|
|
56
64
|
readonly id: string;
|
|
@@ -61,4 +69,4 @@ export interface InstanceFormSectionProps {
|
|
|
61
69
|
* Displays the form in read-only mode normally, or editable mode when the
|
|
62
70
|
* instance has been returned and the current member can resubmit it.
|
|
63
71
|
*/
|
|
64
|
-
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, fieldAccess, fieldLabelMarkers, fill, instance, loading, onDataSourceStateChange, onResubmitFormChange, onReloadAfterConflict, onResubmitInstance, onUploadAttachment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
72
|
+
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, fieldAccess, fieldLabelMarkers, fill, instance, loading, onDataSourceStateChange, onResubmitFormChange, onReloadAfterConflict, onResubmitCommentChange, onResubmitInstance, onUploadAttachment, resubmitComment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
@@ -51,6 +51,14 @@ export interface InstanceFormSectionProps {
|
|
|
51
51
|
readonly onDataSourceStateChange: (fieldKey: string, state: Pick<FormDataSourceFieldState, 'hasValue' | 'invalidValues' | 'status'>) => void;
|
|
52
52
|
/** Called when the user clicks "重新送出". */
|
|
53
53
|
readonly onResubmitInstance: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* The applicant's comment for the resubmission. The comment box shows only
|
|
56
|
+
* when the case can be resubmitted (`canResubmitInstance`) and
|
|
57
|
+
* `onResubmitCommentChange` is given.
|
|
58
|
+
*/
|
|
59
|
+
readonly resubmitComment?: string;
|
|
60
|
+
/** Called when the applicant edits the resubmission comment. */
|
|
61
|
+
readonly onResubmitCommentChange?: ((value: string) => void) | null;
|
|
54
62
|
/** Called when an attachment upload is requested via the form field. */
|
|
55
63
|
readonly onUploadAttachment: (field: FormFieldDefinition, file: File) => Promise<{
|
|
56
64
|
readonly id: string;
|
|
@@ -61,4 +69,4 @@ export interface InstanceFormSectionProps {
|
|
|
61
69
|
* Displays the form in read-only mode normally, or editable mode when the
|
|
62
70
|
* instance has been returned and the current member can resubmit it.
|
|
63
71
|
*/
|
|
64
|
-
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, fieldAccess, fieldLabelMarkers, fill, instance, loading, onDataSourceStateChange, onResubmitFormChange, onReloadAfterConflict, onResubmitInstance, onUploadAttachment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
72
|
+
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, fieldAccess, fieldLabelMarkers, fill, instance, loading, onDataSourceStateChange, onResubmitFormChange, onReloadAfterConflict, onResubmitCommentChange, onResubmitInstance, onUploadAttachment, resubmitComment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ResubmitCommentDraft {
|
|
2
|
+
/** The applicant's unsent resubmission comment for the current case. */
|
|
3
|
+
readonly comment: string;
|
|
4
|
+
readonly setComment: (value: string) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Clears the draft after `submittedInstanceId` was resubmitted, unless the
|
|
7
|
+
* page has since moved to another case whose draft must stay.
|
|
8
|
+
*/
|
|
9
|
+
readonly clearAfterResubmit: (submittedInstanceId: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The resubmission comment draft of the case at `instanceId`. One draft is
|
|
13
|
+
* kept, stored with the case it was written for and read back only for that
|
|
14
|
+
* case: another case shows empty from its very first render, a refresh of the
|
|
15
|
+
* same case (an upload, a decision elsewhere) keeps it, and coming back to the
|
|
16
|
+
* case shows it again unless the applicant has typed on another case since.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useResubmitCommentDraft(instanceId: string): ResubmitCommentDraft;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ResubmitCommentDraft {
|
|
2
|
+
/** The applicant's unsent resubmission comment for the current case. */
|
|
3
|
+
readonly comment: string;
|
|
4
|
+
readonly setComment: (value: string) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Clears the draft after `submittedInstanceId` was resubmitted, unless the
|
|
7
|
+
* page has since moved to another case whose draft must stay.
|
|
8
|
+
*/
|
|
9
|
+
readonly clearAfterResubmit: (submittedInstanceId: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The resubmission comment draft of the case at `instanceId`. One draft is
|
|
13
|
+
* kept, stored with the case it was written for and read back only for that
|
|
14
|
+
* case: another case shows empty from its very first render, a refresh of the
|
|
15
|
+
* same case (an upload, a decision elsewhere) keeps it, and coming back to the
|
|
16
|
+
* case shows it again unless the applicant has typed on another case since.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useResubmitCommentDraft(instanceId: string): ResubmitCommentDraft;
|