@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.
Files changed (108) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/chunks/{FormBuilderView-WtC2iW5f.js → FormBuilderView-6KdApi-D.js} +8 -8
  3. package/dist/chunks/{FormBuilderView-WtC2iW5f.js.map → FormBuilderView-6KdApi-D.js.map} +1 -1
  4. package/dist/chunks/{FormBuilderView-DjPGrOJ2.cjs → FormBuilderView-CGKkuVFi.cjs} +3 -3
  5. package/dist/chunks/{FormBuilderView-DjPGrOJ2.cjs.map → FormBuilderView-CGKkuVFi.cjs.map} +1 -1
  6. package/dist/chunks/{approval-instance-list-page-Bth7Raya.js → approval-instance-list-page-BI5fIXc-.js} +26 -26
  7. package/dist/chunks/{approval-instance-list-page-Bth7Raya.js.map → approval-instance-list-page-BI5fIXc-.js.map} +1 -1
  8. package/dist/chunks/{approval-instance-list-page-Dcvo6TrT.cjs → approval-instance-list-page-Cv5I1YPX.cjs} +2 -2
  9. package/dist/chunks/{approval-instance-list-page-Dcvo6TrT.cjs.map → approval-instance-list-page-Cv5I1YPX.cjs.map} +1 -1
  10. package/dist/chunks/{compose-DZvIspW3.js → compose-DFuLPmOA.js} +4 -4
  11. package/dist/chunks/{compose-DZvIspW3.js.map → compose-DFuLPmOA.js.map} +1 -1
  12. package/dist/chunks/compose-DK3ocWwG.cjs +2 -0
  13. package/dist/chunks/compose-DK3ocWwG.cjs.map +1 -0
  14. package/dist/chunks/designer-CAUWEKJ4.cjs +69 -0
  15. package/dist/chunks/designer-CAUWEKJ4.cjs.map +1 -0
  16. package/dist/chunks/{designer-CWubIE69.js → designer-CCy5EbOe.js} +2189 -1608
  17. package/dist/chunks/designer-CCy5EbOe.js.map +1 -0
  18. package/dist/chunks/detail-C5KrUC7s.cjs +5 -0
  19. package/dist/chunks/detail-C5KrUC7s.cjs.map +1 -0
  20. package/dist/chunks/{detail-Bv90gvy0.js → detail-Dnc4PPWO.js} +768 -742
  21. package/dist/chunks/detail-Dnc4PPWO.js.map +1 -0
  22. package/dist/chunks/{instance-error-message-CAP1vJhX.js → instance-error-message-BEM4O_Kj.js} +6 -2
  23. package/dist/chunks/instance-error-message-BEM4O_Kj.js.map +1 -0
  24. package/dist/chunks/instance-error-message-BpCLCOjp.cjs +2 -0
  25. package/dist/chunks/instance-error-message-BpCLCOjp.cjs.map +1 -0
  26. package/dist/chunks/organization-time-zone-provider-B7CXQril.cjs +2 -0
  27. package/dist/chunks/organization-time-zone-provider-B7CXQril.cjs.map +1 -0
  28. package/dist/chunks/organization-time-zone-provider-DNL8yo4-.js +42 -0
  29. package/dist/chunks/organization-time-zone-provider-DNL8yo4-.js.map +1 -0
  30. package/dist/chunks/{providers-BbCs23sk.js → providers-CQWekD7_.js} +197 -196
  31. package/dist/chunks/providers-CQWekD7_.js.map +1 -0
  32. package/dist/chunks/providers-VUOh6i0i.cjs +2 -0
  33. package/dist/chunks/providers-VUOh6i0i.cjs.map +1 -0
  34. package/dist/components/notification-drawer-options.d.cts +18 -0
  35. package/dist/components/notification-drawer-options.d.ts +18 -0
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +1 -0
  39. package/dist/index.d.ts +1 -0
  40. package/dist/index.js +23 -23
  41. package/dist/index.js.map +1 -1
  42. package/dist/lib/organization-time-zone-provider.d.cts +20 -0
  43. package/dist/lib/organization-time-zone-provider.d.ts +20 -0
  44. package/dist/lib/organization-time-zone.d.cts +8 -0
  45. package/dist/lib/organization-time-zone.d.ts +8 -0
  46. package/dist/lib/providers.d.cts +10 -1
  47. package/dist/lib/providers.d.ts +10 -1
  48. package/dist/next/BPMNextProviders.d.cts +8 -1
  49. package/dist/next/BPMNextProviders.d.ts +8 -1
  50. package/dist/next/index.cjs +1 -1
  51. package/dist/next/index.cjs.map +1 -1
  52. package/dist/next/index.js +12 -11
  53. package/dist/next/index.js.map +1 -1
  54. package/dist/pages/instances/detail/index.cjs +1 -1
  55. package/dist/pages/instances/detail/index.js +1 -1
  56. package/dist/pages/templates/compose/index.cjs +1 -1
  57. package/dist/pages/templates/compose/index.js +1 -1
  58. package/dist/pages/templates/designer/index.cjs +1 -1
  59. package/dist/pages/templates/designer/index.js +1 -1
  60. package/dist/views/cc/index.cjs +1 -1
  61. package/dist/views/cc/index.js +1 -1
  62. package/dist/views/forms/builder/index.cjs +1 -1
  63. package/dist/views/forms/builder/index.js +1 -1
  64. package/dist/views/instances/detail/index.cjs +1 -1
  65. package/dist/views/instances/detail/index.js +1 -1
  66. package/dist/views/instances/detail/sections/shared.d.cts +0 -1
  67. package/dist/views/instances/detail/sections/shared.d.ts +0 -1
  68. package/dist/views/instances/new/index.cjs +1 -1
  69. package/dist/views/instances/new/index.js +1 -1
  70. package/dist/views/search/index.cjs +1 -1
  71. package/dist/views/search/index.js +1 -1
  72. package/dist/views/sent/index.cjs +1 -1
  73. package/dist/views/sent/index.js +1 -1
  74. package/dist/views/templates/compose/index.cjs +1 -1
  75. package/dist/views/templates/compose/index.js +1 -1
  76. package/dist/views/templates/designer/approver-resolver-model.d.cts +105 -1
  77. package/dist/views/templates/designer/approver-resolver-model.d.ts +105 -1
  78. package/dist/views/templates/designer/dynamic-form-resolver-options.d.cts +5 -0
  79. package/dist/views/templates/designer/dynamic-form-resolver-options.d.ts +5 -0
  80. package/dist/views/templates/designer/index.cjs +1 -1
  81. package/dist/views/templates/designer/index.js +1 -1
  82. package/dist/views/templates/designer/node-actor-resolver-options.d.cts +44 -1
  83. package/dist/views/templates/designer/node-actor-resolver-options.d.ts +44 -1
  84. package/dist/views/templates/designer/notify-recipient-options.d.cts +81 -0
  85. package/dist/views/templates/designer/notify-recipient-options.d.ts +81 -0
  86. package/dist/views/templates/designer/position-level-options.d.cts +3 -1
  87. package/dist/views/templates/designer/position-level-options.d.ts +3 -1
  88. package/dist/views/templates/designer/position-scope.d.cts +51 -0
  89. package/dist/views/templates/designer/position-scope.d.ts +51 -0
  90. package/package.json +3 -3
  91. package/dist/chunks/compose-BKUTsB2W.cjs +0 -2
  92. package/dist/chunks/compose-BKUTsB2W.cjs.map +0 -1
  93. package/dist/chunks/designer-CWubIE69.js.map +0 -1
  94. package/dist/chunks/designer-C_m8DmMl.cjs +0 -69
  95. package/dist/chunks/designer-C_m8DmMl.cjs.map +0 -1
  96. package/dist/chunks/detail-Bv90gvy0.js.map +0 -1
  97. package/dist/chunks/detail-DNzqesdI.cjs +0 -5
  98. package/dist/chunks/detail-DNzqesdI.cjs.map +0 -1
  99. package/dist/chunks/instance-error-message-BW464LRQ.cjs +0 -2
  100. package/dist/chunks/instance-error-message-BW464LRQ.cjs.map +0 -1
  101. package/dist/chunks/instance-error-message-CAP1vJhX.js.map +0 -1
  102. package/dist/chunks/language-provider-Bdnx3Gxl.cjs +0 -2
  103. package/dist/chunks/language-provider-Bdnx3Gxl.cjs.map +0 -1
  104. package/dist/chunks/language-provider-phkWOapf.js +0 -17
  105. package/dist/chunks/language-provider-phkWOapf.js.map +0 -1
  106. package/dist/chunks/providers-BbCs23sk.js.map +0 -1
  107. package/dist/chunks/providers-D_KAgOOu.cjs +0 -2
  108. 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 { ControlFieldSlotLayout as g, FormFieldLayout as _ } from "@mezzanine-ui/core/form";
11
- import pe from "@mezzanine-ui/react/ContentHeader";
12
- import { listApprovalTemplates as me } from "@rytass/bpm-core-client/template";
13
- import { APPROVAL_INSTANCE_SORT_TIME_FIELDS as v, isFilterableFieldSortable as he, readFilterableFieldPaths as ge } from "@rytass/bpm-core-shared";
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 = v.map((e) => ({
117
+ let n = g.map((e) => ({
118
118
  id: e,
119
119
  label: k[e]
120
- })), r = t ? e.filter(he).map((e) => ({
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 === "" || v.includes(e) ? !0 : n && t.some((t) => t.path === 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: g.SUB,
186
- layout: _.VERTICAL,
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: v, title: he, 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 ? ge(H) : [], [H]), Ve = a(() => V === null ? void 0 : _e(Q, q), [
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 me();
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: g.SUB,
516
- layout: _.VERTICAL,
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: v,
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: g.SUB,
535
- layout: _.VERTICAL,
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: g.SUB,
556
- layout: _.VERTICAL,
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: g.SUB,
575
- layout: _.VERTICAL,
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: g.SUB,
598
- layout: _.VERTICAL,
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(pe, {
616
+ return /* @__PURE__ */ h(le, { children: [/* @__PURE__ */ m(re, { children: /* @__PURE__ */ m(he, {
617
617
  description: te,
618
- title: he
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-Bth7Raya.js.map
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-Dcvo6TrT.cjs.map
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