@rytass/bpm-core-react 0.17.6 → 0.17.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/chunks/{FormBuilderView-aBcA-_tt.cjs → FormBuilderView-CUOyS07f.cjs} +2 -2
- package/dist/chunks/{FormBuilderView-aBcA-_tt.cjs.map → FormBuilderView-CUOyS07f.cjs.map} +1 -1
- package/dist/chunks/{FormBuilderView-BYL42M0d.js → FormBuilderView-ClLnQ1e_.js} +2 -2
- package/dist/chunks/{FormBuilderView-BYL42M0d.js.map → FormBuilderView-ClLnQ1e_.js.map} +1 -1
- package/dist/chunks/{FormRendererView-cZGOOjU5.js → FormRendererView-BsTwZkqU.js} +207 -198
- package/dist/chunks/FormRendererView-BsTwZkqU.js.map +1 -0
- package/dist/chunks/FormRendererView-GpsE03np.cjs +4 -0
- package/dist/chunks/FormRendererView-GpsE03np.cjs.map +1 -0
- package/dist/chunks/approver-filled-form-D1DmqDVP.cjs +2 -0
- package/dist/chunks/approver-filled-form-D1DmqDVP.cjs.map +1 -0
- package/dist/chunks/approver-filled-form-DuQGPtNB.js +95 -0
- package/dist/chunks/approver-filled-form-DuQGPtNB.js.map +1 -0
- package/dist/chunks/{compose-DOEaPfEC.cjs → compose-DjEJi5Dv.cjs} +2 -2
- package/dist/chunks/{compose-DOEaPfEC.cjs.map → compose-DjEJi5Dv.cjs.map} +1 -1
- package/dist/chunks/{compose-v1Vcw9hE.js → compose-WekGZj74.js} +4 -4
- package/dist/chunks/{compose-v1Vcw9hE.js.map → compose-WekGZj74.js.map} +1 -1
- package/dist/chunks/{designer-DBBrktom.js → designer-D87ILhjz.js} +1664 -1182
- package/dist/chunks/designer-D87ILhjz.js.map +1 -0
- package/dist/chunks/designer-DESS0CMl.cjs +65 -0
- package/dist/chunks/designer-DESS0CMl.cjs.map +1 -0
- package/dist/chunks/detail-D49NuNCn.cjs +2 -0
- package/dist/chunks/detail-D49NuNCn.cjs.map +1 -0
- package/dist/chunks/{detail-B_bSg31B.js → detail-URwxkcro.js} +1036 -847
- package/dist/chunks/detail-URwxkcro.js.map +1 -0
- package/dist/chunks/{providers-H_vPRsSN.js → providers-B_d5tbCL.js} +178 -167
- package/dist/chunks/providers-B_d5tbCL.js.map +1 -0
- package/dist/chunks/providers-chuJvMgv.cjs +2 -0
- package/dist/chunks/providers-chuJvMgv.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.js +1 -1
- package/dist/next/workflow-chat-route.cjs +1 -0
- package/dist/next/workflow-chat-route.cjs.map +1 -1
- package/dist/next/workflow-chat-route.d.cts +1 -1
- package/dist/next/workflow-chat-route.d.ts +1 -1
- package/dist/next/workflow-chat-route.js +1 -1
- package/dist/next/workflow-chat-route.js.map +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/renderer/FormRendererView.d.cts +16 -1
- package/dist/views/forms/renderer/FormRendererView.d.ts +16 -1
- package/dist/views/forms/renderer/index.cjs +1 -1
- package/dist/views/forms/renderer/index.js +1 -1
- package/dist/views/inbox/index.cjs +1 -1
- package/dist/views/inbox/index.cjs.map +1 -1
- package/dist/views/inbox/index.js +109 -99
- package/dist/views/inbox/index.js.map +1 -1
- package/dist/views/instances/approver-filled-form.d.cts +76 -0
- package/dist/views/instances/approver-filled-form.d.ts +76 -0
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +30 -2
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +30 -2
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.cts +4 -1
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +4 -1
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +21 -0
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +21 -0
- package/dist/views/instances/detail/sections/container-helpers.d.cts +1 -1
- package/dist/views/instances/detail/sections/container-helpers.d.ts +1 -1
- package/dist/views/instances/detail/sections/shared.d.cts +11 -2
- package/dist/views/instances/detail/sections/shared.d.ts +11 -2
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.cjs.map +1 -1
- package/dist/views/instances/new/index.js +88 -87
- package/dist/views/instances/new/index.js.map +1 -1
- package/dist/views/instances/viewer-field-access.d.cts +22 -0
- package/dist/views/instances/viewer-field-access.d.ts +22 -0
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.cts +33 -0
- package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.ts +33 -0
- package/dist/views/templates/designer/field-access-matrix/FieldAccessNodeSection.d.cts +20 -0
- package/dist/views/templates/designer/field-access-matrix/FieldAccessNodeSection.d.ts +20 -0
- package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.cts +22 -0
- package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.ts +22 -0
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunks/FormRendererView-DRFi_IH7.cjs +0 -4
- package/dist/chunks/FormRendererView-DRFi_IH7.cjs.map +0 -1
- package/dist/chunks/FormRendererView-cZGOOjU5.js.map +0 -1
- package/dist/chunks/designer-CTXMqCD2.cjs +0 -65
- package/dist/chunks/designer-CTXMqCD2.cjs.map +0 -1
- package/dist/chunks/designer-DBBrktom.js.map +0 -1
- package/dist/chunks/detail-BQSVgVlO.cjs +0 -2
- package/dist/chunks/detail-BQSVgVlO.cjs.map +0 -1
- package/dist/chunks/detail-B_bSg31B.js.map +0 -1
- package/dist/chunks/providers-DP7b0TMN.cjs +0 -2
- package/dist/chunks/providers-DP7b0TMN.cjs.map +0 -1
- package/dist/chunks/providers-H_vPRsSN.js.map +0 -1
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import { CSSProperties, ReactElement } from 'react';
|
|
2
2
|
import { FormDataSourceValueSnapshots, FormDefinitionSchema, FormFieldDefinition, FormUiSchema } from '@rytass/bpm-core-shared/form';
|
|
3
3
|
import { FormRendererValues } from '@rytass/bpm-core-client/form';
|
|
4
|
+
import { ResolvedFieldAccess } from '@rytass/bpm-core-shared';
|
|
4
5
|
import { FormDataSourceFieldState, FormRendererDataSourceContext } from './form-data-source-field.cjs';
|
|
5
6
|
export interface FormRendererProps {
|
|
6
7
|
readonly dataSourceContext?: FormRendererDataSourceContext;
|
|
7
8
|
readonly dataSourceInitialValues?: FormRendererValues;
|
|
8
9
|
readonly emptyText?: string;
|
|
9
10
|
readonly errors?: Readonly<Record<string, string>>;
|
|
11
|
+
/**
|
|
12
|
+
* Per top-level field, what this viewer may see and edit (ADR 20 §3.3,
|
|
13
|
+
* `resolveFieldAccess`). A field with `visible: false` is not rendered; one
|
|
14
|
+
* with `editable: true` stays editable inside a `readonly` form, and one
|
|
15
|
+
* with `editable: false` is read-only in an editable form. The form's own
|
|
16
|
+
* rules (`hidden`, `visibleWhen`, `readonlyWhen`) still apply. A field the
|
|
17
|
+
* map leaves out follows `readonly`; leaving the prop out changes nothing.
|
|
18
|
+
*/
|
|
19
|
+
readonly fieldAccess?: Readonly<Record<string, ResolvedFieldAccess>>;
|
|
20
|
+
/**
|
|
21
|
+
* Short text shown after a field's label (Mezzanine `labelOptionalMarker`),
|
|
22
|
+
* per top-level field — e.g. 「本關補填」 on the fields an approver fills.
|
|
23
|
+
*/
|
|
24
|
+
readonly fieldLabelMarkers?: Readonly<Record<string, string>>;
|
|
10
25
|
readonly maxWidth?: CSSProperties['maxWidth'];
|
|
11
26
|
readonly onChange?: (values: FormRendererValues) => void;
|
|
12
27
|
readonly onDataSourceStateChange?: (fieldKey: string, state: Pick<FormDataSourceFieldState, 'hasValue' | 'invalidValues' | 'status'>) => void;
|
|
@@ -20,5 +35,5 @@ export interface FormRendererProps {
|
|
|
20
35
|
readonly uiSchema: FormUiSchema;
|
|
21
36
|
readonly value?: FormRendererValues;
|
|
22
37
|
}
|
|
23
|
-
export declare function FormRenderer({ dataSourceContext, dataSourceInitialValues, emptyText, errors, maxWidth, onChange, onDataSourceStateChange, onUploadAttachment, optionSnapshots, readonly, schema, singleColumn, uiSchema, value, }: FormRendererProps): ReactElement;
|
|
38
|
+
export declare function FormRenderer({ dataSourceContext, dataSourceInitialValues, emptyText, errors, fieldAccess, fieldLabelMarkers, maxWidth, onChange, onDataSourceStateChange, onUploadAttachment, optionSnapshots, readonly, schema, singleColumn, uiSchema, value, }: FormRendererProps): ReactElement;
|
|
24
39
|
export { FormRenderer as FormRendererView };
|
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import { CSSProperties, ReactElement } from 'react';
|
|
2
2
|
import { FormDataSourceValueSnapshots, FormDefinitionSchema, FormFieldDefinition, FormUiSchema } from '@rytass/bpm-core-shared/form';
|
|
3
3
|
import { FormRendererValues } from '@rytass/bpm-core-client/form';
|
|
4
|
+
import { ResolvedFieldAccess } from '@rytass/bpm-core-shared';
|
|
4
5
|
import { FormDataSourceFieldState, FormRendererDataSourceContext } from './form-data-source-field.js';
|
|
5
6
|
export interface FormRendererProps {
|
|
6
7
|
readonly dataSourceContext?: FormRendererDataSourceContext;
|
|
7
8
|
readonly dataSourceInitialValues?: FormRendererValues;
|
|
8
9
|
readonly emptyText?: string;
|
|
9
10
|
readonly errors?: Readonly<Record<string, string>>;
|
|
11
|
+
/**
|
|
12
|
+
* Per top-level field, what this viewer may see and edit (ADR 20 §3.3,
|
|
13
|
+
* `resolveFieldAccess`). A field with `visible: false` is not rendered; one
|
|
14
|
+
* with `editable: true` stays editable inside a `readonly` form, and one
|
|
15
|
+
* with `editable: false` is read-only in an editable form. The form's own
|
|
16
|
+
* rules (`hidden`, `visibleWhen`, `readonlyWhen`) still apply. A field the
|
|
17
|
+
* map leaves out follows `readonly`; leaving the prop out changes nothing.
|
|
18
|
+
*/
|
|
19
|
+
readonly fieldAccess?: Readonly<Record<string, ResolvedFieldAccess>>;
|
|
20
|
+
/**
|
|
21
|
+
* Short text shown after a field's label (Mezzanine `labelOptionalMarker`),
|
|
22
|
+
* per top-level field — e.g. 「本關補填」 on the fields an approver fills.
|
|
23
|
+
*/
|
|
24
|
+
readonly fieldLabelMarkers?: Readonly<Record<string, string>>;
|
|
10
25
|
readonly maxWidth?: CSSProperties['maxWidth'];
|
|
11
26
|
readonly onChange?: (values: FormRendererValues) => void;
|
|
12
27
|
readonly onDataSourceStateChange?: (fieldKey: string, state: Pick<FormDataSourceFieldState, 'hasValue' | 'invalidValues' | 'status'>) => void;
|
|
@@ -20,5 +35,5 @@ export interface FormRendererProps {
|
|
|
20
35
|
readonly uiSchema: FormUiSchema;
|
|
21
36
|
readonly value?: FormRendererValues;
|
|
22
37
|
}
|
|
23
|
-
export declare function FormRenderer({ dataSourceContext, dataSourceInitialValues, emptyText, errors, maxWidth, onChange, onDataSourceStateChange, onUploadAttachment, optionSnapshots, readonly, schema, singleColumn, uiSchema, value, }: FormRendererProps): ReactElement;
|
|
38
|
+
export declare function FormRenderer({ dataSourceContext, dataSourceInitialValues, emptyText, errors, fieldAccess, fieldLabelMarkers, maxWidth, onChange, onDataSourceStateChange, onUploadAttachment, optionSnapshots, readonly, schema, singleColumn, uiSchema, value, }: FormRendererProps): ReactElement;
|
|
24
39
|
export { FormRenderer as FormRendererView };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/FormRendererView-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/FormRendererView-GpsE03np.cjs");exports.FormRenderer=e.t,exports.FormRendererView=e.t,exports.isFormDataSourceFieldSubmissionBlocked=e.i,exports.readFormDataSourceFieldStatusMessage=e.a,exports.readFormDataSourceSubmissionBlockMessage=e.o,exports.useFormDataSourceField=e.s;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as FormRenderer, t as FormRendererView, i as isFormDataSourceFieldSubmissionBlocked, a as readFormDataSourceFieldStatusMessage, o as readFormDataSourceSubmissionBlockMessage, s as useFormDataSourceField } from "../../../chunks/FormRendererView-
|
|
1
|
+
export { t as FormRenderer, t as FormRendererView, i as isFormDataSourceFieldSubmissionBlocked, a as readFormDataSourceFieldStatusMessage, o as readFormDataSourceSubmissionBlockMessage, s as useFormDataSourceField } from "../../../chunks/FormRendererView-BsTwZkqU.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../chunks/rolldown-runtime-BocRIvOZ.cjs"),t=require("../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../chunks/auth-provider-4BeCw7cI.cjs"),r=require("../../chunks/format-date-time-D-cx5M8z.cjs"),i=require("../../chunks/routes-config-C1j_vFKo.cjs"),a=require("../../chunks/task-node-label-BF6UllxP.cjs");let o=require("react"),s=require("@mezzanine-ui/react"),c=require("react/jsx-runtime"),l=require("@rytass/bpm-core-client/workflow"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@mezzanine-ui/icons");function f(){let e=t.r(),a=i.r(),{member:f}=n.n(),h=f?.memberId??null,[g,_]=(0,o.useState)(`pending`),[v,y]=(0,o.useState)(null),[x,C]=(0,o.useState)([]),[T,E]=(0,o.useState)(!0),[D,O]=(0,o.useState)([]);(0,o.useEffect)(()=>{h&&I()},[h]);let A=(0,o.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:280},{dataIndex:`nodeText`,key:`nodeText`,title:`節點`,width:180},{dataIndex:`statusLabel`,key:`statusLabel`,title:`狀態`,width:120},{key:`slaDueAt`,render:e=>(0,c.jsx)(s.Typography,{color:e.slaStatusColor,component:`span`,variant:`body`,children:e.slaStatusText}),title:`SLA`,width:180},{key:`createdAt`,render:e=>(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:r.t(e.createdAt)}),title:`建立時間`,width:220}],[]),j=(0,o.useMemo)(()=>({render:t=>[{name:`處理`,onClick:()=>e.push(a.caseDetail(t.instanceId))}],variant:`base-secondary`,width:88}),[e,a]),M=(0,o.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:280},{dataIndex:`nodeText`,key:`nodeText`,title:`節點`,width:180},{key:`decisionLabel`,render:e=>(0,c.jsx)(s.Typography,{color:b(e.decisionAction),component:`span`,variant:`body`,children:e.decisionLabel}),title:`決議`,width:120},{key:`decisionComment`,render:e=>(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:e.decisionCommentText}),title:`意見`,width:240},{key:`instanceStateLabel`,render:e=>(0,c.jsx)(s.Typography,{color:S(e.instanceState),component:`span`,variant:`body`,children:e.instanceStateLabel}),title:`流程狀態`,width:140},{key:`decidedAt`,render:e=>(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:w(e.decidedAt)}),title:`簽核時間`,width:220}],[]),N=(0,o.useMemo)(()=>({render:t=>[{name:`查看`,onClick:()=>e.push(a.caseDetail(t.instanceId))}],variant:`base-secondary`,width:88}),[e,a]),P=(0,o.useMemo)(()=>x.filter(e=>e.instanceState===`RUNNING`),[x]);function F(e){_(e===`history`||e===`pending`||e===`tracking`?e:`pending`)}async function I(){E(!0),y(null);try{if(!h){O([]),C([]);return}let[e,t]=await Promise.all([(0,l.listInboxTasks)(h),(0,l.listApprovalHistoryTasks)(h)]),[n,r]=await Promise.all([p(e),m(t)]);O(n),C(r)}catch(e){y(k(e))}finally{E(!1)}}return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.PageHeader,{children:(0,c.jsx)(u.default,{description:`目前以 ${f?.name??h??`目前登入會員`} 查詢待處理與歷史簽核任務。`,title:`我的待簽`,children:(0,c.jsx)(s.Button,{icon:d.PlusIcon,iconType:`leading`,onClick:()=>e.push(a.caseNew()),variant:`base-primary`,children:`發起簽核`})})}),(0,c.jsx)(s.SectionGroup,{children:(0,c.jsxs)(s.Section,{children:[v?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:v}):null,(0,c.jsxs)(s.Tab,{activeKey:g,onChange:F,size:`sub`,children:[(0,c.jsx)(s.TabItem,{badgeCount:T?void 0:D.length,children:`待簽核`},`pending`),(0,c.jsx)(s.TabItem,{badgeCount:T?void 0:P.length,children:`已處理未結束`},`tracking`),(0,c.jsx)(s.TabItem,{children:`歷史簽核記錄`},`history`)]}),g===`pending`?(0,c.jsx)(s.Table,{actions:j,columns:A,dataSource:D,fullWidth:!0,loading:T}):null,g===`tracking`?(0,c.jsx)(s.Table,{actions:N,columns:M,dataSource:P,fullWidth:!0,loading:T}):null,g===`history`?(0,c.jsx)(s.Table,{actions:N,columns:M,dataSource:x,fullWidth:!0,loading:T}):null]})})]})}async function p(e){let t=await h(e);return e.map((e,n)=>({...e,caseTitle:g(e,t[n]??null),key:e.id,nodeText:a.t(e),slaStatusColor:E(e.slaDueAt),slaStatusText:T(e.slaDueAt),statusLabel:O(e.status)}))}async function m(e){let[t,n]=await Promise.all([Promise.all(e.map(e=>(0,l.listTaskDecisions)(e.id))),h(e)]);return e.map((e,r)=>{let i=_(t[r]??[]),o=n[r]??null;return{...e,caseTitle:g(e,o),decisionAction:i?.action??null,decisionComment:i?.comment??null,decisionCommentText:C(i?.comment??null),decisionLabel:y(i?.action??null),decidedAt:i?.decidedAt??e.completedAt,instanceState:o?.state??null,instanceStateLabel:x(o?.state??null),key:e.id,nodeText:a.t(e)}})}async function h(e){return Promise.all(e.map(async e=>{try{return(await(0,l.readApprovalInstance)(e.instanceId)).instance}catch{return null}}))}function g(e,t){return t?(0,l.readApprovalInstanceCaseTitle)(t):e.instanceId}function _(e){return[...e].sort(v)[0]??null}function v(e,t){return new Date(t.decidedAt).getTime()-new Date(e.decidedAt).getTime()}function y(e){return e===`APPROVED`?`同意`:e===`REJECTED`?`拒絕`:e===`RETURNED`?`退回`:e===`TRANSFERRED`?`轉派`:`未記錄`}function b(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`RETURNED`?`text-error`:`text-neutral`}function x(e){return e===`RUNNING`?`進行中`:e===`APPROVED`?`已通過`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`CANCELLED`?`已取消`:e===`EXPIRED`?`已逾期`:e===`DRAFT`?`草稿`:`-`}function S(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`CANCELLED`||e===`EXPIRED`?`text-error`:`text-neutral`}function C(e){return(e?.trim()??``)||`-`}function w(e){return r.t(e)}function T(e){if(!e)return`-`;let t=new Date(e).getTime(),n=Date.now(),r=D(Math.abs(t-n));return t<n?`已逾期 ${r}`:`剩餘 ${r}`}function E(e){return e?new Date(e).getTime()<Date.now()?`text-error`:`text-success`:`text-neutral`}function D(e){let t=Math.max(1,Math.ceil(e/6e4)),n=Math.floor(t/1440),r=Math.floor(t%1440/60),i=t%60;return n>0?`${n}天 ${r}小時`:r>0?`${r}小時 ${i}分鐘`:`${i}分鐘`}function O(e){return e===`PENDING`?`待處理`:e===`IN_PROGRESS`?`處理中`:e===`COMPLETED`?`已完成`:e===`TRANSFERRED`?`已轉派`:e===`CANCELLED`?`已取消`:e}function k(e){return e instanceof Error?e.message:`發生未知錯誤`}exports.InboxView=f;
|
|
1
|
+
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../chunks/rolldown-runtime-BocRIvOZ.cjs"),t=require("../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../chunks/auth-provider-4BeCw7cI.cjs"),r=require("../../chunks/format-date-time-D-cx5M8z.cjs"),i=require("../../chunks/routes-config-C1j_vFKo.cjs"),a=require("../../chunks/task-node-label-BF6UllxP.cjs");let o=require("react"),s=require("@mezzanine-ui/react"),c=require("react/jsx-runtime"),l=require("@rytass/bpm-core-client/workflow"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@mezzanine-ui/icons");function f(){let e=t.r(),a=i.r(),{member:f}=n.n(),h=f?.memberId??null,[g,_]=(0,o.useState)(`pending`),[v,y]=(0,o.useState)(null),[x,C]=(0,o.useState)([]),[T,E]=(0,o.useState)(!0),[D,O]=(0,o.useState)([]);(0,o.useEffect)(()=>{h&&I()},[h]);let A=(0,o.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:280},{dataIndex:`nodeText`,key:`nodeText`,title:`節點`,width:180},{dataIndex:`statusLabel`,key:`statusLabel`,title:`狀態`,width:120},{key:`fill`,render:e=>e.hasFillableFields?(0,c.jsx)(s.Badge,{size:`sub`,text:`需補填`,variant:`dot-warning`}):null,title:`補填`,width:120},{key:`slaDueAt`,render:e=>(0,c.jsx)(s.Typography,{color:e.slaStatusColor,component:`span`,variant:`body`,children:e.slaStatusText}),title:`SLA`,width:180},{key:`createdAt`,render:e=>(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:r.t(e.createdAt)}),title:`建立時間`,width:220}],[]),j=(0,o.useMemo)(()=>({render:t=>[{name:`處理`,onClick:()=>e.push(a.caseDetail(t.instanceId))}],variant:`base-secondary`,width:88}),[e,a]),M=(0,o.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:280},{dataIndex:`nodeText`,key:`nodeText`,title:`節點`,width:180},{key:`decisionLabel`,render:e=>(0,c.jsx)(s.Typography,{color:b(e.decisionAction),component:`span`,variant:`body`,children:e.decisionLabel}),title:`決議`,width:120},{key:`decisionComment`,render:e=>(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:e.decisionCommentText}),title:`意見`,width:240},{key:`instanceStateLabel`,render:e=>(0,c.jsx)(s.Typography,{color:S(e.instanceState),component:`span`,variant:`body`,children:e.instanceStateLabel}),title:`流程狀態`,width:140},{key:`decidedAt`,render:e=>(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:w(e.decidedAt)}),title:`簽核時間`,width:220}],[]),N=(0,o.useMemo)(()=>({render:t=>[{name:`查看`,onClick:()=>e.push(a.caseDetail(t.instanceId))}],variant:`base-secondary`,width:88}),[e,a]),P=(0,o.useMemo)(()=>x.filter(e=>e.instanceState===`RUNNING`),[x]);function F(e){_(e===`history`||e===`pending`||e===`tracking`?e:`pending`)}async function I(){E(!0),y(null);try{if(!h){O([]),C([]);return}let[e,t]=await Promise.all([(0,l.listInboxTasks)(h),(0,l.listApprovalHistoryTasks)(h)]),[n,r]=await Promise.all([p(e),m(t)]);O(n),C(r)}catch(e){y(k(e))}finally{E(!1)}}return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.PageHeader,{children:(0,c.jsx)(u.default,{description:`目前以 ${f?.name??h??`目前登入會員`} 查詢待處理與歷史簽核任務。`,title:`我的待簽`,children:(0,c.jsx)(s.Button,{icon:d.PlusIcon,iconType:`leading`,onClick:()=>e.push(a.caseNew()),variant:`base-primary`,children:`發起簽核`})})}),(0,c.jsx)(s.SectionGroup,{children:(0,c.jsxs)(s.Section,{children:[v?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:v}):null,(0,c.jsxs)(s.Tab,{activeKey:g,onChange:F,size:`sub`,children:[(0,c.jsx)(s.TabItem,{badgeCount:T?void 0:D.length,children:`待簽核`},`pending`),(0,c.jsx)(s.TabItem,{badgeCount:T?void 0:P.length,children:`已處理未結束`},`tracking`),(0,c.jsx)(s.TabItem,{children:`歷史簽核記錄`},`history`)]}),g===`pending`?(0,c.jsx)(s.Table,{actions:j,columns:A,dataSource:D,fullWidth:!0,loading:T}):null,g===`tracking`?(0,c.jsx)(s.Table,{actions:N,columns:M,dataSource:P,fullWidth:!0,loading:T}):null,g===`history`?(0,c.jsx)(s.Table,{actions:N,columns:M,dataSource:x,fullWidth:!0,loading:T}):null]})})]})}async function p(e){let t=await h(e);return e.map((e,n)=>({...e,caseTitle:g(e,t[n]??null),key:e.id,nodeText:a.t(e),slaStatusColor:E(e.slaDueAt),slaStatusText:T(e.slaDueAt),statusLabel:O(e.status)}))}async function m(e){let[t,n]=await Promise.all([Promise.all(e.map(e=>(0,l.listTaskDecisions)(e.id))),h(e)]);return e.map((e,r)=>{let i=_(t[r]??[]),o=n[r]??null;return{...e,caseTitle:g(e,o),decisionAction:i?.action??null,decisionComment:i?.comment??null,decisionCommentText:C(i?.comment??null),decisionLabel:y(i?.action??null),decidedAt:i?.decidedAt??e.completedAt,instanceState:o?.state??null,instanceStateLabel:x(o?.state??null),key:e.id,nodeText:a.t(e)}})}async function h(e){return Promise.all(e.map(async e=>{try{return(await(0,l.readApprovalInstance)(e.instanceId)).instance}catch{return null}}))}function g(e,t){return t?(0,l.readApprovalInstanceCaseTitle)(t):e.instanceId}function _(e){return[...e].sort(v)[0]??null}function v(e,t){return new Date(t.decidedAt).getTime()-new Date(e.decidedAt).getTime()}function y(e){return e===`APPROVED`?`同意`:e===`REJECTED`?`拒絕`:e===`RETURNED`?`退回`:e===`TRANSFERRED`?`轉派`:`未記錄`}function b(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`RETURNED`?`text-error`:`text-neutral`}function x(e){return e===`RUNNING`?`進行中`:e===`APPROVED`?`已通過`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`CANCELLED`?`已取消`:e===`EXPIRED`?`已逾期`:e===`DRAFT`?`草稿`:`-`}function S(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`CANCELLED`||e===`EXPIRED`?`text-error`:`text-neutral`}function C(e){return(e?.trim()??``)||`-`}function w(e){return r.t(e)}function T(e){if(!e)return`-`;let t=new Date(e).getTime(),n=Date.now(),r=D(Math.abs(t-n));return t<n?`已逾期 ${r}`:`剩餘 ${r}`}function E(e){return e?new Date(e).getTime()<Date.now()?`text-error`:`text-success`:`text-neutral`}function D(e){let t=Math.max(1,Math.ceil(e/6e4)),n=Math.floor(t/1440),r=Math.floor(t%1440/60),i=t%60;return n>0?`${n}天 ${r}小時`:r>0?`${r}小時 ${i}分鐘`:`${i}分鐘`}function O(e){return e===`PENDING`?`待處理`:e===`IN_PROGRESS`?`處理中`:e===`COMPLETED`?`已完成`:e===`TRANSFERRED`?`已轉派`:e===`CANCELLED`?`已取消`:e}function k(e){return e instanceof Error?e.message:`發生未知錯誤`}exports.InboxView=f;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["useRouterAdapter","useBPMRoutes","useAuth","useState","useMemo","Typography","formatDateTime","listInboxTasks","listApprovalHistoryTasks","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","Tab","TabItem","Table","readTaskNodeText","listTaskDecisions","readApprovalInstance","readApprovalInstanceCaseTitle","require_rolldown_runtime","require_router_adapter","require_auth_provider","require_format_date_time","require_routes_config","require_task_node_label","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","InboxView","router","routes","currentMemberId","member","activeTab","setActiveTab","error","setError","historyRows","setHistoryRows","loading","setLoading","pendingRows","setPendingRows","refreshTasks","pendingColumns","record","pendingTableActions","historyColumns","readTaskDecisionColor","readInstanceStateColor","formatHistoryDateTime","historyTableActions","trackingRows","row","handleTabChange","activeKey","nextPendingTasks","nextHistoryTasks","nextPendingRows","nextHistoryRows","readInboxTaskRows","readApprovalHistoryRows","requestError","readErrorMessage","instances","readTaskInstances","tasks","task","readTaskCaseTitle","index","readSlaStatusColor","readSlaStatusText","readTaskStatusLabel","decisionLists","decision","readLatestTaskDecision","instance","readDecisionCommentText","readTaskDecisionLabel","readInstanceStateLabel","decisions","compareTaskDecisionDesc","right","left","action","state","comment","value","dueAt","now","label","formatDuration","totalMinutes","days","hours","minutes","status"],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n ApprovalInstanceRecord,\n listApprovalHistoryTasks,\n listInboxTasks,\n listTaskDecisions,\n readApprovalInstance,\n readApprovalInstanceCaseTitle,\n TaskDecisionRecord,\n TaskRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useAuth } from '../../lib/auth-provider';\nimport { readTaskNodeText } from '../../lib/task-node-label';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n nodeText: string;\n slaStatusColor: 'text-error' | 'text-neutral' | 'text-success';\n slaStatusText: string;\n statusLabel: string;\n }\n>;\n\ntype ApprovalHistoryRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n decisionAction: TaskDecisionRecord['action'] | null;\n decisionComment: string | null;\n decisionCommentText: string;\n decisionLabel: string;\n decidedAt: string | null;\n instanceState: ApprovalInstanceRecord['state'] | null;\n instanceStateLabel: string;\n key: string;\n nodeText: string;\n }\n>;\n\n\n/**\n * Framework-agnostic view for the BPM \"我的待簽\" inbox. Mechanical port of\n * `apps/client/src/app/inbox/page.tsx` — renders pending tasks, tracking,\n * and history tabs.\n */\nexport function InboxView(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activeTab, setActiveTab] = useState<InboxTabKey>('pending');\n const [error, setError] = useState<string | null>(null);\n const [historyRows, setHistoryRows] = useState<ApprovalHistoryRow[]>([]);\n const [loading, setLoading] = useState(true);\n const [pendingRows, setPendingRows] = useState<InboxTaskRow[]>([]);\n\n useEffect((): void => {\n if (!currentMemberId) {\n return;\n }\n\n void refreshTasks();\n }, [currentMemberId]);\n\n const pendingColumns = useMemo(\n (): TableColumn<InboxTaskRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'slaDueAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography\n color={record.slaStatusColor}\n component=\"span\"\n variant=\"body\"\n >\n {record.slaStatusText}\n </Typography>\n ),\n title: 'SLA',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n const pendingTableActions = useMemo(\n (): TableActions<InboxTaskRow> => ({\n render: (record): ReturnType<TableActions<InboxTaskRow>['render']> => [\n {\n name: '處理',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const historyColumns = useMemo(\n (): TableColumn<ApprovalHistoryRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n key: 'decisionLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readTaskDecisionColor(record.decisionAction)}\n component=\"span\"\n variant=\"body\"\n >\n {record.decisionLabel}\n </Typography>\n ),\n title: '決議',\n width: 120,\n },\n {\n key: 'decisionComment',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.decisionCommentText}\n </Typography>\n ),\n title: '意見',\n width: 240,\n },\n {\n key: 'instanceStateLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.instanceState)}\n component=\"span\"\n variant=\"body\"\n >\n {record.instanceStateLabel}\n </Typography>\n ),\n title: '流程狀態',\n width: 140,\n },\n {\n key: 'decidedAt',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatHistoryDateTime(record.decidedAt)}\n </Typography>\n ),\n title: '簽核時間',\n width: 220,\n },\n ],\n [],\n );\n const historyTableActions = useMemo(\n (): TableActions<ApprovalHistoryRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalHistoryRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const trackingRows = useMemo(\n (): ApprovalHistoryRow[] =>\n historyRows.filter((row) => row.instanceState === 'RUNNING'),\n [historyRows],\n );\n\n function handleTabChange(activeKey: Key): void {\n if (\n activeKey === 'history' ||\n activeKey === 'pending' ||\n activeKey === 'tracking'\n ) {\n setActiveTab(activeKey);\n return;\n }\n\n setActiveTab('pending');\n }\n\n async function refreshTasks(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n if (!currentMemberId) {\n setPendingRows([]);\n setHistoryRows([]);\n return;\n }\n\n const [nextPendingTasks, nextHistoryTasks] = await Promise.all([\n listInboxTasks(currentMemberId),\n listApprovalHistoryTasks(currentMemberId),\n ]);\n const [nextPendingRows, nextHistoryRows] = await Promise.all([\n readInboxTaskRows(nextPendingTasks),\n readApprovalHistoryRows(nextHistoryTasks),\n ]);\n\n setPendingRows(nextPendingRows);\n setHistoryRows(nextHistoryRows);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={`目前以 ${member?.name ?? currentMemberId ?? '目前登入會員'} 查詢待處理與歷史簽核任務。`}\n title=\"我的待簽\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Tab activeKey={activeTab} onChange={handleTabChange} size=\"sub\">\n <TabItem\n badgeCount={loading ? undefined : pendingRows.length}\n key=\"pending\"\n >\n 待簽核\n </TabItem>\n <TabItem\n badgeCount={loading ? undefined : trackingRows.length}\n key=\"tracking\"\n >\n 已處理未結束\n </TabItem>\n <TabItem key=\"history\">歷史簽核記錄</TabItem>\n </Tab>\n\n {activeTab === 'pending' ? (\n <Table\n actions={pendingTableActions}\n columns={pendingColumns}\n dataSource={pendingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'tracking' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={trackingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'history' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={historyRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nasync function readInboxTaskRows(\n tasks: readonly TaskRecord[],\n): Promise<InboxTaskRow[]> {\n const instances = await readTaskInstances(tasks);\n\n return tasks.map(\n (task, index): InboxTaskRow => ({\n ...task,\n caseTitle: readTaskCaseTitle(task, instances[index] ?? null),\n key: task.id,\n nodeText: readTaskNodeText(task),\n slaStatusColor: readSlaStatusColor(task.slaDueAt),\n slaStatusText: readSlaStatusText(task.slaDueAt),\n statusLabel: readTaskStatusLabel(task.status),\n }),\n );\n}\n\nasync function readApprovalHistoryRows(\n tasks: readonly TaskRecord[],\n): Promise<ApprovalHistoryRow[]> {\n const [decisionLists, instances] = await Promise.all([\n Promise.all(tasks.map((task) => listTaskDecisions(task.id))),\n readTaskInstances(tasks),\n ]);\n\n return tasks.map((task, index): ApprovalHistoryRow => {\n const decision = readLatestTaskDecision(decisionLists[index] ?? []);\n const instance = instances[index] ?? null;\n\n return {\n ...task,\n caseTitle: readTaskCaseTitle(task, instance),\n decisionAction: decision?.action ?? null,\n decisionComment: decision?.comment ?? null,\n decisionCommentText: readDecisionCommentText(decision?.comment ?? null),\n decisionLabel: readTaskDecisionLabel(decision?.action ?? null),\n decidedAt: decision?.decidedAt ?? task.completedAt,\n instanceState: instance?.state ?? null,\n instanceStateLabel: readInstanceStateLabel(instance?.state ?? null),\n key: task.id,\n nodeText: readTaskNodeText(task),\n };\n });\n}\n\nasync function readTaskInstances(\n tasks: readonly TaskRecord[],\n): Promise<readonly (ApprovalInstanceRecord | null)[]> {\n return Promise.all(\n tasks.map(async (task): Promise<ApprovalInstanceRecord | null> => {\n try {\n return (await readApprovalInstance(task.instanceId)).instance;\n } catch {\n return null;\n }\n }),\n );\n}\n\nfunction readTaskCaseTitle(\n task: TaskRecord,\n instance: ApprovalInstanceRecord | null,\n): string {\n return instance ? readApprovalInstanceCaseTitle(instance) : task.instanceId;\n}\n\nfunction readLatestTaskDecision(\n decisions: readonly TaskDecisionRecord[],\n): TaskDecisionRecord | null {\n return [...decisions].sort(compareTaskDecisionDesc)[0] ?? null;\n}\n\nfunction compareTaskDecisionDesc(\n left: TaskDecisionRecord,\n right: TaskDecisionRecord,\n): number {\n return (\n new Date(right.decidedAt).getTime() - new Date(left.decidedAt).getTime()\n );\n}\n\nfunction readTaskDecisionLabel(\n action: TaskDecisionRecord['action'] | null,\n): string {\n if (action === 'APPROVED') {\n return '同意';\n }\n\n if (action === 'REJECTED') {\n return '拒絕';\n }\n\n if (action === 'RETURNED') {\n return '退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '轉派';\n }\n\n return '未記錄';\n}\n\nfunction readTaskDecisionColor(\n action: TaskDecisionRecord['action'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (action === 'APPROVED') {\n return 'text-success';\n }\n\n if (action === 'REJECTED' || action === 'RETURNED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readInstanceStateLabel(\n state: ApprovalInstanceRecord['state'] | null,\n): string {\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n if (state === 'APPROVED') {\n return '已通過';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n return '-';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceRecord['state'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') {\n return 'text-success';\n }\n\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readDecisionCommentText(comment: string | null): string {\n const trimmedComment = comment?.trim() ?? '';\n\n return trimmedComment || '-';\n}\n\nfunction formatHistoryDateTime(value: string | null): string {\n return formatDateTime(value);\n}\n\nfunction readSlaStatusText(value: string | null): string {\n if (!value) {\n return '-';\n }\n\n const dueAt = new Date(value).getTime();\n const now = Date.now();\n const diffMs = Math.abs(dueAt - now);\n const label = formatDuration(diffMs);\n\n return dueAt < now ? `已逾期 ${label}` : `剩餘 ${label}`;\n}\n\nfunction readSlaStatusColor(\n value: string | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (!value) {\n return 'text-neutral';\n }\n\n return new Date(value).getTime() < Date.now() ? 'text-error' : 'text-success';\n}\n\nfunction formatDuration(value: number): string {\n const totalMinutes = Math.max(1, Math.ceil(value / 60_000));\n const days = Math.floor(totalMinutes / 1440);\n const hours = Math.floor((totalMinutes % 1440) / 60);\n const minutes = totalMinutes % 60;\n\n if (days > 0) {\n return `${days}天 ${hours}小時`;\n }\n\n if (hours > 0) {\n return `${hours}小時 ${minutes}分鐘`;\n }\n\n return `${minutes}分鐘`;\n}\n\nfunction readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') {\n return '待處理';\n }\n\n if (status === 'IN_PROGRESS') {\n return '處理中';\n }\n\n if (status === 'COMPLETED') {\n return '已完成';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n if (status === 'CANCELLED') {\n return '已取消';\n }\n\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["useRouterAdapter","useBPMRoutes","useAuth","useState","useMemo","Badge","Typography","formatDateTime","listInboxTasks","listApprovalHistoryTasks","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","Tab","TabItem","Table","readTaskNodeText","listTaskDecisions","readApprovalInstance","readApprovalInstanceCaseTitle","require_rolldown_runtime","require_router_adapter","require_auth_provider","require_format_date_time","require_routes_config","require_task_node_label","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","InboxView","router","routes","currentMemberId","member","activeTab","setActiveTab","error","setError","historyRows","setHistoryRows","loading","setLoading","pendingRows","setPendingRows","refreshTasks","pendingColumns","record","pendingTableActions","historyColumns","readTaskDecisionColor","readInstanceStateColor","formatHistoryDateTime","historyTableActions","trackingRows","row","handleTabChange","activeKey","nextPendingTasks","nextHistoryTasks","nextPendingRows","nextHistoryRows","readInboxTaskRows","readApprovalHistoryRows","requestError","readErrorMessage","instances","readTaskInstances","tasks","task","readTaskCaseTitle","index","readSlaStatusColor","readSlaStatusText","readTaskStatusLabel","decisionLists","decision","readLatestTaskDecision","instance","readDecisionCommentText","readTaskDecisionLabel","readInstanceStateLabel","decisions","compareTaskDecisionDesc","right","left","action","state","comment","value","dueAt","now","label","formatDuration","totalMinutes","days","hours","minutes","status"],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n ApprovalInstanceRecord,\n listApprovalHistoryTasks,\n listInboxTasks,\n listTaskDecisions,\n readApprovalInstance,\n readApprovalInstanceCaseTitle,\n TaskDecisionRecord,\n TaskRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useAuth } from '../../lib/auth-provider';\nimport { readTaskNodeText } from '../../lib/task-node-label';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n nodeText: string;\n slaStatusColor: 'text-error' | 'text-neutral' | 'text-success';\n slaStatusText: string;\n statusLabel: string;\n }\n>;\n\ntype ApprovalHistoryRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n decisionAction: TaskDecisionRecord['action'] | null;\n decisionComment: string | null;\n decisionCommentText: string;\n decisionLabel: string;\n decidedAt: string | null;\n instanceState: ApprovalInstanceRecord['state'] | null;\n instanceStateLabel: string;\n key: string;\n nodeText: string;\n }\n>;\n\n\n/**\n * Framework-agnostic view for the BPM \"我的待簽\" inbox. Mechanical port of\n * `apps/client/src/app/inbox/page.tsx` — renders pending tasks, tracking,\n * and history tabs.\n */\nexport function InboxView(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activeTab, setActiveTab] = useState<InboxTabKey>('pending');\n const [error, setError] = useState<string | null>(null);\n const [historyRows, setHistoryRows] = useState<ApprovalHistoryRow[]>([]);\n const [loading, setLoading] = useState(true);\n const [pendingRows, setPendingRows] = useState<InboxTaskRow[]>([]);\n\n useEffect((): void => {\n if (!currentMemberId) {\n return;\n }\n\n void refreshTasks();\n }, [currentMemberId]);\n\n const pendingColumns = useMemo(\n (): TableColumn<InboxTaskRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'fill',\n // Approving one of these needs the case page, where the fill is entered.\n render: (record: InboxTaskRow): ReactElement | null =>\n record.hasFillableFields ? (\n <Badge size=\"sub\" text=\"需補填\" variant=\"dot-warning\" />\n ) : null,\n title: '補填',\n width: 120,\n },\n {\n key: 'slaDueAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography\n color={record.slaStatusColor}\n component=\"span\"\n variant=\"body\"\n >\n {record.slaStatusText}\n </Typography>\n ),\n title: 'SLA',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n const pendingTableActions = useMemo(\n (): TableActions<InboxTaskRow> => ({\n render: (record): ReturnType<TableActions<InboxTaskRow>['render']> => [\n {\n name: '處理',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const historyColumns = useMemo(\n (): TableColumn<ApprovalHistoryRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n key: 'decisionLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readTaskDecisionColor(record.decisionAction)}\n component=\"span\"\n variant=\"body\"\n >\n {record.decisionLabel}\n </Typography>\n ),\n title: '決議',\n width: 120,\n },\n {\n key: 'decisionComment',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.decisionCommentText}\n </Typography>\n ),\n title: '意見',\n width: 240,\n },\n {\n key: 'instanceStateLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.instanceState)}\n component=\"span\"\n variant=\"body\"\n >\n {record.instanceStateLabel}\n </Typography>\n ),\n title: '流程狀態',\n width: 140,\n },\n {\n key: 'decidedAt',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatHistoryDateTime(record.decidedAt)}\n </Typography>\n ),\n title: '簽核時間',\n width: 220,\n },\n ],\n [],\n );\n const historyTableActions = useMemo(\n (): TableActions<ApprovalHistoryRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalHistoryRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const trackingRows = useMemo(\n (): ApprovalHistoryRow[] =>\n historyRows.filter((row) => row.instanceState === 'RUNNING'),\n [historyRows],\n );\n\n function handleTabChange(activeKey: Key): void {\n if (\n activeKey === 'history' ||\n activeKey === 'pending' ||\n activeKey === 'tracking'\n ) {\n setActiveTab(activeKey);\n return;\n }\n\n setActiveTab('pending');\n }\n\n async function refreshTasks(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n if (!currentMemberId) {\n setPendingRows([]);\n setHistoryRows([]);\n return;\n }\n\n const [nextPendingTasks, nextHistoryTasks] = await Promise.all([\n listInboxTasks(currentMemberId),\n listApprovalHistoryTasks(currentMemberId),\n ]);\n const [nextPendingRows, nextHistoryRows] = await Promise.all([\n readInboxTaskRows(nextPendingTasks),\n readApprovalHistoryRows(nextHistoryTasks),\n ]);\n\n setPendingRows(nextPendingRows);\n setHistoryRows(nextHistoryRows);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={`目前以 ${member?.name ?? currentMemberId ?? '目前登入會員'} 查詢待處理與歷史簽核任務。`}\n title=\"我的待簽\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Tab activeKey={activeTab} onChange={handleTabChange} size=\"sub\">\n <TabItem\n badgeCount={loading ? undefined : pendingRows.length}\n key=\"pending\"\n >\n 待簽核\n </TabItem>\n <TabItem\n badgeCount={loading ? undefined : trackingRows.length}\n key=\"tracking\"\n >\n 已處理未結束\n </TabItem>\n <TabItem key=\"history\">歷史簽核記錄</TabItem>\n </Tab>\n\n {activeTab === 'pending' ? (\n <Table\n actions={pendingTableActions}\n columns={pendingColumns}\n dataSource={pendingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'tracking' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={trackingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'history' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={historyRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nasync function readInboxTaskRows(\n tasks: readonly TaskRecord[],\n): Promise<InboxTaskRow[]> {\n const instances = await readTaskInstances(tasks);\n\n return tasks.map(\n (task, index): InboxTaskRow => ({\n ...task,\n caseTitle: readTaskCaseTitle(task, instances[index] ?? null),\n key: task.id,\n nodeText: readTaskNodeText(task),\n slaStatusColor: readSlaStatusColor(task.slaDueAt),\n slaStatusText: readSlaStatusText(task.slaDueAt),\n statusLabel: readTaskStatusLabel(task.status),\n }),\n );\n}\n\nasync function readApprovalHistoryRows(\n tasks: readonly TaskRecord[],\n): Promise<ApprovalHistoryRow[]> {\n const [decisionLists, instances] = await Promise.all([\n Promise.all(tasks.map((task) => listTaskDecisions(task.id))),\n readTaskInstances(tasks),\n ]);\n\n return tasks.map((task, index): ApprovalHistoryRow => {\n const decision = readLatestTaskDecision(decisionLists[index] ?? []);\n const instance = instances[index] ?? null;\n\n return {\n ...task,\n caseTitle: readTaskCaseTitle(task, instance),\n decisionAction: decision?.action ?? null,\n decisionComment: decision?.comment ?? null,\n decisionCommentText: readDecisionCommentText(decision?.comment ?? null),\n decisionLabel: readTaskDecisionLabel(decision?.action ?? null),\n decidedAt: decision?.decidedAt ?? task.completedAt,\n instanceState: instance?.state ?? null,\n instanceStateLabel: readInstanceStateLabel(instance?.state ?? null),\n key: task.id,\n nodeText: readTaskNodeText(task),\n };\n });\n}\n\nasync function readTaskInstances(\n tasks: readonly TaskRecord[],\n): Promise<readonly (ApprovalInstanceRecord | null)[]> {\n return Promise.all(\n tasks.map(async (task): Promise<ApprovalInstanceRecord | null> => {\n try {\n return (await readApprovalInstance(task.instanceId)).instance;\n } catch {\n return null;\n }\n }),\n );\n}\n\nfunction readTaskCaseTitle(\n task: TaskRecord,\n instance: ApprovalInstanceRecord | null,\n): string {\n return instance ? readApprovalInstanceCaseTitle(instance) : task.instanceId;\n}\n\nfunction readLatestTaskDecision(\n decisions: readonly TaskDecisionRecord[],\n): TaskDecisionRecord | null {\n return [...decisions].sort(compareTaskDecisionDesc)[0] ?? null;\n}\n\nfunction compareTaskDecisionDesc(\n left: TaskDecisionRecord,\n right: TaskDecisionRecord,\n): number {\n return (\n new Date(right.decidedAt).getTime() - new Date(left.decidedAt).getTime()\n );\n}\n\nfunction readTaskDecisionLabel(\n action: TaskDecisionRecord['action'] | null,\n): string {\n if (action === 'APPROVED') {\n return '同意';\n }\n\n if (action === 'REJECTED') {\n return '拒絕';\n }\n\n if (action === 'RETURNED') {\n return '退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '轉派';\n }\n\n return '未記錄';\n}\n\nfunction readTaskDecisionColor(\n action: TaskDecisionRecord['action'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (action === 'APPROVED') {\n return 'text-success';\n }\n\n if (action === 'REJECTED' || action === 'RETURNED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readInstanceStateLabel(\n state: ApprovalInstanceRecord['state'] | null,\n): string {\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n if (state === 'APPROVED') {\n return '已通過';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n return '-';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceRecord['state'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') {\n return 'text-success';\n }\n\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readDecisionCommentText(comment: string | null): string {\n const trimmedComment = comment?.trim() ?? '';\n\n return trimmedComment || '-';\n}\n\nfunction formatHistoryDateTime(value: string | null): string {\n return formatDateTime(value);\n}\n\nfunction readSlaStatusText(value: string | null): string {\n if (!value) {\n return '-';\n }\n\n const dueAt = new Date(value).getTime();\n const now = Date.now();\n const diffMs = Math.abs(dueAt - now);\n const label = formatDuration(diffMs);\n\n return dueAt < now ? `已逾期 ${label}` : `剩餘 ${label}`;\n}\n\nfunction readSlaStatusColor(\n value: string | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (!value) {\n return 'text-neutral';\n }\n\n return new Date(value).getTime() < Date.now() ? 'text-error' : 'text-success';\n}\n\nfunction formatDuration(value: number): string {\n const totalMinutes = Math.max(1, Math.ceil(value / 60_000));\n const days = Math.floor(totalMinutes / 1440);\n const hours = Math.floor((totalMinutes % 1440) / 60);\n const minutes = totalMinutes % 60;\n\n if (days > 0) {\n return `${days}天 ${hours}小時`;\n }\n\n if (hours > 0) {\n return `${hours}小時 ${minutes}分鐘`;\n }\n\n return `${minutes}分鐘`;\n}\n\nfunction readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') {\n return '待處理';\n }\n\n if (status === 'IN_PROGRESS') {\n return '處理中';\n }\n\n if (status === 'COMPLETED') {\n return '已完成';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n if (status === 'CANCELLED') {\n return '已取消';\n }\n\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
@@ -5,18 +5,18 @@ import { t as n } from "../../chunks/format-date-time-CB-LxzqT.js";
|
|
|
5
5
|
import { r } from "../../chunks/routes-config-yZbESPlw.js";
|
|
6
6
|
import { t as i } from "../../chunks/task-node-label-CWZgOBj0.js";
|
|
7
7
|
import { useEffect as a, useMemo as o, useState as s } from "react";
|
|
8
|
-
import {
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { listApprovalHistoryTasks as
|
|
11
|
-
import
|
|
12
|
-
import { PlusIcon as
|
|
8
|
+
import { Badge as c, Button as l, PageHeader as u, Section as d, SectionGroup as f, Tab as p, TabItem as m, Table as h, Typography as g } from "@mezzanine-ui/react";
|
|
9
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
10
|
+
import { listApprovalHistoryTasks as b, listInboxTasks as x, listTaskDecisions as S, readApprovalInstance as C, readApprovalInstanceCaseTitle as w } from "@rytass/bpm-core-client/workflow";
|
|
11
|
+
import T from "@mezzanine-ui/react/ContentHeader";
|
|
12
|
+
import { PlusIcon as E } from "@mezzanine-ui/icons";
|
|
13
13
|
//#region src/views/inbox/InboxView.tsx
|
|
14
|
-
function
|
|
15
|
-
let i = e(),
|
|
14
|
+
function D() {
|
|
15
|
+
let i = e(), S = r(), { member: C } = t(), w = C?.memberId ?? null, [D, A] = s("pending"), [j, M] = s(null), [N, P] = s([]), [I, R] = s(!0), [B, V] = s([]);
|
|
16
16
|
a(() => {
|
|
17
|
-
|
|
18
|
-
}, [
|
|
19
|
-
let
|
|
17
|
+
w && Y();
|
|
18
|
+
}, [w]);
|
|
19
|
+
let H = o(() => [
|
|
20
20
|
{
|
|
21
21
|
dataIndex: "caseTitle",
|
|
22
22
|
key: "caseTitle",
|
|
@@ -35,9 +35,19 @@ function E() {
|
|
|
35
35
|
title: "狀態",
|
|
36
36
|
width: 120
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
key: "fill",
|
|
40
|
+
render: (e) => e.hasFillableFields ? /* @__PURE__ */ v(c, {
|
|
41
|
+
size: "sub",
|
|
42
|
+
text: "需補填",
|
|
43
|
+
variant: "dot-warning"
|
|
44
|
+
}) : null,
|
|
45
|
+
title: "補填",
|
|
46
|
+
width: 120
|
|
47
|
+
},
|
|
38
48
|
{
|
|
39
49
|
key: "slaDueAt",
|
|
40
|
-
render: (e) => /* @__PURE__ */
|
|
50
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
41
51
|
color: e.slaStatusColor,
|
|
42
52
|
component: "span",
|
|
43
53
|
variant: "body",
|
|
@@ -48,7 +58,7 @@ function E() {
|
|
|
48
58
|
},
|
|
49
59
|
{
|
|
50
60
|
key: "createdAt",
|
|
51
|
-
render: (e) => /* @__PURE__ */
|
|
61
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
52
62
|
component: "span",
|
|
53
63
|
variant: "body",
|
|
54
64
|
children: n(e.createdAt)
|
|
@@ -56,14 +66,14 @@ function E() {
|
|
|
56
66
|
title: "建立時間",
|
|
57
67
|
width: 220
|
|
58
68
|
}
|
|
59
|
-
], []),
|
|
69
|
+
], []), U = o(() => ({
|
|
60
70
|
render: (e) => [{
|
|
61
71
|
name: "處理",
|
|
62
|
-
onClick: () => i.push(
|
|
72
|
+
onClick: () => i.push(S.caseDetail(e.instanceId))
|
|
63
73
|
}],
|
|
64
74
|
variant: "base-secondary",
|
|
65
75
|
width: 88
|
|
66
|
-
}), [i,
|
|
76
|
+
}), [i, S]), G = o(() => [
|
|
67
77
|
{
|
|
68
78
|
dataIndex: "caseTitle",
|
|
69
79
|
key: "caseTitle",
|
|
@@ -78,8 +88,8 @@ function E() {
|
|
|
78
88
|
},
|
|
79
89
|
{
|
|
80
90
|
key: "decisionLabel",
|
|
81
|
-
render: (e) => /* @__PURE__ */
|
|
82
|
-
color:
|
|
91
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
92
|
+
color: F(e.decisionAction),
|
|
83
93
|
component: "span",
|
|
84
94
|
variant: "body",
|
|
85
95
|
children: e.decisionLabel
|
|
@@ -89,7 +99,7 @@ function E() {
|
|
|
89
99
|
},
|
|
90
100
|
{
|
|
91
101
|
key: "decisionComment",
|
|
92
|
-
render: (e) => /* @__PURE__ */
|
|
102
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
93
103
|
component: "span",
|
|
94
104
|
variant: "body",
|
|
95
105
|
children: e.decisionCommentText
|
|
@@ -99,8 +109,8 @@ function E() {
|
|
|
99
109
|
},
|
|
100
110
|
{
|
|
101
111
|
key: "instanceStateLabel",
|
|
102
|
-
render: (e) => /* @__PURE__ */
|
|
103
|
-
color:
|
|
112
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
113
|
+
color: L(e.instanceState),
|
|
104
114
|
component: "span",
|
|
105
115
|
variant: "body",
|
|
106
116
|
children: e.instanceStateLabel
|
|
@@ -110,181 +120,181 @@ function E() {
|
|
|
110
120
|
},
|
|
111
121
|
{
|
|
112
122
|
key: "decidedAt",
|
|
113
|
-
render: (e) => /* @__PURE__ */
|
|
123
|
+
render: (e) => /* @__PURE__ */ v(g, {
|
|
114
124
|
component: "span",
|
|
115
125
|
variant: "body",
|
|
116
|
-
children:
|
|
126
|
+
children: z(e.decidedAt)
|
|
117
127
|
}),
|
|
118
128
|
title: "簽核時間",
|
|
119
129
|
width: 220
|
|
120
130
|
}
|
|
121
|
-
], []),
|
|
131
|
+
], []), K = o(() => ({
|
|
122
132
|
render: (e) => [{
|
|
123
133
|
name: "查看",
|
|
124
|
-
onClick: () => i.push(
|
|
134
|
+
onClick: () => i.push(S.caseDetail(e.instanceId))
|
|
125
135
|
}],
|
|
126
136
|
variant: "base-secondary",
|
|
127
137
|
width: 88
|
|
128
|
-
}), [i,
|
|
129
|
-
function
|
|
130
|
-
|
|
138
|
+
}), [i, S]), q = o(() => N.filter((e) => e.instanceState === "RUNNING"), [N]);
|
|
139
|
+
function J(e) {
|
|
140
|
+
A(e === "history" || e === "pending" || e === "tracking" ? e : "pending");
|
|
131
141
|
}
|
|
132
|
-
async function
|
|
133
|
-
|
|
142
|
+
async function Y() {
|
|
143
|
+
R(!0), M(null);
|
|
134
144
|
try {
|
|
135
|
-
if (!
|
|
136
|
-
|
|
145
|
+
if (!w) {
|
|
146
|
+
V([]), P([]);
|
|
137
147
|
return;
|
|
138
148
|
}
|
|
139
|
-
let [e, t] = await Promise.all([
|
|
140
|
-
|
|
149
|
+
let [e, t] = await Promise.all([x(w), b(w)]), [n, r] = await Promise.all([O(e), k(t)]);
|
|
150
|
+
V(n), P(r);
|
|
141
151
|
} catch (e) {
|
|
142
|
-
|
|
152
|
+
M(W(e));
|
|
143
153
|
} finally {
|
|
144
|
-
|
|
154
|
+
R(!1);
|
|
145
155
|
}
|
|
146
156
|
}
|
|
147
|
-
return /* @__PURE__ */
|
|
148
|
-
description: `目前以 ${
|
|
157
|
+
return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(u, { children: /* @__PURE__ */ v(T, {
|
|
158
|
+
description: `目前以 ${C?.name ?? w ?? "目前登入會員"} 查詢待處理與歷史簽核任務。`,
|
|
149
159
|
title: "我的待簽",
|
|
150
|
-
children: /* @__PURE__ */
|
|
151
|
-
icon:
|
|
160
|
+
children: /* @__PURE__ */ v(l, {
|
|
161
|
+
icon: E,
|
|
152
162
|
iconType: "leading",
|
|
153
|
-
onClick: () => i.push(
|
|
163
|
+
onClick: () => i.push(S.caseNew()),
|
|
154
164
|
variant: "base-primary",
|
|
155
165
|
children: "發起簽核"
|
|
156
166
|
})
|
|
157
|
-
}) }), /* @__PURE__ */
|
|
158
|
-
|
|
167
|
+
}) }), /* @__PURE__ */ v(f, { children: /* @__PURE__ */ y(d, { children: [
|
|
168
|
+
j ? /* @__PURE__ */ v(g, {
|
|
159
169
|
color: "text-error",
|
|
160
170
|
variant: "body",
|
|
161
|
-
children:
|
|
171
|
+
children: j
|
|
162
172
|
}) : null,
|
|
163
|
-
/* @__PURE__ */
|
|
164
|
-
activeKey:
|
|
165
|
-
onChange:
|
|
173
|
+
/* @__PURE__ */ y(p, {
|
|
174
|
+
activeKey: D,
|
|
175
|
+
onChange: J,
|
|
166
176
|
size: "sub",
|
|
167
177
|
children: [
|
|
168
|
-
/* @__PURE__ */
|
|
169
|
-
badgeCount:
|
|
178
|
+
/* @__PURE__ */ v(m, {
|
|
179
|
+
badgeCount: I ? void 0 : B.length,
|
|
170
180
|
children: "待簽核"
|
|
171
181
|
}, "pending"),
|
|
172
|
-
/* @__PURE__ */
|
|
173
|
-
badgeCount:
|
|
182
|
+
/* @__PURE__ */ v(m, {
|
|
183
|
+
badgeCount: I ? void 0 : q.length,
|
|
174
184
|
children: "已處理未結束"
|
|
175
185
|
}, "tracking"),
|
|
176
|
-
/* @__PURE__ */
|
|
186
|
+
/* @__PURE__ */ v(m, { children: "歷史簽核記錄" }, "history")
|
|
177
187
|
]
|
|
178
188
|
}),
|
|
179
|
-
|
|
180
|
-
actions:
|
|
181
|
-
columns:
|
|
182
|
-
dataSource:
|
|
189
|
+
D === "pending" ? /* @__PURE__ */ v(h, {
|
|
190
|
+
actions: U,
|
|
191
|
+
columns: H,
|
|
192
|
+
dataSource: B,
|
|
183
193
|
fullWidth: !0,
|
|
184
|
-
loading:
|
|
194
|
+
loading: I
|
|
185
195
|
}) : null,
|
|
186
|
-
|
|
187
|
-
actions:
|
|
188
|
-
columns:
|
|
189
|
-
dataSource:
|
|
196
|
+
D === "tracking" ? /* @__PURE__ */ v(h, {
|
|
197
|
+
actions: K,
|
|
198
|
+
columns: G,
|
|
199
|
+
dataSource: q,
|
|
190
200
|
fullWidth: !0,
|
|
191
|
-
loading:
|
|
201
|
+
loading: I
|
|
192
202
|
}) : null,
|
|
193
|
-
|
|
194
|
-
actions:
|
|
195
|
-
columns:
|
|
196
|
-
dataSource:
|
|
203
|
+
D === "history" ? /* @__PURE__ */ v(h, {
|
|
204
|
+
actions: K,
|
|
205
|
+
columns: G,
|
|
206
|
+
dataSource: N,
|
|
197
207
|
fullWidth: !0,
|
|
198
|
-
loading:
|
|
208
|
+
loading: I
|
|
199
209
|
}) : null
|
|
200
210
|
] }) })] });
|
|
201
211
|
}
|
|
202
|
-
async function
|
|
203
|
-
let t = await
|
|
212
|
+
async function O(e) {
|
|
213
|
+
let t = await A(e);
|
|
204
214
|
return e.map((e, n) => ({
|
|
205
215
|
...e,
|
|
206
|
-
caseTitle:
|
|
216
|
+
caseTitle: j(e, t[n] ?? null),
|
|
207
217
|
key: e.id,
|
|
208
218
|
nodeText: i(e),
|
|
209
|
-
slaStatusColor:
|
|
210
|
-
slaStatusText:
|
|
211
|
-
statusLabel:
|
|
219
|
+
slaStatusColor: V(e.slaDueAt),
|
|
220
|
+
slaStatusText: B(e.slaDueAt),
|
|
221
|
+
statusLabel: U(e.status)
|
|
212
222
|
}));
|
|
213
223
|
}
|
|
214
|
-
async function
|
|
215
|
-
let [t, n] = await Promise.all([Promise.all(e.map((e) =>
|
|
224
|
+
async function k(e) {
|
|
225
|
+
let [t, n] = await Promise.all([Promise.all(e.map((e) => S(e.id))), A(e)]);
|
|
216
226
|
return e.map((e, r) => {
|
|
217
|
-
let a =
|
|
227
|
+
let a = M(t[r] ?? []), o = n[r] ?? null;
|
|
218
228
|
return {
|
|
219
229
|
...e,
|
|
220
|
-
caseTitle:
|
|
230
|
+
caseTitle: j(e, o),
|
|
221
231
|
decisionAction: a?.action ?? null,
|
|
222
232
|
decisionComment: a?.comment ?? null,
|
|
223
|
-
decisionCommentText:
|
|
224
|
-
decisionLabel:
|
|
233
|
+
decisionCommentText: R(a?.comment ?? null),
|
|
234
|
+
decisionLabel: P(a?.action ?? null),
|
|
225
235
|
decidedAt: a?.decidedAt ?? e.completedAt,
|
|
226
236
|
instanceState: o?.state ?? null,
|
|
227
|
-
instanceStateLabel:
|
|
237
|
+
instanceStateLabel: I(o?.state ?? null),
|
|
228
238
|
key: e.id,
|
|
229
239
|
nodeText: i(e)
|
|
230
240
|
};
|
|
231
241
|
});
|
|
232
242
|
}
|
|
233
|
-
async function
|
|
243
|
+
async function A(e) {
|
|
234
244
|
return Promise.all(e.map(async (e) => {
|
|
235
245
|
try {
|
|
236
|
-
return (await
|
|
246
|
+
return (await C(e.instanceId)).instance;
|
|
237
247
|
} catch {
|
|
238
248
|
return null;
|
|
239
249
|
}
|
|
240
250
|
}));
|
|
241
251
|
}
|
|
242
|
-
function
|
|
243
|
-
return t ?
|
|
252
|
+
function j(e, t) {
|
|
253
|
+
return t ? w(t) : e.instanceId;
|
|
244
254
|
}
|
|
245
|
-
function
|
|
246
|
-
return [...e].sort(
|
|
255
|
+
function M(e) {
|
|
256
|
+
return [...e].sort(N)[0] ?? null;
|
|
247
257
|
}
|
|
248
|
-
function
|
|
258
|
+
function N(e, t) {
|
|
249
259
|
return new Date(t.decidedAt).getTime() - new Date(e.decidedAt).getTime();
|
|
250
260
|
}
|
|
251
|
-
function
|
|
261
|
+
function P(e) {
|
|
252
262
|
return e === "APPROVED" ? "同意" : e === "REJECTED" ? "拒絕" : e === "RETURNED" ? "退回" : e === "TRANSFERRED" ? "轉派" : "未記錄";
|
|
253
263
|
}
|
|
254
|
-
function
|
|
264
|
+
function F(e) {
|
|
255
265
|
return e === "APPROVED" ? "text-success" : e === "REJECTED" || e === "RETURNED" ? "text-error" : "text-neutral";
|
|
256
266
|
}
|
|
257
|
-
function
|
|
267
|
+
function I(e) {
|
|
258
268
|
return e === "RUNNING" ? "進行中" : e === "APPROVED" ? "已通過" : e === "REJECTED" ? "已拒絕" : e === "RETURNED" ? "已退回" : e === "CANCELLED" ? "已取消" : e === "EXPIRED" ? "已逾期" : e === "DRAFT" ? "草稿" : "-";
|
|
259
269
|
}
|
|
260
|
-
function
|
|
270
|
+
function L(e) {
|
|
261
271
|
return e === "APPROVED" ? "text-success" : e === "REJECTED" || e === "CANCELLED" || e === "EXPIRED" ? "text-error" : "text-neutral";
|
|
262
272
|
}
|
|
263
|
-
function
|
|
273
|
+
function R(e) {
|
|
264
274
|
return (e?.trim() ?? "") || "-";
|
|
265
275
|
}
|
|
266
|
-
function
|
|
276
|
+
function z(e) {
|
|
267
277
|
return n(e);
|
|
268
278
|
}
|
|
269
|
-
function
|
|
279
|
+
function B(e) {
|
|
270
280
|
if (!e) return "-";
|
|
271
|
-
let t = new Date(e).getTime(), n = Date.now(), r =
|
|
281
|
+
let t = new Date(e).getTime(), n = Date.now(), r = H(Math.abs(t - n));
|
|
272
282
|
return t < n ? `已逾期 ${r}` : `剩餘 ${r}`;
|
|
273
283
|
}
|
|
274
|
-
function
|
|
284
|
+
function V(e) {
|
|
275
285
|
return e ? new Date(e).getTime() < Date.now() ? "text-error" : "text-success" : "text-neutral";
|
|
276
286
|
}
|
|
277
|
-
function
|
|
287
|
+
function H(e) {
|
|
278
288
|
let t = Math.max(1, Math.ceil(e / 6e4)), n = Math.floor(t / 1440), r = Math.floor(t % 1440 / 60), i = t % 60;
|
|
279
289
|
return n > 0 ? `${n}天 ${r}小時` : r > 0 ? `${r}小時 ${i}分鐘` : `${i}分鐘`;
|
|
280
290
|
}
|
|
281
|
-
function
|
|
291
|
+
function U(e) {
|
|
282
292
|
return e === "PENDING" ? "待處理" : e === "IN_PROGRESS" ? "處理中" : e === "COMPLETED" ? "已完成" : e === "TRANSFERRED" ? "已轉派" : e === "CANCELLED" ? "已取消" : e;
|
|
283
293
|
}
|
|
284
|
-
function
|
|
294
|
+
function W(e) {
|
|
285
295
|
return e instanceof Error ? e.message : "發生未知錯誤";
|
|
286
296
|
}
|
|
287
297
|
//#endregion
|
|
288
|
-
export {
|
|
298
|
+
export { D as InboxView };
|
|
289
299
|
|
|
290
300
|
//# sourceMappingURL=index.js.map
|