@rytass/bpm-core-react 0.21.0 → 0.21.1
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 +46 -0
- package/dist/chunks/{FormBuilderView-WtC2iW5f.js → FormBuilderView-6KdApi-D.js} +8 -8
- package/dist/chunks/{FormBuilderView-WtC2iW5f.js.map → FormBuilderView-6KdApi-D.js.map} +1 -1
- package/dist/chunks/{FormBuilderView-DjPGrOJ2.cjs → FormBuilderView-CGKkuVFi.cjs} +3 -3
- package/dist/chunks/{FormBuilderView-DjPGrOJ2.cjs.map → FormBuilderView-CGKkuVFi.cjs.map} +1 -1
- package/dist/chunks/{approval-instance-list-page-Bth7Raya.js → approval-instance-list-page-BI5fIXc-.js} +26 -26
- package/dist/chunks/{approval-instance-list-page-Bth7Raya.js.map → approval-instance-list-page-BI5fIXc-.js.map} +1 -1
- package/dist/chunks/{approval-instance-list-page-Dcvo6TrT.cjs → approval-instance-list-page-Cv5I1YPX.cjs} +2 -2
- package/dist/chunks/{approval-instance-list-page-Dcvo6TrT.cjs.map → approval-instance-list-page-Cv5I1YPX.cjs.map} +1 -1
- package/dist/chunks/{compose-DZvIspW3.js → compose-DFuLPmOA.js} +4 -4
- package/dist/chunks/{compose-DZvIspW3.js.map → compose-DFuLPmOA.js.map} +1 -1
- package/dist/chunks/compose-DK3ocWwG.cjs +2 -0
- package/dist/chunks/compose-DK3ocWwG.cjs.map +1 -0
- package/dist/chunks/designer-CAUWEKJ4.cjs +69 -0
- package/dist/chunks/designer-CAUWEKJ4.cjs.map +1 -0
- package/dist/chunks/{designer-CWubIE69.js → designer-CCy5EbOe.js} +2189 -1608
- package/dist/chunks/designer-CCy5EbOe.js.map +1 -0
- package/dist/chunks/detail-C5KrUC7s.cjs +5 -0
- package/dist/chunks/detail-C5KrUC7s.cjs.map +1 -0
- package/dist/chunks/{detail-Bv90gvy0.js → detail-Dnc4PPWO.js} +768 -742
- package/dist/chunks/detail-Dnc4PPWO.js.map +1 -0
- package/dist/chunks/{instance-error-message-CAP1vJhX.js → instance-error-message-BEM4O_Kj.js} +6 -2
- package/dist/chunks/instance-error-message-BEM4O_Kj.js.map +1 -0
- package/dist/chunks/instance-error-message-BpCLCOjp.cjs +2 -0
- package/dist/chunks/instance-error-message-BpCLCOjp.cjs.map +1 -0
- package/dist/chunks/organization-time-zone-provider-B7CXQril.cjs +2 -0
- package/dist/chunks/organization-time-zone-provider-B7CXQril.cjs.map +1 -0
- package/dist/chunks/organization-time-zone-provider-DNL8yo4-.js +42 -0
- package/dist/chunks/organization-time-zone-provider-DNL8yo4-.js.map +1 -0
- package/dist/chunks/{providers-BbCs23sk.js → providers-CQWekD7_.js} +197 -196
- package/dist/chunks/providers-CQWekD7_.js.map +1 -0
- package/dist/chunks/providers-VUOh6i0i.cjs +2 -0
- package/dist/chunks/providers-VUOh6i0i.cjs.map +1 -0
- package/dist/components/notification-drawer-options.d.cts +18 -0
- package/dist/components/notification-drawer-options.d.ts +18 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +23 -23
- package/dist/index.js.map +1 -1
- package/dist/lib/organization-time-zone-provider.d.cts +20 -0
- package/dist/lib/organization-time-zone-provider.d.ts +20 -0
- package/dist/lib/organization-time-zone.d.cts +8 -0
- package/dist/lib/organization-time-zone.d.ts +8 -0
- package/dist/lib/providers.d.cts +10 -1
- package/dist/lib/providers.d.ts +10 -1
- package/dist/next/BPMNextProviders.d.cts +8 -1
- package/dist/next/BPMNextProviders.d.ts +8 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.js +12 -11
- package/dist/next/index.js.map +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/cc/index.cjs +1 -1
- package/dist/views/cc/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/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/shared.d.cts +0 -1
- package/dist/views/instances/detail/sections/shared.d.ts +0 -1
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.js +1 -1
- package/dist/views/search/index.cjs +1 -1
- package/dist/views/search/index.js +1 -1
- package/dist/views/sent/index.cjs +1 -1
- package/dist/views/sent/index.js +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/approver-resolver-model.d.cts +105 -1
- package/dist/views/templates/designer/approver-resolver-model.d.ts +105 -1
- package/dist/views/templates/designer/dynamic-form-resolver-options.d.cts +5 -0
- package/dist/views/templates/designer/dynamic-form-resolver-options.d.ts +5 -0
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/dist/views/templates/designer/node-actor-resolver-options.d.cts +44 -1
- package/dist/views/templates/designer/node-actor-resolver-options.d.ts +44 -1
- package/dist/views/templates/designer/notify-recipient-options.d.cts +81 -0
- package/dist/views/templates/designer/notify-recipient-options.d.ts +81 -0
- package/dist/views/templates/designer/position-level-options.d.cts +3 -1
- package/dist/views/templates/designer/position-level-options.d.ts +3 -1
- package/dist/views/templates/designer/position-scope.d.cts +51 -0
- package/dist/views/templates/designer/position-scope.d.ts +51 -0
- package/package.json +3 -3
- package/dist/chunks/compose-BKUTsB2W.cjs +0 -2
- package/dist/chunks/compose-BKUTsB2W.cjs.map +0 -1
- package/dist/chunks/designer-CWubIE69.js.map +0 -1
- package/dist/chunks/designer-C_m8DmMl.cjs +0 -69
- package/dist/chunks/designer-C_m8DmMl.cjs.map +0 -1
- package/dist/chunks/detail-Bv90gvy0.js.map +0 -1
- package/dist/chunks/detail-DNzqesdI.cjs +0 -5
- package/dist/chunks/detail-DNzqesdI.cjs.map +0 -1
- package/dist/chunks/instance-error-message-BW464LRQ.cjs +0 -2
- package/dist/chunks/instance-error-message-BW464LRQ.cjs.map +0 -1
- package/dist/chunks/instance-error-message-CAP1vJhX.js.map +0 -1
- package/dist/chunks/language-provider-Bdnx3Gxl.cjs +0 -2
- package/dist/chunks/language-provider-Bdnx3Gxl.cjs.map +0 -1
- package/dist/chunks/language-provider-phkWOapf.js +0 -17
- package/dist/chunks/language-provider-phkWOapf.js.map +0 -1
- package/dist/chunks/providers-BbCs23sk.js.map +0 -1
- package/dist/chunks/providers-D_KAgOOu.cjs +0 -2
- package/dist/chunks/providers-D_KAgOOu.cjs.map +0 -1
|
@@ -7,10 +7,10 @@ import { DateRangePicker as s, DateTimeRangePicker as te, Filter as c, FilterAre
|
|
|
7
7
|
import { resolveMembers as ce } from "@rytass/bpm-core-client";
|
|
8
8
|
import { Fragment as le, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
9
9
|
import { listApprovalInstancesPage as ue, readApprovalInstanceCaseTitle as de, readApprovalTemplateCurrentFormSchema as fe } from "@rytass/bpm-core-client/workflow";
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
10
|
+
import { APPROVAL_INSTANCE_SORT_TIME_FIELDS as g, isFilterableFieldSortable as pe, readFilterableFieldPaths as me } from "@rytass/bpm-core-shared";
|
|
11
|
+
import { ControlFieldSlotLayout as _, FormFieldLayout as v } from "@mezzanine-ui/core/form";
|
|
12
|
+
import he from "@mezzanine-ui/react/ContentHeader";
|
|
13
|
+
import { listApprovalTemplates as ge } from "@rytass/bpm-core-client/template";
|
|
14
14
|
import { formatDatePickerValue as y, formatDateTimePickerValue as b } from "@rytass/bpm-core-client/form";
|
|
15
15
|
import '../approval-instance-list-page.css';// src/components/approval-instance-field-filters.ts
|
|
16
16
|
function x(e) {
|
|
@@ -114,10 +114,10 @@ var O = {
|
|
|
114
114
|
updatedAt: "最後更新"
|
|
115
115
|
};
|
|
116
116
|
function ye(e, t) {
|
|
117
|
-
let n =
|
|
117
|
+
let n = g.map((e) => ({
|
|
118
118
|
id: e,
|
|
119
119
|
label: k[e]
|
|
120
|
-
})), r = t ? e.filter(
|
|
120
|
+
})), r = t ? e.filter(pe).map((e) => ({
|
|
121
121
|
id: e.path,
|
|
122
122
|
label: e.label
|
|
123
123
|
})) : [];
|
|
@@ -128,7 +128,7 @@ function ye(e, t) {
|
|
|
128
128
|
];
|
|
129
129
|
}
|
|
130
130
|
function be(e, t, n) {
|
|
131
|
-
return e === "" ||
|
|
131
|
+
return e === "" || g.includes(e) ? !0 : n && t.some((t) => t.path === e);
|
|
132
132
|
}
|
|
133
133
|
function xe(e) {
|
|
134
134
|
return e.field === "" ? void 0 : [{
|
|
@@ -182,8 +182,8 @@ function j(e, t, n, r) {
|
|
|
182
182
|
children: /* @__PURE__ */ m(u, {
|
|
183
183
|
fullWidth: !0,
|
|
184
184
|
hintText: r,
|
|
185
|
-
controlFieldSlotLayout:
|
|
186
|
-
layout:
|
|
185
|
+
controlFieldSlotLayout: _.SUB,
|
|
186
|
+
layout: v.VERTICAL,
|
|
187
187
|
label: t,
|
|
188
188
|
name: `fieldFilter-${e}`,
|
|
189
189
|
children: n
|
|
@@ -340,8 +340,8 @@ var Ce = { instanceFilterArea: "bpm_instanceFilterArea_qpvJq" }, we = [
|
|
|
340
340
|
id: "ASC",
|
|
341
341
|
name: "舊到新"
|
|
342
342
|
}];
|
|
343
|
-
function I({ defaultState: s, description: te, emptyMessage: de, searchPlaceholder:
|
|
344
|
-
let b = e(), x = t(), [S, C] = o(null), [w, T] = o(/* @__PURE__ */ new Map()), [E, D] = o(1), [k, A] = o(10), [j, M] = o(0), [N, P] = o(!0), [I, R] = o([]), [z, Fe] = o(""), [B, Ie] = o(L(s)), [Le, Re] = o([]), [V, ze] = o(null), [H, U] = o(null), [Be, W] = o(!1), [G, K] = o(null), [q, J] = o({}), [Y, X] = o(O), Z = ee(0), Q = a(() => H ?
|
|
343
|
+
function I({ defaultState: s, description: te, emptyMessage: de, searchPlaceholder: g, title: pe, view: y }) {
|
|
344
|
+
let b = e(), x = t(), [S, C] = o(null), [w, T] = o(/* @__PURE__ */ new Map()), [E, D] = o(1), [k, A] = o(10), [j, M] = o(0), [N, P] = o(!0), [I, R] = o([]), [z, Fe] = o(""), [B, Ie] = o(L(s)), [Le, Re] = o([]), [V, ze] = o(null), [H, U] = o(null), [Be, W] = o(!1), [G, K] = o(null), [q, J] = o({}), [Y, X] = o(O), Z = ee(0), Q = a(() => H ? me(H) : [], [H]), Ve = a(() => V === null ? void 0 : _e(Q, q), [
|
|
345
345
|
q,
|
|
346
346
|
Q,
|
|
347
347
|
V
|
|
@@ -382,7 +382,7 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
382
382
|
let e = !1;
|
|
383
383
|
return (async () => {
|
|
384
384
|
try {
|
|
385
|
-
let t = await
|
|
385
|
+
let t = await ge();
|
|
386
386
|
e || Re(t);
|
|
387
387
|
} catch {
|
|
388
388
|
e || Re([]);
|
|
@@ -512,15 +512,15 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
512
512
|
span: 2,
|
|
513
513
|
children: /* @__PURE__ */ m(u, {
|
|
514
514
|
fullWidth: !0,
|
|
515
|
-
controlFieldSlotLayout:
|
|
516
|
-
layout:
|
|
515
|
+
controlFieldSlotLayout: _.SUB,
|
|
516
|
+
layout: v.VERTICAL,
|
|
517
517
|
name: "instanceSearchText",
|
|
518
518
|
children: /* @__PURE__ */ m(d, {
|
|
519
519
|
fullWidth: !0,
|
|
520
520
|
onChange: (e) => {
|
|
521
521
|
Fe(e.target.value), D(1);
|
|
522
522
|
},
|
|
523
|
-
placeholder:
|
|
523
|
+
placeholder: g,
|
|
524
524
|
size: "sub",
|
|
525
525
|
value: z,
|
|
526
526
|
variant: "base"
|
|
@@ -531,8 +531,8 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
531
531
|
span: 2,
|
|
532
532
|
children: /* @__PURE__ */ m(u, {
|
|
533
533
|
fullWidth: !0,
|
|
534
|
-
controlFieldSlotLayout:
|
|
535
|
-
layout:
|
|
534
|
+
controlFieldSlotLayout: _.SUB,
|
|
535
|
+
layout: v.VERTICAL,
|
|
536
536
|
name: "instanceState",
|
|
537
537
|
children: /* @__PURE__ */ m(f, {
|
|
538
538
|
clearable: !1,
|
|
@@ -552,8 +552,8 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
552
552
|
span: 2,
|
|
553
553
|
children: /* @__PURE__ */ m(u, {
|
|
554
554
|
fullWidth: !0,
|
|
555
|
-
controlFieldSlotLayout:
|
|
556
|
-
layout:
|
|
555
|
+
controlFieldSlotLayout: _.SUB,
|
|
556
|
+
layout: v.VERTICAL,
|
|
557
557
|
label: "範本",
|
|
558
558
|
name: "instanceTemplate",
|
|
559
559
|
children: /* @__PURE__ */ m(f, {
|
|
@@ -571,8 +571,8 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
571
571
|
span: 2,
|
|
572
572
|
children: /* @__PURE__ */ m(u, {
|
|
573
573
|
fullWidth: !0,
|
|
574
|
-
controlFieldSlotLayout:
|
|
575
|
-
layout:
|
|
574
|
+
controlFieldSlotLayout: _.SUB,
|
|
575
|
+
layout: v.VERTICAL,
|
|
576
576
|
label: "排序欄位",
|
|
577
577
|
name: "instanceSortField",
|
|
578
578
|
children: /* @__PURE__ */ m(f, {
|
|
@@ -594,8 +594,8 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
594
594
|
span: 2,
|
|
595
595
|
children: /* @__PURE__ */ m(u, {
|
|
596
596
|
fullWidth: !0,
|
|
597
|
-
controlFieldSlotLayout:
|
|
598
|
-
layout:
|
|
597
|
+
controlFieldSlotLayout: _.SUB,
|
|
598
|
+
layout: v.VERTICAL,
|
|
599
599
|
label: "排序方向",
|
|
600
600
|
name: "instanceSortDirection",
|
|
601
601
|
children: /* @__PURE__ */ m(ie, {
|
|
@@ -613,9 +613,9 @@ function I({ defaultState: s, description: te, emptyMessage: de, searchPlacehold
|
|
|
613
613
|
})
|
|
614
614
|
})
|
|
615
615
|
})] }, "sort");
|
|
616
|
-
return /* @__PURE__ */ h(le, { children: [/* @__PURE__ */ m(re, { children: /* @__PURE__ */ m(
|
|
616
|
+
return /* @__PURE__ */ h(le, { children: [/* @__PURE__ */ m(re, { children: /* @__PURE__ */ m(he, {
|
|
617
617
|
description: te,
|
|
618
|
-
title:
|
|
618
|
+
title: pe
|
|
619
619
|
}) }), /* @__PURE__ */ m(oe, { children: /* @__PURE__ */ h(ae, {
|
|
620
620
|
filterArea: /* @__PURE__ */ m(ne, {
|
|
621
621
|
className: Ce.instanceFilterArea,
|
|
@@ -721,4 +721,4 @@ function Pe(e) {
|
|
|
721
721
|
}
|
|
722
722
|
export { I as t };
|
|
723
723
|
|
|
724
|
-
//# sourceMappingURL=approval-instance-list-page-
|
|
724
|
+
//# sourceMappingURL=approval-instance-list-page-BI5fIXc-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-instance-list-page-Bth7Raya.js","names":["_Fragment","styles","useRouterAdapter","useBPMRoutes","formatDateTime","Fragment$1","ContentHeader","readFieldFilterControl","item","EMPTY_FIELD_FILTER_DRAFT","DECIMAL_PATTERN","isDecimalText","readDecimal","value","plain","readIdList","text","toApprovalInstanceFieldFilter","draft","ids","from","to","buildApprovalInstanceFieldFilters","paths","filter","drafts","DEFAULT_SORT_DRAFT","DEFAULT_SORT_OPTION","SORT_TIME_LABELS","readSortFieldOptions","timeOptions","APPROVAL_INSTANCE_SORT_TIME_FIELDS","field","fieldOptions","templateSelected","isFilterableFieldSortable","isSortFieldAvailable","toApprovalInstanceSort","BOOLEAN_CHOICES","readFieldFilterElements","change","next","control","renderFilter","Input","event","readNumberHint","renderControl","readIdNoun","Filter","FormField","ControlFieldSlotLayout","FormFieldLayout","key","choices","option","Select","selected","label","choice","DateRangePicker","formatDatePickerValue","target","DateTimeRangePicker","formatDateTimePickerValue","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","FIELD_FILTERS_PER_LINE","STATE_FILTER_OPTIONS","SORT_DIRECTION_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","useState","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","templates","setTemplates","templateId","setTemplateId","templateSchema","setTemplateSchema","schemaLoading","setSchemaLoading","schemaError","setSchemaError","fieldDrafts","setFieldDrafts","sortDraft","setSortDraft","refreshRequestIdRef","useRef","fieldPaths","useMemo","readFilterableFieldPaths","fieldFilters","sort","sortOptions","refreshInstances","useCallback","requestId","result","listApprovalInstancesPage","readApprovalInstanceRow","requestError","readErrorMessage","view","useEffect","cancelled","loaded","listApprovalTemplates","schema","readApprovalTemplateCurrentFormSchema","schemaLoadError","initiatorMemberIds","row","profiles","resolveMembers","profile","handleTemplateChange","previous","handleFilterReset","handleFilterSubmit","handleFieldDraftChange","path","columns","Typography","readInstanceStateColor","record","readInitiatorLabel","tableActions","templateOptions","template","selectedTemplate","fieldFilterLines","chunkElements","FilterLine","elements","index","sortFieldChoices","selectedSortField","searchFilterLine","searchPlaceholder","readSelectedStateFilterOption","readStateFilterLabel","sortFilterLine","RadioGroup","readSortDirection","PageHeader","SectionGroup","Section","FilterArea","emptyMessage","Table","page","pageSize","total","items","last","lines","size","instance","readApprovalInstanceCaseTitle","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-field-filters.ts","../../src/components/approval-instance-field-filter-controls.tsx","../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":["import {\n APPROVAL_INSTANCE_SORT_TIME_FIELDS,\n isFilterableFieldSortable,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormFieldOption,\n} from '@rytass/bpm-core-shared';\n\n/**\n * Pure logic behind the list page's field filters (ADR 25 §7). Turns the\n * filterable fields of a template's schema into controls, and the control\n * values into `fieldFilters` and `sort` for `listApprovalInstancesPage`. The\n * operator for each control is one `readFilterOperatorsForFieldType` allows.\n */\n\n/** Which control a filterable field gets on the list page. */\nexport type FieldFilterControl =\n /** Text, textarea and dynamic (data-source) options: CONTAINS on a text input. */\n | { readonly kind: 'contains' }\n /** Static options: IN on a multi-select. */\n | { readonly kind: 'option-in'; readonly options: readonly FormFieldOption[] }\n /** Member and org unit: IN on comma-separated ids (no picker yet). */\n | { readonly kind: 'id-in' }\n /** Number and money: RANGE with two number inputs. */\n | { readonly kind: 'number-range' }\n /** Date: RANGE with a date range picker. */\n | { readonly kind: 'date-range' }\n /** Datetime: RANGE with a datetime range picker. */\n | { readonly kind: 'datetime-range' }\n /** Boolean: EQUALS with a yes / no select. */\n | { readonly kind: 'boolean' };\n\nexport function readFieldFilterControl(\n item: FilterableFieldPath,\n): FieldFilterControl {\n switch (item.kind) {\n case 'number':\n return { kind: 'number-range' };\n case 'date':\n return { kind: 'date-range' };\n case 'datetime':\n return { kind: 'datetime-range' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'member':\n case 'org_unit':\n return { kind: 'id-in' };\n case 'option':\n return item.staticOptions\n ? { kind: 'option-in', options: item.staticOptions }\n : { kind: 'contains' };\n case 'text':\n return { kind: 'contains' };\n }\n}\n\n/**\n * One field's entered condition. `from` and `to` hold canonical values\n * (decimal string, `YYYY-MM-DD`, or ISO 8601) as the controls produce them.\n */\nexport interface FieldFilterDraft {\n readonly from: string;\n readonly to: string;\n /** CONTAINS text, or comma-separated ids for IN on member and org unit. */\n readonly text: string;\n /** Selected option values (IN), or `['true']` / `['false']` for boolean. */\n readonly values: readonly string[];\n}\n\nexport const EMPTY_FIELD_FILTER_DRAFT: FieldFilterDraft = {\n from: '',\n text: '',\n to: '',\n values: [],\n};\n\n/** Drafts keyed by the field path, so a path can be looked up directly. */\nexport type FieldFilterDrafts = Readonly<Record<string, FieldFilterDraft>>;\n\nconst DECIMAL_PATTERN = /^-?\\d+(\\.\\d+)?$/u;\n\n/**\n * Whether a number control's text is a decimal. Surrounding spaces and\n * thousands separators (`1,000`) are accepted and dropped before sending.\n */\nexport function isDecimalText(value: string): boolean {\n return readDecimal(value) !== null;\n}\n\nfunction readDecimal(value: string): string | null {\n const plain = value.trim().replace(/,/gu, '');\n\n return DECIMAL_PATTERN.test(plain) ? plain : null;\n}\n\nfunction readIdList(text: string): readonly string[] {\n return text\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\n/**\n * The condition one draft asks for, or `null` when it is empty. Empty means\n * no condition, so it must not reach the server as a filter.\n */\nexport function toApprovalInstanceFieldFilter(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n): ApprovalInstanceFieldFilter | null {\n const control = readFieldFilterControl(item);\n\n switch (control.kind) {\n case 'contains': {\n const text = draft.text.trim();\n\n return text\n ? { fieldKey: item.path, operator: 'CONTAINS', values: [text] }\n : null;\n }\n case 'option-in':\n return draft.values.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: [...draft.values] }\n : null;\n case 'id-in': {\n const ids = readIdList(draft.text);\n\n return ids.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: ids }\n : null;\n }\n case 'number-range': {\n const from = readDecimal(draft.from);\n const to = readDecimal(draft.to);\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'date-range':\n case 'datetime-range': {\n const from = draft.from.trim();\n const to = draft.to.trim();\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'boolean': {\n const value = draft.values[0];\n\n return value === 'true' || value === 'false'\n ? { fieldKey: item.path, operator: 'EQUALS', values: [value] }\n : null;\n }\n }\n}\n\n/** Every non-empty condition, in schema order. */\nexport function buildApprovalInstanceFieldFilters(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n): readonly ApprovalInstanceFieldFilter[] {\n return paths.flatMap((item): readonly ApprovalInstanceFieldFilter[] => {\n const filter = toApprovalInstanceFieldFilter(\n item,\n drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT,\n );\n\n return filter ? [filter] : [];\n });\n}\n\n/** The sort the user picked. An empty `field` keeps the server default. */\nexport interface SortDraft {\n readonly direction: ApprovalInstanceSortDirection;\n readonly field: string;\n}\n\nexport const DEFAULT_SORT_DRAFT: SortDraft = { direction: 'DESC', field: '' };\n\nexport interface SortFieldOption {\n readonly id: string;\n readonly label: string;\n}\n\nexport const DEFAULT_SORT_OPTION: SortFieldOption = {\n id: '',\n label: '預設(建立時間,新到舊)',\n};\n\nconst SORT_TIME_LABELS: Readonly<\n Record<(typeof APPROVAL_INSTANCE_SORT_TIME_FIELDS)[number], string>\n> = {\n completedAt: '完成時間',\n submittedAt: '送出時間',\n updatedAt: '最後更新',\n};\n\n/**\n * Sort choices. Time fields are always offered. Form fields are offered only\n * with a template selected, because the server needs a template to sort by a\n * form field.\n */\nexport function readSortFieldOptions(\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): readonly SortFieldOption[] {\n const timeOptions = APPROVAL_INSTANCE_SORT_TIME_FIELDS.map(\n (field): SortFieldOption => ({ id: field, label: SORT_TIME_LABELS[field] }),\n );\n const fieldOptions = templateSelected\n ? paths\n .filter(isFilterableFieldSortable)\n .map((item): SortFieldOption => ({ id: item.path, label: item.label }))\n : [];\n\n return [DEFAULT_SORT_OPTION, ...timeOptions, ...fieldOptions];\n}\n\n/** Whether a sort on `field` is valid for the current template selection. */\nexport function isSortFieldAvailable(\n field: string,\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): boolean {\n if (field === '') {\n return true;\n }\n\n if (\n (APPROVAL_INSTANCE_SORT_TIME_FIELDS as readonly string[]).includes(field)\n ) {\n return true;\n }\n\n return templateSelected && paths.some((item) => item.path === field);\n}\n\nexport function toApprovalInstanceSort(\n draft: SortDraft,\n): readonly ApprovalInstanceSort[] | undefined {\n return draft.field === ''\n ? undefined\n : [{ direction: draft.direction, field: draft.field }];\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n DateRangePicker,\n DateTimeRangePicker,\n Filter,\n FormField,\n Input,\n Select,\n type FilterProps,\n} from '@mezzanine-ui/react';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport {\n formatDatePickerValue,\n formatDateTimePickerValue,\n} from '@rytass/bpm-core-client/form';\nimport type { FilterableFieldPath } from '@rytass/bpm-core-shared';\nimport {\n EMPTY_FIELD_FILTER_DRAFT,\n isDecimalText,\n readFieldFilterControl,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n} from './approval-instance-field-filters';\n\nexport type FieldFilterDraftChange = (\n path: string,\n draft: FieldFilterDraft,\n) => void;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst BOOLEAN_CHOICES: readonly SelectChoice[] = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\n/**\n * One list-page `Filter` per condition the template's filterable fields need.\n * A number field yields two (lower and upper bound) because Mezzanine has no\n * number range control. Returned as elements so the caller can place them\n * directly inside `FilterLine`, which only accepts `Filter` children.\n */\nexport function readFieldFilterElements(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n onDraftChange: FieldFilterDraftChange,\n): readonly ReactElement<FilterProps>[] {\n return paths.flatMap((item): readonly ReactElement<FilterProps>[] => {\n const draft = drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT;\n const change = (next: FieldFilterDraft): void => {\n onDraftChange(item.path, next);\n };\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'number-range') {\n return [\n renderFilter(\n `${item.path}:from`,\n `${item.label}(下限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, from: event.target.value });\n }}\n placeholder={`${item.label}:下限`}\n size=\"sub\"\n value={draft.from}\n variant=\"base\"\n />,\n readNumberHint(draft.from),\n ),\n renderFilter(\n `${item.path}:to`,\n `${item.label}(上限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, to: event.target.value });\n }}\n placeholder={`${item.label}:上限`}\n size=\"sub\"\n value={draft.to}\n variant=\"base\"\n />,\n readNumberHint(draft.to),\n ),\n ];\n }\n\n return [\n renderFilter(\n item.path,\n item.label,\n renderControl(item, draft, change, item.label),\n control.kind === 'id-in'\n ? `多個${readIdNoun(item)}以逗號分隔`\n : undefined,\n ),\n ];\n });\n}\n\nfunction renderFilter(\n key: string,\n label: string,\n control: ReactElement,\n hintText?: string,\n): ReactElement<FilterProps> {\n return (\n <Filter key={key} span={2}>\n <FormField\n fullWidth\n hintText={hintText}\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label={label}\n name={`fieldFilter-${key}`}\n >\n {control}\n </FormField>\n </Filter>\n );\n}\n\n/** What an id-in field holds: members, or org units for an `org_unit` field. */\nfunction readIdNoun(item: FilterableFieldPath): string {\n return item.kind === 'org_unit' ? '組織' : '成員';\n}\n\nfunction readNumberHint(value: string): string | undefined {\n return !value || isDecimalText(value) ? undefined : '請輸入數字';\n}\n\nfunction renderControl(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n change: (next: FieldFilterDraft) => void,\n label: string,\n): ReactElement {\n // The list page hides FormField labels to keep its filter rows compact, so\n // each control names its field in the placeholder, as the state filter does.\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'option-in') {\n const choices = control.options.map((option): SelectChoice => ({\n id: option.value,\n name: option.label,\n }));\n\n return (\n <Select\n clearable\n fullWidth\n mode=\"multiple\"\n onChange={(selected: readonly SelectChoice[]): void => {\n change({ ...draft, values: selected.map((option) => option.id) });\n }}\n options={[...choices]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={choices.filter((choice) => draft.values.includes(choice.id))}\n />\n );\n }\n\n if (control.kind === 'boolean') {\n const selected = BOOLEAN_CHOICES.find((choice) =>\n draft.values.includes(choice.id),\n );\n\n return (\n <Select\n clearable\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n change({ ...draft, values: option ? [option.id] : [] });\n }}\n options={[...BOOLEAN_CHOICES]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={selected ?? null}\n />\n );\n }\n\n if (control.kind === 'date-range') {\n return (\n <DateRangePicker\n clearable\n fullWidth\n inputFromPlaceholder={`${label}:起`}\n inputToPlaceholder=\"迄\"\n onChange={(target?: readonly (string | undefined)[]): void => {\n change({\n ...draft,\n from: formatDatePickerValue(target?.[0]) ?? '',\n to: formatDatePickerValue(target?.[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={draft.from && draft.to ? [draft.from, draft.to] : []}\n />\n );\n }\n\n if (control.kind === 'datetime-range') {\n return (\n <DateTimeRangePicker\n clearable\n fullWidth\n onChange={(value): void => {\n change({\n ...draft,\n from: formatDateTimePickerValue(value[0]) ?? '',\n to: formatDateTimePickerValue(value[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={[draft.from || undefined, draft.to || undefined]}\n />\n );\n }\n\n if (control.kind === 'id-in') {\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:${readIdNoun(item)} ID`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n }\n\n // contains (text, textarea and data-source options)\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:包含`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n}\n",".instanceFilterArea {\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n RadioGroup,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n type FilterLineProps,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalTemplates,\n type ApprovalTemplateRecord,\n} from '@rytass/bpm-core-client/template';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n readApprovalTemplateCurrentFormSchema,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readFilterableFieldPaths,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormDefinitionSchema,\n} from '@rytass/bpm-core-shared';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport {\n buildApprovalInstanceFieldFilters,\n DEFAULT_SORT_DRAFT,\n DEFAULT_SORT_OPTION,\n isSortFieldAvailable,\n readSortFieldOptions,\n toApprovalInstanceSort,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n type SortDraft,\n type SortFieldOption,\n} from './approval-instance-field-filters';\nimport { readFieldFilterElements } from './approval-instance-field-filter-controls';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst FIELD_FILTERS_PER_LINE = 3;\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\nconst SORT_DIRECTION_OPTIONS: readonly (SelectChoice & {\n id: ApprovalInstanceSortDirection;\n})[] = [\n { id: 'DESC', name: '新到舊' },\n { id: 'ASC', name: '舊到新' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n *\n * With a template selected, the filter bar also carries one control per\n * filterable field of that template's current form (ADR 25 §7), and the sort\n * may use those fields. Without a template only time fields can sort.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [templateId, setTemplateId] = useState<string | null>(null);\n const [templateSchema, setTemplateSchema] =\n useState<FormDefinitionSchema | null>(null);\n const [schemaLoading, setSchemaLoading] = useState(false);\n const [schemaError, setSchemaError] = useState<string | null>(null);\n const [fieldDrafts, setFieldDrafts] = useState<FieldFilterDrafts>({});\n const [sortDraft, setSortDraft] = useState<SortDraft>(DEFAULT_SORT_DRAFT);\n const refreshRequestIdRef = useRef(0);\n\n const fieldPaths = useMemo(\n (): readonly FilterableFieldPath[] =>\n templateSchema ? readFilterableFieldPaths(templateSchema) : [],\n [templateSchema],\n );\n const fieldFilters = useMemo(\n (): readonly ApprovalInstanceFieldFilter[] | undefined =>\n templateId === null\n ? undefined\n : buildApprovalInstanceFieldFilters(fieldPaths, fieldDrafts),\n [fieldDrafts, fieldPaths, templateId],\n );\n const sort = useMemo(\n (): readonly ApprovalInstanceSort[] | undefined =>\n toApprovalInstanceSort(sortDraft),\n [sortDraft],\n );\n const sortOptions = useMemo(\n (): readonly SortFieldOption[] =>\n readSortFieldOptions(fieldPaths, templateId !== null),\n [fieldPaths, templateId],\n );\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n fieldFilters,\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n sort,\n state: stateFilter.state,\n templateId,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [\n fieldFilters,\n instancePage,\n instancePageSize,\n searchText,\n sort,\n stateFilter,\n templateId,\n view,\n ]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const loaded = await listApprovalTemplates();\n\n if (!cancelled) {\n setTemplates(loaded);\n }\n } catch {\n if (!cancelled) {\n setTemplates([]);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, []);\n\n // Race guard: a schema response for a previously picked template is dropped\n // when the template changes again (cleanup flips `cancelled`).\n useEffect((): (() => void) | void => {\n if (templateId === null) {\n setTemplateSchema(null);\n setSchemaLoading(false);\n setSchemaError(null);\n\n return;\n }\n\n let cancelled = false;\n setSchemaLoading(true);\n setSchemaError(null);\n\n void (async (): Promise<void> => {\n try {\n const schema = await readApprovalTemplateCurrentFormSchema(templateId);\n\n if (!cancelled) {\n setTemplateSchema(schema);\n }\n } catch (schemaLoadError: unknown) {\n if (!cancelled) {\n setTemplateSchema(null);\n setSchemaError(readErrorMessage(schemaLoadError));\n }\n } finally {\n if (!cancelled) {\n setSchemaLoading(false);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [templateId]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const handleTemplateChange = useCallback(\n (option: SelectChoice | null): void => {\n setTemplateId(option?.id ?? null);\n // Drop the previous template's fields at once, so nothing is built from\n // them while the new schema loads.\n setTemplateSchema(null);\n setFieldDrafts({});\n setInstancePage(1);\n // A form-field sort belongs to one template. Time-field sorts survive.\n setSortDraft((previous): SortDraft =>\n isSortFieldAvailable(previous.field, [], false)\n ? previous\n : { ...previous, field: DEFAULT_SORT_DRAFT.field },\n );\n },\n [],\n );\n\n const handleFilterReset = useCallback((): void => {\n setSearchText('');\n setStateFilter(readStateFilterOption(defaultState));\n setTemplateId(null);\n setTemplateSchema(null);\n setFieldDrafts({});\n setSortDraft(DEFAULT_SORT_DRAFT);\n setInstancePage(1);\n }, [defaultState]);\n const handleFilterSubmit = useCallback((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n const handleFieldDraftChange = useCallback(\n (path: string, draft: FieldFilterDraft): void => {\n setFieldDrafts((previous): FieldFilterDrafts => ({\n ...previous,\n [path]: draft,\n }));\n setInstancePage(1);\n },\n [],\n );\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n const templateOptions = useMemo(\n (): readonly SelectChoice[] =>\n templates.map((template) => ({ id: template.id, name: template.name })),\n [templates],\n );\n const selectedTemplate = templateOptions.find(\n (option) => option.id === templateId,\n );\n const fieldFilterLines = useMemo(\n (): readonly ReactElement<FilterLineProps>[] =>\n chunkElements(\n readFieldFilterElements(\n fieldPaths,\n fieldDrafts,\n handleFieldDraftChange,\n ),\n FIELD_FILTERS_PER_LINE,\n ).map((elements, index): ReactElement<FilterLineProps> => (\n <FilterLine key={`field-filter-line-${index}`}>\n {[...elements]}\n </FilterLine>\n )),\n [fieldDrafts, fieldPaths, handleFieldDraftChange],\n );\n const sortFieldChoices = useMemo(\n (): readonly SelectChoice[] =>\n sortOptions.map((option) => ({ id: option.id, name: option.label })),\n [sortOptions],\n );\n const selectedSortField =\n sortFieldChoices.find((option) => option.id === sortDraft.field) ??\n sortFieldChoices.find((option) => option.id === DEFAULT_SORT_OPTION.id);\n\n const searchFilterLine = (\n <FilterLine key=\"search\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"範本\"\n name=\"instanceTemplate\"\n >\n <Select\n clearable\n fullWidth\n onChange={handleTemplateChange}\n options={[...templateOptions]}\n placeholder=\"全部範本\"\n size=\"sub\"\n value={selectedTemplate ?? null}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n const sortFilterLine = (\n <FilterLine key=\"sort\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序欄位\"\n name=\"instanceSortField\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n field: option?.id ?? DEFAULT_SORT_DRAFT.field,\n }));\n setInstancePage(1);\n }}\n options={[...sortFieldChoices]}\n placeholder=\"排序欄位\"\n size=\"sub\"\n value={selectedSortField ?? null}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序方向\"\n name=\"instanceSortDirection\"\n >\n <RadioGroup\n name=\"instanceSortDirection\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n direction: readSortDirection(event.target.value),\n }));\n setInstancePage(1);\n }}\n options={[...SORT_DIRECTION_OPTIONS]}\n size=\"sub\"\n type=\"segment\"\n value={sortDraft.direction}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea\n className={styles.instanceFilterArea}\n onReset={handleFilterReset}\n onSubmit={handleFilterSubmit}\n resetText=\"清除條件\"\n rowAlign=\"end\"\n size=\"sub\"\n submitText=\"重新查詢\"\n >\n {[searchFilterLine, ...fieldFilterLines, sortFilterLine]}\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {schemaError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {schemaError}\n </Typography>\n ) : null}\n {templateId !== null &&\n !schemaLoading &&\n !schemaError &&\n templateSchema &&\n fieldPaths.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此範本沒有可篩選的欄位。\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction chunkElements<T>(\n items: readonly T[],\n size: number,\n): readonly (readonly T[])[] {\n return items.reduce<readonly (readonly T[])[]>(\n (lines, item): readonly (readonly T[])[] => {\n const last = lines[lines.length - 1];\n\n return last && last.length < size\n ? [...lines.slice(0, -1), [...last, item]]\n : [...lines, [item]];\n },\n [],\n );\n}\n\nfunction readSortDirection(value: string): ApprovalInstanceSortDirection {\n return value === 'ASC' ? 'ASC' : 'DESC';\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\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":"approval-instance-list-page-BI5fIXc-.js","names":["_Fragment","styles","useRouterAdapter","useBPMRoutes","formatDateTime","Fragment$1","ContentHeader","readFieldFilterControl","item","EMPTY_FIELD_FILTER_DRAFT","DECIMAL_PATTERN","isDecimalText","readDecimal","value","plain","readIdList","text","toApprovalInstanceFieldFilter","draft","ids","from","to","buildApprovalInstanceFieldFilters","paths","filter","drafts","DEFAULT_SORT_DRAFT","DEFAULT_SORT_OPTION","SORT_TIME_LABELS","readSortFieldOptions","timeOptions","APPROVAL_INSTANCE_SORT_TIME_FIELDS","field","fieldOptions","templateSelected","isFilterableFieldSortable","isSortFieldAvailable","toApprovalInstanceSort","BOOLEAN_CHOICES","readFieldFilterElements","change","next","control","renderFilter","Input","event","readNumberHint","renderControl","readIdNoun","Filter","FormField","ControlFieldSlotLayout","FormFieldLayout","key","choices","option","Select","selected","label","choice","DateRangePicker","formatDatePickerValue","target","DateTimeRangePicker","formatDateTimePickerValue","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","FIELD_FILTERS_PER_LINE","STATE_FILTER_OPTIONS","SORT_DIRECTION_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","useState","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","templates","setTemplates","templateId","setTemplateId","templateSchema","setTemplateSchema","schemaLoading","setSchemaLoading","schemaError","setSchemaError","fieldDrafts","setFieldDrafts","sortDraft","setSortDraft","refreshRequestIdRef","useRef","fieldPaths","useMemo","readFilterableFieldPaths","fieldFilters","sort","sortOptions","refreshInstances","useCallback","requestId","result","listApprovalInstancesPage","readApprovalInstanceRow","requestError","readErrorMessage","view","useEffect","cancelled","loaded","listApprovalTemplates","schema","readApprovalTemplateCurrentFormSchema","schemaLoadError","initiatorMemberIds","row","profiles","resolveMembers","profile","handleTemplateChange","previous","handleFilterReset","handleFilterSubmit","handleFieldDraftChange","path","columns","Typography","readInstanceStateColor","record","readInitiatorLabel","tableActions","templateOptions","template","selectedTemplate","fieldFilterLines","chunkElements","FilterLine","elements","index","sortFieldChoices","selectedSortField","searchFilterLine","searchPlaceholder","readSelectedStateFilterOption","readStateFilterLabel","sortFilterLine","RadioGroup","readSortDirection","PageHeader","SectionGroup","Section","FilterArea","emptyMessage","Table","page","pageSize","total","items","last","lines","size","instance","readApprovalInstanceCaseTitle","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-field-filters.ts","../../src/components/approval-instance-field-filter-controls.tsx","../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":["import {\n APPROVAL_INSTANCE_SORT_TIME_FIELDS,\n isFilterableFieldSortable,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormFieldOption,\n} from '@rytass/bpm-core-shared';\n\n/**\n * Pure logic behind the list page's field filters (ADR 25 §7). Turns the\n * filterable fields of a template's schema into controls, and the control\n * values into `fieldFilters` and `sort` for `listApprovalInstancesPage`. The\n * operator for each control is one `readFilterOperatorsForFieldType` allows.\n */\n\n/** Which control a filterable field gets on the list page. */\nexport type FieldFilterControl =\n /** Text, textarea and dynamic (data-source) options: CONTAINS on a text input. */\n | { readonly kind: 'contains' }\n /** Static options: IN on a multi-select. */\n | { readonly kind: 'option-in'; readonly options: readonly FormFieldOption[] }\n /** Member and org unit: IN on comma-separated ids (no picker yet). */\n | { readonly kind: 'id-in' }\n /** Number and money: RANGE with two number inputs. */\n | { readonly kind: 'number-range' }\n /** Date: RANGE with a date range picker. */\n | { readonly kind: 'date-range' }\n /** Datetime: RANGE with a datetime range picker. */\n | { readonly kind: 'datetime-range' }\n /** Boolean: EQUALS with a yes / no select. */\n | { readonly kind: 'boolean' };\n\nexport function readFieldFilterControl(\n item: FilterableFieldPath,\n): FieldFilterControl {\n switch (item.kind) {\n case 'number':\n return { kind: 'number-range' };\n case 'date':\n return { kind: 'date-range' };\n case 'datetime':\n return { kind: 'datetime-range' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'member':\n case 'org_unit':\n return { kind: 'id-in' };\n case 'option':\n return item.staticOptions\n ? { kind: 'option-in', options: item.staticOptions }\n : { kind: 'contains' };\n case 'text':\n return { kind: 'contains' };\n }\n}\n\n/**\n * One field's entered condition. `from` and `to` hold canonical values\n * (decimal string, `YYYY-MM-DD`, or ISO 8601) as the controls produce them.\n */\nexport interface FieldFilterDraft {\n readonly from: string;\n readonly to: string;\n /** CONTAINS text, or comma-separated ids for IN on member and org unit. */\n readonly text: string;\n /** Selected option values (IN), or `['true']` / `['false']` for boolean. */\n readonly values: readonly string[];\n}\n\nexport const EMPTY_FIELD_FILTER_DRAFT: FieldFilterDraft = {\n from: '',\n text: '',\n to: '',\n values: [],\n};\n\n/** Drafts keyed by the field path, so a path can be looked up directly. */\nexport type FieldFilterDrafts = Readonly<Record<string, FieldFilterDraft>>;\n\nconst DECIMAL_PATTERN = /^-?\\d+(\\.\\d+)?$/u;\n\n/**\n * Whether a number control's text is a decimal. Surrounding spaces and\n * thousands separators (`1,000`) are accepted and dropped before sending.\n */\nexport function isDecimalText(value: string): boolean {\n return readDecimal(value) !== null;\n}\n\nfunction readDecimal(value: string): string | null {\n const plain = value.trim().replace(/,/gu, '');\n\n return DECIMAL_PATTERN.test(plain) ? plain : null;\n}\n\nfunction readIdList(text: string): readonly string[] {\n return text\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\n/**\n * The condition one draft asks for, or `null` when it is empty. Empty means\n * no condition, so it must not reach the server as a filter.\n */\nexport function toApprovalInstanceFieldFilter(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n): ApprovalInstanceFieldFilter | null {\n const control = readFieldFilterControl(item);\n\n switch (control.kind) {\n case 'contains': {\n const text = draft.text.trim();\n\n return text\n ? { fieldKey: item.path, operator: 'CONTAINS', values: [text] }\n : null;\n }\n case 'option-in':\n return draft.values.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: [...draft.values] }\n : null;\n case 'id-in': {\n const ids = readIdList(draft.text);\n\n return ids.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: ids }\n : null;\n }\n case 'number-range': {\n const from = readDecimal(draft.from);\n const to = readDecimal(draft.to);\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'date-range':\n case 'datetime-range': {\n const from = draft.from.trim();\n const to = draft.to.trim();\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'boolean': {\n const value = draft.values[0];\n\n return value === 'true' || value === 'false'\n ? { fieldKey: item.path, operator: 'EQUALS', values: [value] }\n : null;\n }\n }\n}\n\n/** Every non-empty condition, in schema order. */\nexport function buildApprovalInstanceFieldFilters(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n): readonly ApprovalInstanceFieldFilter[] {\n return paths.flatMap((item): readonly ApprovalInstanceFieldFilter[] => {\n const filter = toApprovalInstanceFieldFilter(\n item,\n drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT,\n );\n\n return filter ? [filter] : [];\n });\n}\n\n/** The sort the user picked. An empty `field` keeps the server default. */\nexport interface SortDraft {\n readonly direction: ApprovalInstanceSortDirection;\n readonly field: string;\n}\n\nexport const DEFAULT_SORT_DRAFT: SortDraft = { direction: 'DESC', field: '' };\n\nexport interface SortFieldOption {\n readonly id: string;\n readonly label: string;\n}\n\nexport const DEFAULT_SORT_OPTION: SortFieldOption = {\n id: '',\n label: '預設(建立時間,新到舊)',\n};\n\nconst SORT_TIME_LABELS: Readonly<\n Record<(typeof APPROVAL_INSTANCE_SORT_TIME_FIELDS)[number], string>\n> = {\n completedAt: '完成時間',\n submittedAt: '送出時間',\n updatedAt: '最後更新',\n};\n\n/**\n * Sort choices. Time fields are always offered. Form fields are offered only\n * with a template selected, because the server needs a template to sort by a\n * form field.\n */\nexport function readSortFieldOptions(\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): readonly SortFieldOption[] {\n const timeOptions = APPROVAL_INSTANCE_SORT_TIME_FIELDS.map(\n (field): SortFieldOption => ({ id: field, label: SORT_TIME_LABELS[field] }),\n );\n const fieldOptions = templateSelected\n ? paths\n .filter(isFilterableFieldSortable)\n .map((item): SortFieldOption => ({ id: item.path, label: item.label }))\n : [];\n\n return [DEFAULT_SORT_OPTION, ...timeOptions, ...fieldOptions];\n}\n\n/** Whether a sort on `field` is valid for the current template selection. */\nexport function isSortFieldAvailable(\n field: string,\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): boolean {\n if (field === '') {\n return true;\n }\n\n if (\n (APPROVAL_INSTANCE_SORT_TIME_FIELDS as readonly string[]).includes(field)\n ) {\n return true;\n }\n\n return templateSelected && paths.some((item) => item.path === field);\n}\n\nexport function toApprovalInstanceSort(\n draft: SortDraft,\n): readonly ApprovalInstanceSort[] | undefined {\n return draft.field === ''\n ? undefined\n : [{ direction: draft.direction, field: draft.field }];\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n DateRangePicker,\n DateTimeRangePicker,\n Filter,\n FormField,\n Input,\n Select,\n type FilterProps,\n} from '@mezzanine-ui/react';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport {\n formatDatePickerValue,\n formatDateTimePickerValue,\n} from '@rytass/bpm-core-client/form';\nimport type { FilterableFieldPath } from '@rytass/bpm-core-shared';\nimport {\n EMPTY_FIELD_FILTER_DRAFT,\n isDecimalText,\n readFieldFilterControl,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n} from './approval-instance-field-filters';\n\nexport type FieldFilterDraftChange = (\n path: string,\n draft: FieldFilterDraft,\n) => void;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst BOOLEAN_CHOICES: readonly SelectChoice[] = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\n/**\n * One list-page `Filter` per condition the template's filterable fields need.\n * A number field yields two (lower and upper bound) because Mezzanine has no\n * number range control. Returned as elements so the caller can place them\n * directly inside `FilterLine`, which only accepts `Filter` children.\n */\nexport function readFieldFilterElements(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n onDraftChange: FieldFilterDraftChange,\n): readonly ReactElement<FilterProps>[] {\n return paths.flatMap((item): readonly ReactElement<FilterProps>[] => {\n const draft = drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT;\n const change = (next: FieldFilterDraft): void => {\n onDraftChange(item.path, next);\n };\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'number-range') {\n return [\n renderFilter(\n `${item.path}:from`,\n `${item.label}(下限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, from: event.target.value });\n }}\n placeholder={`${item.label}:下限`}\n size=\"sub\"\n value={draft.from}\n variant=\"base\"\n />,\n readNumberHint(draft.from),\n ),\n renderFilter(\n `${item.path}:to`,\n `${item.label}(上限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, to: event.target.value });\n }}\n placeholder={`${item.label}:上限`}\n size=\"sub\"\n value={draft.to}\n variant=\"base\"\n />,\n readNumberHint(draft.to),\n ),\n ];\n }\n\n return [\n renderFilter(\n item.path,\n item.label,\n renderControl(item, draft, change, item.label),\n control.kind === 'id-in'\n ? `多個${readIdNoun(item)}以逗號分隔`\n : undefined,\n ),\n ];\n });\n}\n\nfunction renderFilter(\n key: string,\n label: string,\n control: ReactElement,\n hintText?: string,\n): ReactElement<FilterProps> {\n return (\n <Filter key={key} span={2}>\n <FormField\n fullWidth\n hintText={hintText}\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label={label}\n name={`fieldFilter-${key}`}\n >\n {control}\n </FormField>\n </Filter>\n );\n}\n\n/** What an id-in field holds: members, or org units for an `org_unit` field. */\nfunction readIdNoun(item: FilterableFieldPath): string {\n return item.kind === 'org_unit' ? '組織' : '成員';\n}\n\nfunction readNumberHint(value: string): string | undefined {\n return !value || isDecimalText(value) ? undefined : '請輸入數字';\n}\n\nfunction renderControl(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n change: (next: FieldFilterDraft) => void,\n label: string,\n): ReactElement {\n // The list page hides FormField labels to keep its filter rows compact, so\n // each control names its field in the placeholder, as the state filter does.\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'option-in') {\n const choices = control.options.map((option): SelectChoice => ({\n id: option.value,\n name: option.label,\n }));\n\n return (\n <Select\n clearable\n fullWidth\n mode=\"multiple\"\n onChange={(selected: readonly SelectChoice[]): void => {\n change({ ...draft, values: selected.map((option) => option.id) });\n }}\n options={[...choices]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={choices.filter((choice) => draft.values.includes(choice.id))}\n />\n );\n }\n\n if (control.kind === 'boolean') {\n const selected = BOOLEAN_CHOICES.find((choice) =>\n draft.values.includes(choice.id),\n );\n\n return (\n <Select\n clearable\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n change({ ...draft, values: option ? [option.id] : [] });\n }}\n options={[...BOOLEAN_CHOICES]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={selected ?? null}\n />\n );\n }\n\n if (control.kind === 'date-range') {\n return (\n <DateRangePicker\n clearable\n fullWidth\n inputFromPlaceholder={`${label}:起`}\n inputToPlaceholder=\"迄\"\n onChange={(target?: readonly (string | undefined)[]): void => {\n change({\n ...draft,\n from: formatDatePickerValue(target?.[0]) ?? '',\n to: formatDatePickerValue(target?.[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={draft.from && draft.to ? [draft.from, draft.to] : []}\n />\n );\n }\n\n if (control.kind === 'datetime-range') {\n return (\n <DateTimeRangePicker\n clearable\n fullWidth\n onChange={(value): void => {\n change({\n ...draft,\n from: formatDateTimePickerValue(value[0]) ?? '',\n to: formatDateTimePickerValue(value[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={[draft.from || undefined, draft.to || undefined]}\n />\n );\n }\n\n if (control.kind === 'id-in') {\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:${readIdNoun(item)} ID`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n }\n\n // contains (text, textarea and data-source options)\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:包含`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n}\n",".instanceFilterArea {\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n RadioGroup,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n type FilterLineProps,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalTemplates,\n type ApprovalTemplateRecord,\n} from '@rytass/bpm-core-client/template';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n readApprovalTemplateCurrentFormSchema,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readFilterableFieldPaths,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormDefinitionSchema,\n} from '@rytass/bpm-core-shared';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport {\n buildApprovalInstanceFieldFilters,\n DEFAULT_SORT_DRAFT,\n DEFAULT_SORT_OPTION,\n isSortFieldAvailable,\n readSortFieldOptions,\n toApprovalInstanceSort,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n type SortDraft,\n type SortFieldOption,\n} from './approval-instance-field-filters';\nimport { readFieldFilterElements } from './approval-instance-field-filter-controls';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst FIELD_FILTERS_PER_LINE = 3;\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\nconst SORT_DIRECTION_OPTIONS: readonly (SelectChoice & {\n id: ApprovalInstanceSortDirection;\n})[] = [\n { id: 'DESC', name: '新到舊' },\n { id: 'ASC', name: '舊到新' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n *\n * With a template selected, the filter bar also carries one control per\n * filterable field of that template's current form (ADR 25 §7), and the sort\n * may use those fields. Without a template only time fields can sort.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [templateId, setTemplateId] = useState<string | null>(null);\n const [templateSchema, setTemplateSchema] =\n useState<FormDefinitionSchema | null>(null);\n const [schemaLoading, setSchemaLoading] = useState(false);\n const [schemaError, setSchemaError] = useState<string | null>(null);\n const [fieldDrafts, setFieldDrafts] = useState<FieldFilterDrafts>({});\n const [sortDraft, setSortDraft] = useState<SortDraft>(DEFAULT_SORT_DRAFT);\n const refreshRequestIdRef = useRef(0);\n\n const fieldPaths = useMemo(\n (): readonly FilterableFieldPath[] =>\n templateSchema ? readFilterableFieldPaths(templateSchema) : [],\n [templateSchema],\n );\n const fieldFilters = useMemo(\n (): readonly ApprovalInstanceFieldFilter[] | undefined =>\n templateId === null\n ? undefined\n : buildApprovalInstanceFieldFilters(fieldPaths, fieldDrafts),\n [fieldDrafts, fieldPaths, templateId],\n );\n const sort = useMemo(\n (): readonly ApprovalInstanceSort[] | undefined =>\n toApprovalInstanceSort(sortDraft),\n [sortDraft],\n );\n const sortOptions = useMemo(\n (): readonly SortFieldOption[] =>\n readSortFieldOptions(fieldPaths, templateId !== null),\n [fieldPaths, templateId],\n );\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n fieldFilters,\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n sort,\n state: stateFilter.state,\n templateId,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [\n fieldFilters,\n instancePage,\n instancePageSize,\n searchText,\n sort,\n stateFilter,\n templateId,\n view,\n ]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const loaded = await listApprovalTemplates();\n\n if (!cancelled) {\n setTemplates(loaded);\n }\n } catch {\n if (!cancelled) {\n setTemplates([]);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, []);\n\n // Race guard: a schema response for a previously picked template is dropped\n // when the template changes again (cleanup flips `cancelled`).\n useEffect((): (() => void) | void => {\n if (templateId === null) {\n setTemplateSchema(null);\n setSchemaLoading(false);\n setSchemaError(null);\n\n return;\n }\n\n let cancelled = false;\n setSchemaLoading(true);\n setSchemaError(null);\n\n void (async (): Promise<void> => {\n try {\n const schema = await readApprovalTemplateCurrentFormSchema(templateId);\n\n if (!cancelled) {\n setTemplateSchema(schema);\n }\n } catch (schemaLoadError: unknown) {\n if (!cancelled) {\n setTemplateSchema(null);\n setSchemaError(readErrorMessage(schemaLoadError));\n }\n } finally {\n if (!cancelled) {\n setSchemaLoading(false);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [templateId]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const handleTemplateChange = useCallback(\n (option: SelectChoice | null): void => {\n setTemplateId(option?.id ?? null);\n // Drop the previous template's fields at once, so nothing is built from\n // them while the new schema loads.\n setTemplateSchema(null);\n setFieldDrafts({});\n setInstancePage(1);\n // A form-field sort belongs to one template. Time-field sorts survive.\n setSortDraft((previous): SortDraft =>\n isSortFieldAvailable(previous.field, [], false)\n ? previous\n : { ...previous, field: DEFAULT_SORT_DRAFT.field },\n );\n },\n [],\n );\n\n const handleFilterReset = useCallback((): void => {\n setSearchText('');\n setStateFilter(readStateFilterOption(defaultState));\n setTemplateId(null);\n setTemplateSchema(null);\n setFieldDrafts({});\n setSortDraft(DEFAULT_SORT_DRAFT);\n setInstancePage(1);\n }, [defaultState]);\n const handleFilterSubmit = useCallback((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n const handleFieldDraftChange = useCallback(\n (path: string, draft: FieldFilterDraft): void => {\n setFieldDrafts((previous): FieldFilterDrafts => ({\n ...previous,\n [path]: draft,\n }));\n setInstancePage(1);\n },\n [],\n );\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n const templateOptions = useMemo(\n (): readonly SelectChoice[] =>\n templates.map((template) => ({ id: template.id, name: template.name })),\n [templates],\n );\n const selectedTemplate = templateOptions.find(\n (option) => option.id === templateId,\n );\n const fieldFilterLines = useMemo(\n (): readonly ReactElement<FilterLineProps>[] =>\n chunkElements(\n readFieldFilterElements(\n fieldPaths,\n fieldDrafts,\n handleFieldDraftChange,\n ),\n FIELD_FILTERS_PER_LINE,\n ).map((elements, index): ReactElement<FilterLineProps> => (\n <FilterLine key={`field-filter-line-${index}`}>\n {[...elements]}\n </FilterLine>\n )),\n [fieldDrafts, fieldPaths, handleFieldDraftChange],\n );\n const sortFieldChoices = useMemo(\n (): readonly SelectChoice[] =>\n sortOptions.map((option) => ({ id: option.id, name: option.label })),\n [sortOptions],\n );\n const selectedSortField =\n sortFieldChoices.find((option) => option.id === sortDraft.field) ??\n sortFieldChoices.find((option) => option.id === DEFAULT_SORT_OPTION.id);\n\n const searchFilterLine = (\n <FilterLine key=\"search\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"範本\"\n name=\"instanceTemplate\"\n >\n <Select\n clearable\n fullWidth\n onChange={handleTemplateChange}\n options={[...templateOptions]}\n placeholder=\"全部範本\"\n size=\"sub\"\n value={selectedTemplate ?? null}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n const sortFilterLine = (\n <FilterLine key=\"sort\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序欄位\"\n name=\"instanceSortField\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n field: option?.id ?? DEFAULT_SORT_DRAFT.field,\n }));\n setInstancePage(1);\n }}\n options={[...sortFieldChoices]}\n placeholder=\"排序欄位\"\n size=\"sub\"\n value={selectedSortField ?? null}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序方向\"\n name=\"instanceSortDirection\"\n >\n <RadioGroup\n name=\"instanceSortDirection\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n direction: readSortDirection(event.target.value),\n }));\n setInstancePage(1);\n }}\n options={[...SORT_DIRECTION_OPTIONS]}\n size=\"sub\"\n type=\"segment\"\n value={sortDraft.direction}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea\n className={styles.instanceFilterArea}\n onReset={handleFilterReset}\n onSubmit={handleFilterSubmit}\n resetText=\"清除條件\"\n rowAlign=\"end\"\n size=\"sub\"\n submitText=\"重新查詢\"\n >\n {[searchFilterLine, ...fieldFilterLines, sortFilterLine]}\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {schemaError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {schemaError}\n </Typography>\n ) : null}\n {templateId !== null &&\n !schemaLoading &&\n !schemaError &&\n templateSchema &&\n fieldPaths.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此範本沒有可篩選的欄位。\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction chunkElements<T>(\n items: readonly T[],\n size: number,\n): readonly (readonly T[])[] {\n return items.reduce<readonly (readonly T[])[]>(\n (lines, item): readonly (readonly T[])[] => {\n const last = lines[lines.length - 1];\n\n return last && last.length < size\n ? [...lines.slice(0, -1), [...last, item]]\n : [...lines, [item]];\n },\n [],\n );\n}\n\nfunction readSortDirection(value: string): ApprovalInstanceSortDirection {\n return value === 'ASC' ? 'ASC' : 'DESC';\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取簽核案件失敗。';\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";require('../approval-instance-list-page.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-C1j_vFKo.cjs"),r=require("./format-date-time-D-cx5M8z.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("@rytass/bpm-core-client"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let ee=require("@rytass/bpm-core-client/template"),d=require("@rytass/bpm-core-shared"),f=require("@rytass/bpm-core-client/form");function p(e){switch(e.kind){case`number`:return{kind:`number-range`};case`date`:return{kind:`date-range`};case`datetime`:return{kind:`datetime-range`};case`boolean`:return{kind:`boolean`};case`member`:case`org_unit`:return{kind:`id-in`};case`option`:return e.staticOptions?{kind:`option-in`,options:e.staticOptions}:{kind:`contains`};case`text`:return{kind:`contains`}}}var m={from:``,text:``,to:``,values:[]},h=/^-?\d+(\.\d+)?$/u;function g(e){return _(e)!==null}function _(e){let t=e.trim().replace(/,/gu,``);return h.test(t)?t:null}function te(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function v(e,t){switch(p(e).kind){case`contains`:{let n=t.text.trim();return n?{fieldKey:e.path,operator:`CONTAINS`,values:[n]}:null}case`option-in`:return t.values.length>0?{fieldKey:e.path,operator:`IN`,values:[...t.values]}:null;case`id-in`:{let n=te(t.text);return n.length>0?{fieldKey:e.path,operator:`IN`,values:n}:null}case`number-range`:{let n=_(t.from),r=_(t.to);return n||r?{fieldKey:e.path,operator:`RANGE`,...n?{from:n}:{},...r?{to:r}:{}}:null}case`date-range`:case`datetime-range`:{let n=t.from.trim(),r=t.to.trim();return n||r?{fieldKey:e.path,operator:`RANGE`,...n?{from:n}:{},...r?{to:r}:{}}:null}case`boolean`:{let n=t.values[0];return n===`true`||n===`false`?{fieldKey:e.path,operator:`EQUALS`,values:[n]}:null}}}function ne(e,t){return e.flatMap(e=>{let n=v(e,t[e.path]??m);return n?[n]:[]})}var y={direction:`DESC`,field:``},re={id:``,label:`預設(建立時間,新到舊)`},b={completedAt:`完成時間`,submittedAt:`送出時間`,updatedAt:`最後更新`};function ie(e,t){let n=d.APPROVAL_INSTANCE_SORT_TIME_FIELDS.map(e=>({id:e,label:b[e]})),r=t?e.filter(d.isFilterableFieldSortable).map(e=>({id:e.path,label:e.label})):[];return[re,...n,...r]}function ae(e,t,n){return e===``||d.APPROVAL_INSTANCE_SORT_TIME_FIELDS.includes(e)?!0:n&&t.some(t=>t.path===e)}function oe(e){return e.field===``?void 0:[{direction:e.direction,field:e.field}]}var x=[{id:`true`,name:`是`},{id:`false`,name:`否`}];function se(e,t,n){return e.flatMap(e=>{let r=t[e.path]??m,i=t=>{n(e.path,t)},o=p(e);return o.kind===`number-range`?[S(`${e.path}:from`,`${e.label}(下限)`,(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{i({...r,from:e.target.value})},placeholder:`${e.label}:下限`,size:`sub`,value:r.from,variant:`base`}),w(r.from)),S(`${e.path}:to`,`${e.label}(上限)`,(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{i({...r,to:e.target.value})},placeholder:`${e.label}:上限`,size:`sub`,value:r.to,variant:`base`}),w(r.to))]:[S(e.path,e.label,T(e,r,i,e.label),o.kind===`id-in`?`多個${C(e)}以逗號分隔`:void 0)]})}function S(e,t,n,r){return(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,hintText:r,controlFieldSlotLayout:l.ControlFieldSlotLayout.SUB,layout:l.FormFieldLayout.VERTICAL,label:t,name:`fieldFilter-${e}`,children:n})},e)}function C(e){return e.kind===`org_unit`?`組織`:`成員`}function w(e){return!e||g(e)?void 0:`請輸入數字`}function T(e,t,n,r){let i=p(e);if(i.kind===`option-in`){let e=i.options.map(e=>({id:e.value,name:e.label}));return(0,s.jsx)(a.Select,{clearable:!0,fullWidth:!0,mode:`multiple`,onChange:e=>{n({...t,values:e.map(e=>e.id)})},options:[...e],placeholder:`${r}:全部`,size:`sub`,value:e.filter(e=>t.values.includes(e.id))})}if(i.kind===`boolean`){let e=x.find(e=>t.values.includes(e.id));return(0,s.jsx)(a.Select,{clearable:!0,fullWidth:!0,onChange:e=>{n({...t,values:e?[e.id]:[]})},options:[...x],placeholder:`${r}:全部`,size:`sub`,value:e??null})}return i.kind===`date-range`?(0,s.jsx)(a.DateRangePicker,{clearable:!0,fullWidth:!0,inputFromPlaceholder:`${r}:起`,inputToPlaceholder:`迄`,onChange:e=>{n({...t,from:(0,f.formatDatePickerValue)(e?.[0])??``,to:(0,f.formatDatePickerValue)(e?.[1])??``})},size:`sub`,value:t.from&&t.to?[t.from,t.to]:[]}):i.kind===`datetime-range`?(0,s.jsx)(a.DateTimeRangePicker,{clearable:!0,fullWidth:!0,onChange:e=>{n({...t,from:(0,f.formatDateTimePickerValue)(e[0])??``,to:(0,f.formatDateTimePickerValue)(e[1])??``})},size:`sub`,value:[t.from||void 0,t.to||void 0]}):i.kind===`id-in`?(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{n({...t,text:e.target.value})},placeholder:`${r}:${C(e)} ID`,size:`sub`,value:t.text,variant:`base`}):(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{n({...t,text:e.target.value})},placeholder:`${r}:包含`,size:`sub`,value:t.text,variant:`base`})}var ce={instanceFilterArea:`bpm_instanceFilterArea_qpvJq`},le=[10,20,50],ue=3,E=[{id:`ALL`,name:`全部狀態`,state:null},{id:`RUNNING`,name:`進行中`,state:`RUNNING`},{id:`APPROVED`,name:`已通過`,state:`APPROVED`},{id:`REJECTED`,name:`已拒絕`,state:`REJECTED`},{id:`RETURNED`,name:`已退回`,state:`RETURNED`},{id:`CANCELLED`,name:`已取消`,state:`CANCELLED`},{id:`EXPIRED`,name:`已逾期`,state:`EXPIRED`},{id:`DRAFT`,name:`草稿`,state:`DRAFT`}],de=[{id:`DESC`,name:`新到舊`},{id:`ASC`,name:`舊到新`}];function fe({defaultState:e,description:f,emptyMessage:p,searchPlaceholder:m,title:h,view:g}){let _=t.r(),te=n.r(),[v,b]=(0,i.useState)(null),[x,S]=(0,i.useState)(new Map),[C,w]=(0,i.useState)(1),[T,fe]=(0,i.useState)(10),[O,k]=(0,i.useState)(0),[j,M]=(0,i.useState)(!0),[N,be]=(0,i.useState)([]),[P,F]=(0,i.useState)(``),[I,L]=(0,i.useState)(D(e)),[R,z]=(0,i.useState)([]),[B,xe]=(0,i.useState)(null),[V,H]=(0,i.useState)(null),[Se,U]=(0,i.useState)(!1),[W,G]=(0,i.useState)(null),[K,q]=(0,i.useState)({}),[J,Y]=(0,i.useState)(y),X=(0,i.useRef)(0),Z=(0,i.useMemo)(()=>V?(0,d.readFilterableFieldPaths)(V):[],[V]),Ce=(0,i.useMemo)(()=>B===null?void 0:ne(Z,K),[K,Z,B]),we=(0,i.useMemo)(()=>oe(J),[J]),Te=(0,i.useMemo)(()=>ie(Z,B!==null),[Z,B]),Q=(0,i.useCallback)(async()=>{let e=X.current+1;X.current=e,M(!0),b(null);try{let t=await(0,c.listApprovalInstancesPage)({fieldFilters:Ce,page:C,pageSize:T,searchText:P,sort:we,state:I.state,templateId:B,view:g});if(e!==X.current)return;be(t.instances.map(he)),k(t.totalCount)}catch(t){e===X.current&&b(A(t))}finally{e===X.current&&M(!1)}},[Ce,C,T,P,we,I,B,g]);(0,i.useEffect)(()=>{Q()},[Q]),(0,i.useEffect)(()=>{let e=!1;return(async()=>{try{let t=await(0,ee.listApprovalTemplates)();e||z(t)}catch{e||z([])}})(),()=>{e=!0}},[]),(0,i.useEffect)(()=>{if(B===null){H(null),U(!1),G(null);return}let e=!1;return U(!0),G(null),(async()=>{try{let t=await(0,c.readApprovalTemplateCurrentFormSchema)(B);e||H(t)}catch(t){e||(H(null),G(A(t)))}finally{e||U(!1)}})(),()=>{e=!0}},[B]),(0,i.useEffect)(()=>{let e=Array.from(new Set(N.map(e=>e.initiatorMemberId).filter(Boolean)));if(e.length===0){S(new Map);return}let t=!1;return(async()=>{try{let n=await(0,o.resolveMembers)(e);if(t)return;S(new Map(n.map(e=>[e.memberId,e])))}catch{if(t)return;S(new Map)}})(),()=>{t=!0}},[N]);let Ee=(0,i.useCallback)(e=>{xe(e?.id??null),H(null),q({}),w(1),Y(e=>ae(e.field,[],!1)?e:{...e,field:y.field})},[]),De=(0,i.useCallback)(()=>{F(``),L(D(e)),xe(null),H(null),q({}),Y(y),w(1)},[e]),Oe=(0,i.useCallback)(()=>{Q()},[Q]),ke=(0,i.useCallback)((e,t)=>{q(n=>({...n,[e]:t})),w(1)},[]),Ae=(0,i.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:300},{key:`state`,render:e=>(0,s.jsx)(a.Typography,{color:ve(e.state),component:`span`,variant:`body`,children:e.stateLabel}),title:`狀態`,width:120},{key:`initiatorMemberId`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:ye(e.initiatorMemberId,x)}),title:`發起人`,width:180},{key:`startedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:r.t(e.startedAt)}),title:`發起時間`,width:220},{key:`completedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:r.t(e.completedAt)}),title:`完成時間`,width:220}],[x]),je=(0,i.useMemo)(()=>({render:e=>[{name:`查看`,onClick:()=>_.push(te.caseDetail(e.id))}],variant:`base-secondary`,width:88}),[_]),Me=(0,i.useMemo)(()=>R.map(e=>({id:e.id,name:e.name})),[R]),Ne=Me.find(e=>e.id===B),Pe=(0,i.useMemo)(()=>pe(se(Z,K,ke),ue).map((e,t)=>(0,s.jsx)(a.FilterLine,{children:[...e]},`field-filter-line-${t}`)),[K,Z,ke]),$=(0,i.useMemo)(()=>Te.map(e=>({id:e.id,name:e.label})),[Te]),Fe=$.find(e=>e.id===J.field)??$.find(e=>e.id===re.id),Ie=(0,s.jsxs)(a.FilterLine,{children:[(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:l.ControlFieldSlotLayout.SUB,layout:l.FormFieldLayout.VERTICAL,name:`instanceSearchText`,children:(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{F(e.target.value),w(1)},placeholder:m,size:`sub`,value:P,variant:`base`})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:l.ControlFieldSlotLayout.SUB,layout:l.FormFieldLayout.VERTICAL,name:`instanceState`,children:(0,s.jsx)(a.Select,{clearable:!1,fullWidth:!0,onChange:e=>{L(ge(e)),w(1)},options:[...E],placeholder:`狀態`,renderValue:e=>`狀態:${_e(e)}`,size:`sub`,value:I})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:l.ControlFieldSlotLayout.SUB,layout:l.FormFieldLayout.VERTICAL,label:`範本`,name:`instanceTemplate`,children:(0,s.jsx)(a.Select,{clearable:!0,fullWidth:!0,onChange:Ee,options:[...Me],placeholder:`全部範本`,size:`sub`,value:Ne??null})})})]},`search`),Le=(0,s.jsxs)(a.FilterLine,{children:[(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:l.ControlFieldSlotLayout.SUB,layout:l.FormFieldLayout.VERTICAL,label:`排序欄位`,name:`instanceSortField`,children:(0,s.jsx)(a.Select,{clearable:!1,fullWidth:!0,onChange:e=>{Y(t=>({...t,field:e?.id??y.field})),w(1)},options:[...$],placeholder:`排序欄位`,size:`sub`,value:Fe??null})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:l.ControlFieldSlotLayout.SUB,layout:l.FormFieldLayout.VERTICAL,label:`排序方向`,name:`instanceSortDirection`,children:(0,s.jsx)(a.RadioGroup,{name:`instanceSortDirection`,onChange:e=>{Y(t=>({...t,direction:me(e.target.value)})),w(1)},options:[...de],size:`sub`,type:`segment`,value:J.direction})})})]},`sort`);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.PageHeader,{children:(0,s.jsx)(u.default,{description:f,title:h})}),(0,s.jsx)(a.SectionGroup,{children:(0,s.jsxs)(a.Section,{filterArea:(0,s.jsx)(a.FilterArea,{className:ce.instanceFilterArea,onReset:De,onSubmit:Oe,resetText:`清除條件`,rowAlign:`end`,size:`sub`,submitText:`重新查詢`,children:[Ie,...Pe,Le]}),children:[v?(0,s.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:v}):null,W?(0,s.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:W}):null,B!==null&&!Se&&!W&&V&&Z.length===0?(0,s.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:`此範本沒有可篩選的欄位。`}):null,!v&&!j&&N.length===0?(0,s.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:p}):null,(0,s.jsx)(a.Table,{actions:je,columns:Ae,dataSource:[...N],fullWidth:!0,loading:j,pagination:{current:C,onChange:e=>{w(e)},onChangePageSize:e=>{w(1),fe(e)},pageSize:T,pageSizeLabel:`每頁筆數`,pageSizeOptions:le,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:O}})]})})]})}function pe(e,t){return e.reduce((e,n)=>{let r=e[e.length-1];return r&&r.length<t?[...e.slice(0,-1),[...r,n]]:[...e,[n]]},[])}function me(e){return e===`ASC`?`ASC`:`DESC`}function he(e){return{...e,caseTitle:(0,c.readApprovalInstanceCaseTitle)(e),key:e.id,stateLabel:k(e.state)}}function ge(e){return O(e)?D(e.state):E[0]}function D(e){return E.find(t=>t.state===e)??E[0]}function _e(e){return O(e)?e.name:E[0].name}function O(e){return typeof e==`object`&&!!e&&`id`in e&&`name`in e&&`state`in e}function k(e){return e===`RUNNING`?`進行中`:e===`APPROVED`?`已通過`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`CANCELLED`?`已取消`:e===`EXPIRED`?`已逾期`:`草稿`}function ve(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`CANCELLED`||e===`EXPIRED`?`text-error`:`text-neutral`}function ye(e,t){let n=(e??``).trim();return n?t.get(n)?.name??n:`未知發起人`}function A(e){return e instanceof Error?e.message:`讀取簽核案件失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return fe}});
|
|
2
|
-
//# sourceMappingURL=approval-instance-list-page-
|
|
1
|
+
"use client";require('../approval-instance-list-page.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-C1j_vFKo.cjs"),r=require("./format-date-time-D-cx5M8z.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("@rytass/bpm-core-client"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@rytass/bpm-core-shared"),u=require("@mezzanine-ui/core/form"),d=require("@mezzanine-ui/react/ContentHeader");d=e.t(d,1);let ee=require("@rytass/bpm-core-client/template"),f=require("@rytass/bpm-core-client/form");function p(e){switch(e.kind){case`number`:return{kind:`number-range`};case`date`:return{kind:`date-range`};case`datetime`:return{kind:`datetime-range`};case`boolean`:return{kind:`boolean`};case`member`:case`org_unit`:return{kind:`id-in`};case`option`:return e.staticOptions?{kind:`option-in`,options:e.staticOptions}:{kind:`contains`};case`text`:return{kind:`contains`}}}var m={from:``,text:``,to:``,values:[]},h=/^-?\d+(\.\d+)?$/u;function g(e){return _(e)!==null}function _(e){let t=e.trim().replace(/,/gu,``);return h.test(t)?t:null}function te(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}function v(e,t){switch(p(e).kind){case`contains`:{let n=t.text.trim();return n?{fieldKey:e.path,operator:`CONTAINS`,values:[n]}:null}case`option-in`:return t.values.length>0?{fieldKey:e.path,operator:`IN`,values:[...t.values]}:null;case`id-in`:{let n=te(t.text);return n.length>0?{fieldKey:e.path,operator:`IN`,values:n}:null}case`number-range`:{let n=_(t.from),r=_(t.to);return n||r?{fieldKey:e.path,operator:`RANGE`,...n?{from:n}:{},...r?{to:r}:{}}:null}case`date-range`:case`datetime-range`:{let n=t.from.trim(),r=t.to.trim();return n||r?{fieldKey:e.path,operator:`RANGE`,...n?{from:n}:{},...r?{to:r}:{}}:null}case`boolean`:{let n=t.values[0];return n===`true`||n===`false`?{fieldKey:e.path,operator:`EQUALS`,values:[n]}:null}}}function ne(e,t){return e.flatMap(e=>{let n=v(e,t[e.path]??m);return n?[n]:[]})}var y={direction:`DESC`,field:``},re={id:``,label:`預設(建立時間,新到舊)`},b={completedAt:`完成時間`,submittedAt:`送出時間`,updatedAt:`最後更新`};function ie(e,t){let n=l.APPROVAL_INSTANCE_SORT_TIME_FIELDS.map(e=>({id:e,label:b[e]})),r=t?e.filter(l.isFilterableFieldSortable).map(e=>({id:e.path,label:e.label})):[];return[re,...n,...r]}function ae(e,t,n){return e===``||l.APPROVAL_INSTANCE_SORT_TIME_FIELDS.includes(e)?!0:n&&t.some(t=>t.path===e)}function oe(e){return e.field===``?void 0:[{direction:e.direction,field:e.field}]}var x=[{id:`true`,name:`是`},{id:`false`,name:`否`}];function se(e,t,n){return e.flatMap(e=>{let r=t[e.path]??m,i=t=>{n(e.path,t)},o=p(e);return o.kind===`number-range`?[S(`${e.path}:from`,`${e.label}(下限)`,(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{i({...r,from:e.target.value})},placeholder:`${e.label}:下限`,size:`sub`,value:r.from,variant:`base`}),w(r.from)),S(`${e.path}:to`,`${e.label}(上限)`,(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{i({...r,to:e.target.value})},placeholder:`${e.label}:上限`,size:`sub`,value:r.to,variant:`base`}),w(r.to))]:[S(e.path,e.label,T(e,r,i,e.label),o.kind===`id-in`?`多個${C(e)}以逗號分隔`:void 0)]})}function S(e,t,n,r){return(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,hintText:r,controlFieldSlotLayout:u.ControlFieldSlotLayout.SUB,layout:u.FormFieldLayout.VERTICAL,label:t,name:`fieldFilter-${e}`,children:n})},e)}function C(e){return e.kind===`org_unit`?`組織`:`成員`}function w(e){return!e||g(e)?void 0:`請輸入數字`}function T(e,t,n,r){let i=p(e);if(i.kind===`option-in`){let e=i.options.map(e=>({id:e.value,name:e.label}));return(0,s.jsx)(a.Select,{clearable:!0,fullWidth:!0,mode:`multiple`,onChange:e=>{n({...t,values:e.map(e=>e.id)})},options:[...e],placeholder:`${r}:全部`,size:`sub`,value:e.filter(e=>t.values.includes(e.id))})}if(i.kind===`boolean`){let e=x.find(e=>t.values.includes(e.id));return(0,s.jsx)(a.Select,{clearable:!0,fullWidth:!0,onChange:e=>{n({...t,values:e?[e.id]:[]})},options:[...x],placeholder:`${r}:全部`,size:`sub`,value:e??null})}return i.kind===`date-range`?(0,s.jsx)(a.DateRangePicker,{clearable:!0,fullWidth:!0,inputFromPlaceholder:`${r}:起`,inputToPlaceholder:`迄`,onChange:e=>{n({...t,from:(0,f.formatDatePickerValue)(e?.[0])??``,to:(0,f.formatDatePickerValue)(e?.[1])??``})},size:`sub`,value:t.from&&t.to?[t.from,t.to]:[]}):i.kind===`datetime-range`?(0,s.jsx)(a.DateTimeRangePicker,{clearable:!0,fullWidth:!0,onChange:e=>{n({...t,from:(0,f.formatDateTimePickerValue)(e[0])??``,to:(0,f.formatDateTimePickerValue)(e[1])??``})},size:`sub`,value:[t.from||void 0,t.to||void 0]}):i.kind===`id-in`?(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{n({...t,text:e.target.value})},placeholder:`${r}:${C(e)} ID`,size:`sub`,value:t.text,variant:`base`}):(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{n({...t,text:e.target.value})},placeholder:`${r}:包含`,size:`sub`,value:t.text,variant:`base`})}var ce={instanceFilterArea:`bpm_instanceFilterArea_qpvJq`},le=[10,20,50],ue=3,E=[{id:`ALL`,name:`全部狀態`,state:null},{id:`RUNNING`,name:`進行中`,state:`RUNNING`},{id:`APPROVED`,name:`已通過`,state:`APPROVED`},{id:`REJECTED`,name:`已拒絕`,state:`REJECTED`},{id:`RETURNED`,name:`已退回`,state:`RETURNED`},{id:`CANCELLED`,name:`已取消`,state:`CANCELLED`},{id:`EXPIRED`,name:`已逾期`,state:`EXPIRED`},{id:`DRAFT`,name:`草稿`,state:`DRAFT`}],de=[{id:`DESC`,name:`新到舊`},{id:`ASC`,name:`舊到新`}];function fe({defaultState:e,description:f,emptyMessage:p,searchPlaceholder:m,title:h,view:g}){let _=t.r(),te=n.r(),[v,b]=(0,i.useState)(null),[x,S]=(0,i.useState)(new Map),[C,w]=(0,i.useState)(1),[T,fe]=(0,i.useState)(10),[O,k]=(0,i.useState)(0),[j,M]=(0,i.useState)(!0),[N,be]=(0,i.useState)([]),[P,F]=(0,i.useState)(``),[I,L]=(0,i.useState)(D(e)),[R,z]=(0,i.useState)([]),[B,xe]=(0,i.useState)(null),[V,H]=(0,i.useState)(null),[Se,U]=(0,i.useState)(!1),[W,G]=(0,i.useState)(null),[K,q]=(0,i.useState)({}),[J,Y]=(0,i.useState)(y),X=(0,i.useRef)(0),Z=(0,i.useMemo)(()=>V?(0,l.readFilterableFieldPaths)(V):[],[V]),Ce=(0,i.useMemo)(()=>B===null?void 0:ne(Z,K),[K,Z,B]),we=(0,i.useMemo)(()=>oe(J),[J]),Te=(0,i.useMemo)(()=>ie(Z,B!==null),[Z,B]),Q=(0,i.useCallback)(async()=>{let e=X.current+1;X.current=e,M(!0),b(null);try{let t=await(0,c.listApprovalInstancesPage)({fieldFilters:Ce,page:C,pageSize:T,searchText:P,sort:we,state:I.state,templateId:B,view:g});if(e!==X.current)return;be(t.instances.map(he)),k(t.totalCount)}catch(t){e===X.current&&b(A(t))}finally{e===X.current&&M(!1)}},[Ce,C,T,P,we,I,B,g]);(0,i.useEffect)(()=>{Q()},[Q]),(0,i.useEffect)(()=>{let e=!1;return(async()=>{try{let t=await(0,ee.listApprovalTemplates)();e||z(t)}catch{e||z([])}})(),()=>{e=!0}},[]),(0,i.useEffect)(()=>{if(B===null){H(null),U(!1),G(null);return}let e=!1;return U(!0),G(null),(async()=>{try{let t=await(0,c.readApprovalTemplateCurrentFormSchema)(B);e||H(t)}catch(t){e||(H(null),G(A(t)))}finally{e||U(!1)}})(),()=>{e=!0}},[B]),(0,i.useEffect)(()=>{let e=Array.from(new Set(N.map(e=>e.initiatorMemberId).filter(Boolean)));if(e.length===0){S(new Map);return}let t=!1;return(async()=>{try{let n=await(0,o.resolveMembers)(e);if(t)return;S(new Map(n.map(e=>[e.memberId,e])))}catch{if(t)return;S(new Map)}})(),()=>{t=!0}},[N]);let Ee=(0,i.useCallback)(e=>{xe(e?.id??null),H(null),q({}),w(1),Y(e=>ae(e.field,[],!1)?e:{...e,field:y.field})},[]),De=(0,i.useCallback)(()=>{F(``),L(D(e)),xe(null),H(null),q({}),Y(y),w(1)},[e]),Oe=(0,i.useCallback)(()=>{Q()},[Q]),ke=(0,i.useCallback)((e,t)=>{q(n=>({...n,[e]:t})),w(1)},[]),Ae=(0,i.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:300},{key:`state`,render:e=>(0,s.jsx)(a.Typography,{color:ve(e.state),component:`span`,variant:`body`,children:e.stateLabel}),title:`狀態`,width:120},{key:`initiatorMemberId`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:ye(e.initiatorMemberId,x)}),title:`發起人`,width:180},{key:`startedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:r.t(e.startedAt)}),title:`發起時間`,width:220},{key:`completedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:r.t(e.completedAt)}),title:`完成時間`,width:220}],[x]),je=(0,i.useMemo)(()=>({render:e=>[{name:`查看`,onClick:()=>_.push(te.caseDetail(e.id))}],variant:`base-secondary`,width:88}),[_]),Me=(0,i.useMemo)(()=>R.map(e=>({id:e.id,name:e.name})),[R]),Ne=Me.find(e=>e.id===B),Pe=(0,i.useMemo)(()=>pe(se(Z,K,ke),ue).map((e,t)=>(0,s.jsx)(a.FilterLine,{children:[...e]},`field-filter-line-${t}`)),[K,Z,ke]),$=(0,i.useMemo)(()=>Te.map(e=>({id:e.id,name:e.label})),[Te]),Fe=$.find(e=>e.id===J.field)??$.find(e=>e.id===re.id),Ie=(0,s.jsxs)(a.FilterLine,{children:[(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:u.ControlFieldSlotLayout.SUB,layout:u.FormFieldLayout.VERTICAL,name:`instanceSearchText`,children:(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{F(e.target.value),w(1)},placeholder:m,size:`sub`,value:P,variant:`base`})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:u.ControlFieldSlotLayout.SUB,layout:u.FormFieldLayout.VERTICAL,name:`instanceState`,children:(0,s.jsx)(a.Select,{clearable:!1,fullWidth:!0,onChange:e=>{L(ge(e)),w(1)},options:[...E],placeholder:`狀態`,renderValue:e=>`狀態:${_e(e)}`,size:`sub`,value:I})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:u.ControlFieldSlotLayout.SUB,layout:u.FormFieldLayout.VERTICAL,label:`範本`,name:`instanceTemplate`,children:(0,s.jsx)(a.Select,{clearable:!0,fullWidth:!0,onChange:Ee,options:[...Me],placeholder:`全部範本`,size:`sub`,value:Ne??null})})})]},`search`),Le=(0,s.jsxs)(a.FilterLine,{children:[(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:u.ControlFieldSlotLayout.SUB,layout:u.FormFieldLayout.VERTICAL,label:`排序欄位`,name:`instanceSortField`,children:(0,s.jsx)(a.Select,{clearable:!1,fullWidth:!0,onChange:e=>{Y(t=>({...t,field:e?.id??y.field})),w(1)},options:[...$],placeholder:`排序欄位`,size:`sub`,value:Fe??null})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,controlFieldSlotLayout:u.ControlFieldSlotLayout.SUB,layout:u.FormFieldLayout.VERTICAL,label:`排序方向`,name:`instanceSortDirection`,children:(0,s.jsx)(a.RadioGroup,{name:`instanceSortDirection`,onChange:e=>{Y(t=>({...t,direction:me(e.target.value)})),w(1)},options:[...de],size:`sub`,type:`segment`,value:J.direction})})})]},`sort`);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.PageHeader,{children:(0,s.jsx)(d.default,{description:f,title:h})}),(0,s.jsx)(a.SectionGroup,{children:(0,s.jsxs)(a.Section,{filterArea:(0,s.jsx)(a.FilterArea,{className:ce.instanceFilterArea,onReset:De,onSubmit:Oe,resetText:`清除條件`,rowAlign:`end`,size:`sub`,submitText:`重新查詢`,children:[Ie,...Pe,Le]}),children:[v?(0,s.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:v}):null,W?(0,s.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:W}):null,B!==null&&!Se&&!W&&V&&Z.length===0?(0,s.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:`此範本沒有可篩選的欄位。`}):null,!v&&!j&&N.length===0?(0,s.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:p}):null,(0,s.jsx)(a.Table,{actions:je,columns:Ae,dataSource:[...N],fullWidth:!0,loading:j,pagination:{current:C,onChange:e=>{w(e)},onChangePageSize:e=>{w(1),fe(e)},pageSize:T,pageSizeLabel:`每頁筆數`,pageSizeOptions:le,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:O}})]})})]})}function pe(e,t){return e.reduce((e,n)=>{let r=e[e.length-1];return r&&r.length<t?[...e.slice(0,-1),[...r,n]]:[...e,[n]]},[])}function me(e){return e===`ASC`?`ASC`:`DESC`}function he(e){return{...e,caseTitle:(0,c.readApprovalInstanceCaseTitle)(e),key:e.id,stateLabel:k(e.state)}}function ge(e){return O(e)?D(e.state):E[0]}function D(e){return E.find(t=>t.state===e)??E[0]}function _e(e){return O(e)?e.name:E[0].name}function O(e){return typeof e==`object`&&!!e&&`id`in e&&`name`in e&&`state`in e}function k(e){return e===`RUNNING`?`進行中`:e===`APPROVED`?`已通過`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`CANCELLED`?`已取消`:e===`EXPIRED`?`已逾期`:`草稿`}function ve(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`CANCELLED`||e===`EXPIRED`?`text-error`:`text-neutral`}function ye(e,t){let n=(e??``).trim();return n?t.get(n)?.name??n:`未知發起人`}function A(e){return e instanceof Error?e.message:`讀取簽核案件失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return fe}});
|
|
2
|
+
//# sourceMappingURL=approval-instance-list-page-Cv5I1YPX.cjs.map
|