@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readTaskNodeText","Fragment$1","ContentHeader","InboxView","router","routes","useBPMRoutes","currentMemberId","member","activeTab","setActiveTab","useState","error","setError","historyRows","setHistoryRows","loading","setLoading","pendingRows","setPendingRows","refreshTasks","pendingColumns","useMemo","Typography","record","pendingTableActions","historyColumns","readTaskDecisionColor","readInstanceStateColor","formatHistoryDateTime","historyTableActions","trackingRows","row","handleTabChange","activeKey","nextPendingTasks","nextHistoryTasks","listInboxTasks","listApprovalHistoryTasks","nextPendingRows","nextHistoryRows","readInboxTaskRows","readApprovalHistoryRows","requestError","readErrorMessage","PageHeader","Button","PlusIcon","SectionGroup","Section","Tab","TabItem","Table","instances","readTaskInstances","tasks","task","readTaskCaseTitle","index","readSlaStatusColor","readSlaStatusText","readTaskStatusLabel","decisionLists","listTaskDecisions","decision","readLatestTaskDecision","instance","readDecisionCommentText","readTaskDecisionLabel","readInstanceStateLabel","readApprovalInstance","readApprovalInstanceCaseTitle","decisions","compareTaskDecisionDesc","right","left","action","state","comment","value","dueAt","now","label","formatDuration","totalMinutes","days","hours","minutes","status"],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n 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.js","names":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readTaskNodeText","Fragment$1","ContentHeader","InboxView","router","routes","useBPMRoutes","currentMemberId","member","activeTab","setActiveTab","useState","error","setError","historyRows","setHistoryRows","loading","setLoading","pendingRows","setPendingRows","refreshTasks","pendingColumns","useMemo","record","Badge","Typography","pendingTableActions","historyColumns","readTaskDecisionColor","readInstanceStateColor","formatHistoryDateTime","historyTableActions","trackingRows","row","handleTabChange","activeKey","nextPendingTasks","nextHistoryTasks","listInboxTasks","listApprovalHistoryTasks","nextPendingRows","nextHistoryRows","readInboxTaskRows","readApprovalHistoryRows","requestError","readErrorMessage","PageHeader","Button","PlusIcon","SectionGroup","Section","Tab","TabItem","Table","instances","readTaskInstances","tasks","task","readTaskCaseTitle","index","readSlaStatusColor","readSlaStatusText","readTaskStatusLabel","decisionLists","listTaskDecisions","decision","readLatestTaskDecision","instance","readDecisionCommentText","readTaskDecisionLabel","readInstanceStateLabel","readApprovalInstance","readApprovalInstanceCaseTitle","decisions","compareTaskDecisionDesc","right","left","action","state","comment","value","dueAt","now","label","formatDuration","totalMinutes","days","hours","minutes","status"],"sources":["../../../src/views/inbox/InboxView.tsx"],"sourcesContent":["'use client';\n\nimport { type Key, ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n ApprovalInstanceRecord,\n listApprovalHistoryTasks,\n listInboxTasks,\n listTaskDecisions,\n readApprovalInstance,\n readApprovalInstanceCaseTitle,\n TaskDecisionRecord,\n TaskRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useAuth } from '../../lib/auth-provider';\nimport { readTaskNodeText } from '../../lib/task-node-label';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\n\ntype InboxTabKey = 'history' | 'pending' | 'tracking';\n\ntype InboxTaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n key: string;\n nodeText: string;\n slaStatusColor: 'text-error' | 'text-neutral' | 'text-success';\n slaStatusText: string;\n statusLabel: string;\n }\n>;\n\ntype ApprovalHistoryRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n caseTitle: string;\n decisionAction: TaskDecisionRecord['action'] | null;\n decisionComment: string | null;\n decisionCommentText: string;\n decisionLabel: string;\n decidedAt: string | null;\n instanceState: ApprovalInstanceRecord['state'] | null;\n instanceStateLabel: string;\n key: string;\n nodeText: string;\n }\n>;\n\n\n/**\n * Framework-agnostic view for the BPM \"我的待簽\" inbox. Mechanical port of\n * `apps/client/src/app/inbox/page.tsx` — renders pending tasks, tracking,\n * and history tabs.\n */\nexport function InboxView(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activeTab, setActiveTab] = useState<InboxTabKey>('pending');\n const [error, setError] = useState<string | null>(null);\n const [historyRows, setHistoryRows] = useState<ApprovalHistoryRow[]>([]);\n const [loading, setLoading] = useState(true);\n const [pendingRows, setPendingRows] = useState<InboxTaskRow[]>([]);\n\n useEffect((): void => {\n if (!currentMemberId) {\n return;\n }\n\n void refreshTasks();\n }, [currentMemberId]);\n\n const pendingColumns = useMemo(\n (): TableColumn<InboxTaskRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'fill',\n // Approving one of these needs the case page, where the fill is entered.\n render: (record: InboxTaskRow): ReactElement | null =>\n record.hasFillableFields ? (\n <Badge size=\"sub\" text=\"需補填\" variant=\"dot-warning\" />\n ) : null,\n title: '補填',\n width: 120,\n },\n {\n key: 'slaDueAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography\n color={record.slaStatusColor}\n component=\"span\"\n variant=\"body\"\n >\n {record.slaStatusText}\n </Typography>\n ),\n title: 'SLA',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: InboxTaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n const pendingTableActions = useMemo(\n (): TableActions<InboxTaskRow> => ({\n render: (record): ReturnType<TableActions<InboxTaskRow>['render']> => [\n {\n name: '處理',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const historyColumns = useMemo(\n (): TableColumn<ApprovalHistoryRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 280 },\n { dataIndex: 'nodeText', key: 'nodeText', title: '節點', width: 180 },\n {\n key: 'decisionLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readTaskDecisionColor(record.decisionAction)}\n component=\"span\"\n variant=\"body\"\n >\n {record.decisionLabel}\n </Typography>\n ),\n title: '決議',\n width: 120,\n },\n {\n key: 'decisionComment',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.decisionCommentText}\n </Typography>\n ),\n title: '意見',\n width: 240,\n },\n {\n key: 'instanceStateLabel',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.instanceState)}\n component=\"span\"\n variant=\"body\"\n >\n {record.instanceStateLabel}\n </Typography>\n ),\n title: '流程狀態',\n width: 140,\n },\n {\n key: 'decidedAt',\n render: (record: ApprovalHistoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatHistoryDateTime(record.decidedAt)}\n </Typography>\n ),\n title: '簽核時間',\n width: 220,\n },\n ],\n [],\n );\n const historyTableActions = useMemo(\n (): TableActions<ApprovalHistoryRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalHistoryRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.instanceId)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router, routes],\n );\n const trackingRows = useMemo(\n (): ApprovalHistoryRow[] =>\n historyRows.filter((row) => row.instanceState === 'RUNNING'),\n [historyRows],\n );\n\n function handleTabChange(activeKey: Key): void {\n if (\n activeKey === 'history' ||\n activeKey === 'pending' ||\n activeKey === 'tracking'\n ) {\n setActiveTab(activeKey);\n return;\n }\n\n setActiveTab('pending');\n }\n\n async function refreshTasks(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n if (!currentMemberId) {\n setPendingRows([]);\n setHistoryRows([]);\n return;\n }\n\n const [nextPendingTasks, nextHistoryTasks] = await Promise.all([\n listInboxTasks(currentMemberId),\n listApprovalHistoryTasks(currentMemberId),\n ]);\n const [nextPendingRows, nextHistoryRows] = await Promise.all([\n readInboxTaskRows(nextPendingTasks),\n readApprovalHistoryRows(nextHistoryTasks),\n ]);\n\n setPendingRows(nextPendingRows);\n setHistoryRows(nextHistoryRows);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={`目前以 ${member?.name ?? currentMemberId ?? '目前登入會員'} 查詢待處理與歷史簽核任務。`}\n title=\"我的待簽\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Tab activeKey={activeTab} onChange={handleTabChange} size=\"sub\">\n <TabItem\n badgeCount={loading ? undefined : pendingRows.length}\n key=\"pending\"\n >\n 待簽核\n </TabItem>\n <TabItem\n badgeCount={loading ? undefined : trackingRows.length}\n key=\"tracking\"\n >\n 已處理未結束\n </TabItem>\n <TabItem key=\"history\">歷史簽核記錄</TabItem>\n </Tab>\n\n {activeTab === 'pending' ? (\n <Table\n actions={pendingTableActions}\n columns={pendingColumns}\n dataSource={pendingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'tracking' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={trackingRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n {activeTab === 'history' ? (\n <Table\n actions={historyTableActions}\n columns={historyColumns}\n dataSource={historyRows}\n fullWidth\n loading={loading}\n />\n ) : null}\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nasync function readInboxTaskRows(\n tasks: readonly TaskRecord[],\n): Promise<InboxTaskRow[]> {\n const instances = await readTaskInstances(tasks);\n\n return tasks.map(\n (task, index): InboxTaskRow => ({\n ...task,\n caseTitle: readTaskCaseTitle(task, instances[index] ?? null),\n key: task.id,\n nodeText: readTaskNodeText(task),\n slaStatusColor: readSlaStatusColor(task.slaDueAt),\n slaStatusText: readSlaStatusText(task.slaDueAt),\n statusLabel: readTaskStatusLabel(task.status),\n }),\n );\n}\n\nasync function readApprovalHistoryRows(\n tasks: readonly TaskRecord[],\n): Promise<ApprovalHistoryRow[]> {\n const [decisionLists, instances] = await Promise.all([\n Promise.all(tasks.map((task) => listTaskDecisions(task.id))),\n readTaskInstances(tasks),\n ]);\n\n return tasks.map((task, index): ApprovalHistoryRow => {\n const decision = readLatestTaskDecision(decisionLists[index] ?? []);\n const instance = instances[index] ?? null;\n\n return {\n ...task,\n caseTitle: readTaskCaseTitle(task, instance),\n decisionAction: decision?.action ?? null,\n decisionComment: decision?.comment ?? null,\n decisionCommentText: readDecisionCommentText(decision?.comment ?? null),\n decisionLabel: readTaskDecisionLabel(decision?.action ?? null),\n decidedAt: decision?.decidedAt ?? task.completedAt,\n instanceState: instance?.state ?? null,\n instanceStateLabel: readInstanceStateLabel(instance?.state ?? null),\n key: task.id,\n nodeText: readTaskNodeText(task),\n };\n });\n}\n\nasync function readTaskInstances(\n tasks: readonly TaskRecord[],\n): Promise<readonly (ApprovalInstanceRecord | null)[]> {\n return Promise.all(\n tasks.map(async (task): Promise<ApprovalInstanceRecord | null> => {\n try {\n return (await readApprovalInstance(task.instanceId)).instance;\n } catch {\n return null;\n }\n }),\n );\n}\n\nfunction readTaskCaseTitle(\n task: TaskRecord,\n instance: ApprovalInstanceRecord | null,\n): string {\n return instance ? readApprovalInstanceCaseTitle(instance) : task.instanceId;\n}\n\nfunction readLatestTaskDecision(\n decisions: readonly TaskDecisionRecord[],\n): TaskDecisionRecord | null {\n return [...decisions].sort(compareTaskDecisionDesc)[0] ?? null;\n}\n\nfunction compareTaskDecisionDesc(\n left: TaskDecisionRecord,\n right: TaskDecisionRecord,\n): number {\n return (\n new Date(right.decidedAt).getTime() - new Date(left.decidedAt).getTime()\n );\n}\n\nfunction readTaskDecisionLabel(\n action: TaskDecisionRecord['action'] | null,\n): string {\n if (action === 'APPROVED') {\n return '同意';\n }\n\n if (action === 'REJECTED') {\n return '拒絕';\n }\n\n if (action === 'RETURNED') {\n return '退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '轉派';\n }\n\n return '未記錄';\n}\n\nfunction readTaskDecisionColor(\n action: TaskDecisionRecord['action'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (action === 'APPROVED') {\n return 'text-success';\n }\n\n if (action === 'REJECTED' || action === 'RETURNED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readInstanceStateLabel(\n state: ApprovalInstanceRecord['state'] | null,\n): string {\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n if (state === 'APPROVED') {\n return '已通過';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n return '-';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceRecord['state'] | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') {\n return 'text-success';\n }\n\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n\n return 'text-neutral';\n}\n\nfunction readDecisionCommentText(comment: string | null): string {\n const trimmedComment = comment?.trim() ?? '';\n\n return trimmedComment || '-';\n}\n\nfunction formatHistoryDateTime(value: string | null): string {\n return formatDateTime(value);\n}\n\nfunction readSlaStatusText(value: string | null): string {\n if (!value) {\n return '-';\n }\n\n const dueAt = new Date(value).getTime();\n const now = Date.now();\n const diffMs = Math.abs(dueAt - now);\n const label = formatDuration(diffMs);\n\n return dueAt < now ? `已逾期 ${label}` : `剩餘 ${label}`;\n}\n\nfunction readSlaStatusColor(\n value: string | null,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (!value) {\n return 'text-neutral';\n }\n\n return new Date(value).getTime() < Date.now() ? 'text-error' : 'text-success';\n}\n\nfunction formatDuration(value: number): string {\n const totalMinutes = Math.max(1, Math.ceil(value / 60_000));\n const days = Math.floor(totalMinutes / 1440);\n const hours = Math.floor((totalMinutes % 1440) / 60);\n const minutes = totalMinutes % 60;\n\n if (days > 0) {\n return `${days}天 ${hours}小時`;\n }\n\n if (hours > 0) {\n return `${hours}小時 ${minutes}分鐘`;\n }\n\n return `${minutes}分鐘`;\n}\n\nfunction readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') {\n return '待處理';\n }\n\n if (status === 'IN_PROGRESS') {\n return '處理中';\n }\n\n if (status === 'COMPLETED') {\n return '已完成';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n if (status === 'CANCELLED') {\n return '已取消';\n }\n\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { UserTaskNode, WorkflowDefinition } from '@rytass/bpm-core-shared';
|
|
2
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
3
|
+
import { WorkflowFormData } from '@rytass/bpm-core-client/workflow';
|
|
4
|
+
/**
|
|
5
|
+
* The form as the applicant sees it: without the fields some approver fills in.
|
|
6
|
+
* The server drops those keys from a submission, so rendering one would swallow
|
|
7
|
+
* what the applicant types, and a `minRows` or `required` on it would block a
|
|
8
|
+
* launch nobody can complete. Returns an equal schema when nothing is
|
|
9
|
+
* approver-filled; never mutates its input.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readApplicantFormSchema(schema: FormDefinitionSchema, definition: WorkflowDefinition): FormDefinitionSchema;
|
|
12
|
+
/** The payload the applicant may send: `values` without approver-filled keys. */
|
|
13
|
+
export declare function readApplicantSubmission(values: WorkflowFormData, definition: WorkflowDefinition): WorkflowFormData;
|
|
14
|
+
/**
|
|
15
|
+
* The form an approver's fill is validated against: only the fields `node`
|
|
16
|
+
* lets them fill in, each required exactly when the node says `REQUIRED`. A
|
|
17
|
+
* required table needs at least one row, the rule `validateFormRendererValues`
|
|
18
|
+
* already applies, so the result agrees with the server's fill check. Never
|
|
19
|
+
* mutates its input.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readFillValidationSchema(schema: FormDefinitionSchema, node: UserTaskNode): FormDefinitionSchema;
|
|
22
|
+
/**
|
|
23
|
+
* The schema the fill node's approver sees: every field as the form defines
|
|
24
|
+
* it, except that the node's fillable fields are required exactly when the
|
|
25
|
+
* node says `REQUIRED`, so the asterisk matches what approving will check.
|
|
26
|
+
*/
|
|
27
|
+
export declare function readFillDisplaySchema(schema: FormDefinitionSchema, node: UserTaskNode): FormDefinitionSchema;
|
|
28
|
+
/**
|
|
29
|
+
* The marker shown after each approver-filled field's label: 「本關補填」 on
|
|
30
|
+
* the fields `viewerFillNode` lets the viewer fill, 「<node>補填」 on every
|
|
31
|
+
* other approver-filled field (the first node in the definition that fills
|
|
32
|
+
* it names it).
|
|
33
|
+
*/
|
|
34
|
+
export declare function readFillLabelMarkers(definition: WorkflowDefinition, viewerFillNode: UserTaskNode | null): Readonly<Record<string, string>>;
|
|
35
|
+
/**
|
|
36
|
+
* What approving sends as `fill.formData`: the keys of `values` that `node`
|
|
37
|
+
* lets its approver fill, and nothing else (the server refuses any other key).
|
|
38
|
+
* `values` is what the approver changed, not the rendered form — a renderer
|
|
39
|
+
* default the approver never touched (a table's empty rows, a boolean's
|
|
40
|
+
* `false`) is not theirs to sign, and would otherwise show up as filled in.
|
|
41
|
+
*/
|
|
42
|
+
export declare function readFillPayload(values: WorkflowFormData, node: UserTaskNode): Readonly<Record<string, unknown>>;
|
|
43
|
+
/**
|
|
44
|
+
* What the approver's fill amounts to: the fields they changed (`draft`), plus
|
|
45
|
+
* each fill table the page seeds with `minRows` rows that the case does not
|
|
46
|
+
* store yet. The page shows those rows and validates them, so they are sent
|
|
47
|
+
* too — left out, the server would refuse the approval for missing rows the
|
|
48
|
+
* approver can see on screen.
|
|
49
|
+
*/
|
|
50
|
+
export declare function readFillChanges({ draft, node, schema, stored, values, }: {
|
|
51
|
+
readonly draft: WorkflowFormData;
|
|
52
|
+
readonly node: UserTaskNode;
|
|
53
|
+
readonly schema: FormDefinitionSchema;
|
|
54
|
+
readonly stored: WorkflowFormData;
|
|
55
|
+
readonly values: WorkflowFormData;
|
|
56
|
+
}): WorkflowFormData;
|
|
57
|
+
/** The server message of a fill against form data someone else changed. */
|
|
58
|
+
export declare function isFillConflictMessage(message: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Turns the server's fill validation message (docs/08 §8.5, error table 2)
|
|
61
|
+
* into field errors keyed the way `FormRenderer` addresses them, so a check
|
|
62
|
+
* the page missed still lands on the field. `null` when any part does not
|
|
63
|
+
* parse — the caller then shows the message as it is.
|
|
64
|
+
*/
|
|
65
|
+
export declare function readFillServerErrors(message: string, schema: FormDefinitionSchema, node: UserTaskNode): Readonly<Record<string, string>> | null;
|
|
66
|
+
export interface FillSummaryItem {
|
|
67
|
+
readonly fieldKey: string;
|
|
68
|
+
readonly label: string;
|
|
69
|
+
readonly text: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* One line per field `node` lets its approver fill, in form order, for the
|
|
73
|
+
* approve dialog: what will be sent along with the approval. A member field
|
|
74
|
+
* names each member found in `memberNames` and shows the id otherwise.
|
|
75
|
+
*/
|
|
76
|
+
export declare function readFillSummary(schema: FormDefinitionSchema, node: UserTaskNode, values: WorkflowFormData, memberNames?: ReadonlyMap<string, string>): readonly FillSummaryItem[];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { UserTaskNode, WorkflowDefinition } from '@rytass/bpm-core-shared';
|
|
2
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
3
|
+
import { WorkflowFormData } from '@rytass/bpm-core-client/workflow';
|
|
4
|
+
/**
|
|
5
|
+
* The form as the applicant sees it: without the fields some approver fills in.
|
|
6
|
+
* The server drops those keys from a submission, so rendering one would swallow
|
|
7
|
+
* what the applicant types, and a `minRows` or `required` on it would block a
|
|
8
|
+
* launch nobody can complete. Returns an equal schema when nothing is
|
|
9
|
+
* approver-filled; never mutates its input.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readApplicantFormSchema(schema: FormDefinitionSchema, definition: WorkflowDefinition): FormDefinitionSchema;
|
|
12
|
+
/** The payload the applicant may send: `values` without approver-filled keys. */
|
|
13
|
+
export declare function readApplicantSubmission(values: WorkflowFormData, definition: WorkflowDefinition): WorkflowFormData;
|
|
14
|
+
/**
|
|
15
|
+
* The form an approver's fill is validated against: only the fields `node`
|
|
16
|
+
* lets them fill in, each required exactly when the node says `REQUIRED`. A
|
|
17
|
+
* required table needs at least one row, the rule `validateFormRendererValues`
|
|
18
|
+
* already applies, so the result agrees with the server's fill check. Never
|
|
19
|
+
* mutates its input.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readFillValidationSchema(schema: FormDefinitionSchema, node: UserTaskNode): FormDefinitionSchema;
|
|
22
|
+
/**
|
|
23
|
+
* The schema the fill node's approver sees: every field as the form defines
|
|
24
|
+
* it, except that the node's fillable fields are required exactly when the
|
|
25
|
+
* node says `REQUIRED`, so the asterisk matches what approving will check.
|
|
26
|
+
*/
|
|
27
|
+
export declare function readFillDisplaySchema(schema: FormDefinitionSchema, node: UserTaskNode): FormDefinitionSchema;
|
|
28
|
+
/**
|
|
29
|
+
* The marker shown after each approver-filled field's label: 「本關補填」 on
|
|
30
|
+
* the fields `viewerFillNode` lets the viewer fill, 「<node>補填」 on every
|
|
31
|
+
* other approver-filled field (the first node in the definition that fills
|
|
32
|
+
* it names it).
|
|
33
|
+
*/
|
|
34
|
+
export declare function readFillLabelMarkers(definition: WorkflowDefinition, viewerFillNode: UserTaskNode | null): Readonly<Record<string, string>>;
|
|
35
|
+
/**
|
|
36
|
+
* What approving sends as `fill.formData`: the keys of `values` that `node`
|
|
37
|
+
* lets its approver fill, and nothing else (the server refuses any other key).
|
|
38
|
+
* `values` is what the approver changed, not the rendered form — a renderer
|
|
39
|
+
* default the approver never touched (a table's empty rows, a boolean's
|
|
40
|
+
* `false`) is not theirs to sign, and would otherwise show up as filled in.
|
|
41
|
+
*/
|
|
42
|
+
export declare function readFillPayload(values: WorkflowFormData, node: UserTaskNode): Readonly<Record<string, unknown>>;
|
|
43
|
+
/**
|
|
44
|
+
* What the approver's fill amounts to: the fields they changed (`draft`), plus
|
|
45
|
+
* each fill table the page seeds with `minRows` rows that the case does not
|
|
46
|
+
* store yet. The page shows those rows and validates them, so they are sent
|
|
47
|
+
* too — left out, the server would refuse the approval for missing rows the
|
|
48
|
+
* approver can see on screen.
|
|
49
|
+
*/
|
|
50
|
+
export declare function readFillChanges({ draft, node, schema, stored, values, }: {
|
|
51
|
+
readonly draft: WorkflowFormData;
|
|
52
|
+
readonly node: UserTaskNode;
|
|
53
|
+
readonly schema: FormDefinitionSchema;
|
|
54
|
+
readonly stored: WorkflowFormData;
|
|
55
|
+
readonly values: WorkflowFormData;
|
|
56
|
+
}): WorkflowFormData;
|
|
57
|
+
/** The server message of a fill against form data someone else changed. */
|
|
58
|
+
export declare function isFillConflictMessage(message: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Turns the server's fill validation message (docs/08 §8.5, error table 2)
|
|
61
|
+
* into field errors keyed the way `FormRenderer` addresses them, so a check
|
|
62
|
+
* the page missed still lands on the field. `null` when any part does not
|
|
63
|
+
* parse — the caller then shows the message as it is.
|
|
64
|
+
*/
|
|
65
|
+
export declare function readFillServerErrors(message: string, schema: FormDefinitionSchema, node: UserTaskNode): Readonly<Record<string, string>> | null;
|
|
66
|
+
export interface FillSummaryItem {
|
|
67
|
+
readonly fieldKey: string;
|
|
68
|
+
readonly label: string;
|
|
69
|
+
readonly text: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* One line per field `node` lets its approver fill, in form order, for the
|
|
73
|
+
* approve dialog: what will be sent along with the approval. A member field
|
|
74
|
+
* names each member found in `memberNames` and shows the id otherwise.
|
|
75
|
+
*/
|
|
76
|
+
export declare function readFillSummary(schema: FormDefinitionSchema, node: UserTaskNode, values: WorkflowFormData, memberNames?: ReadonlyMap<string, string>): readonly FillSummaryItem[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-D49NuNCn.cjs");exports.InstanceAttachmentsSection=e.o,exports.InstanceDetailView=e.t,exports.InstanceFormSection=e.s,exports.InstanceHistorySection=e.r,exports.InstanceSignaturesSection=e.i,exports.InstanceTasksSection=e.a,exports.InstanceWebhookDeliveriesSection=e.n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { o as InstanceAttachmentsSection, t as InstanceDetailView, s as InstanceFormSection, r as InstanceHistorySection, i as InstanceSignaturesSection, a as InstanceTasksSection, n as InstanceWebhookDeliveriesSection } from "../../../chunks/detail-
|
|
1
|
+
export { o as InstanceAttachmentsSection, t as InstanceDetailView, s as InstanceFormSection, r as InstanceHistorySection, i as InstanceSignaturesSection, a as InstanceTasksSection, n as InstanceWebhookDeliveriesSection } from "../../../chunks/detail-URwxkcro.js";
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedFieldAccess } from '@rytass/bpm-core-shared';
|
|
3
|
+
import { FormDefinitionSchema, FormFieldDefinition } from '@rytass/bpm-core-shared/form';
|
|
3
4
|
import { ApprovalInstanceRecord, WorkflowFormData } from '@rytass/bpm-core-client/workflow';
|
|
4
5
|
import { FormDataSourceFieldState } from '../../../forms/renderer/form-data-source-field.cjs';
|
|
6
|
+
/** The fill state of the viewer's own task at a node that fills in fields. */
|
|
7
|
+
export interface InstanceFormSectionFill {
|
|
8
|
+
/** Field errors from the page's check or the server's, keyed by path. */
|
|
9
|
+
readonly errors: Readonly<Record<string, string>>;
|
|
10
|
+
/** How many fields this node lets the viewer fill in. */
|
|
11
|
+
readonly fieldCount: number;
|
|
12
|
+
/** Called with the whole form value whenever a fill field changes. */
|
|
13
|
+
readonly onChange: (values: WorkflowFormData) => void;
|
|
14
|
+
/** The form as this approver sees it (fill fields required per node). */
|
|
15
|
+
readonly schema: FormDefinitionSchema;
|
|
16
|
+
/** The stored form data with the draft fill on top. */
|
|
17
|
+
readonly value: WorkflowFormData;
|
|
18
|
+
}
|
|
5
19
|
export interface InstanceFormSectionProps {
|
|
20
|
+
/**
|
|
21
|
+
* What the viewer may see and edit per field (`readViewerFieldAccess`).
|
|
22
|
+
* Ignored while the applicant edits a returned instance.
|
|
23
|
+
*/
|
|
24
|
+
readonly fieldAccess?: Readonly<Record<string, ResolvedFieldAccess>>;
|
|
25
|
+
/** Marker after each approver-filled field's label (`readFillLabelMarkers`). */
|
|
26
|
+
readonly fieldLabelMarkers?: Readonly<Record<string, string>>;
|
|
27
|
+
/** Present when the viewer's task fills in fields; edits go through it. */
|
|
28
|
+
readonly fill?: InstanceFormSectionFill | null;
|
|
29
|
+
/**
|
|
30
|
+
* Present after approving failed because the form changed meanwhile; the
|
|
31
|
+
* draft fill is kept and re-applied after reloading.
|
|
32
|
+
*/
|
|
33
|
+
readonly onReloadAfterConflict?: (() => void) | null;
|
|
6
34
|
/** The loaded approval instance, or null while loading. */
|
|
7
35
|
readonly instance: ApprovalInstanceRecord | null;
|
|
8
36
|
/** Whether the instance is in a loading state. */
|
|
@@ -33,4 +61,4 @@ export interface InstanceFormSectionProps {
|
|
|
33
61
|
* Displays the form in read-only mode normally, or editable mode when the
|
|
34
62
|
* instance has been returned and the current member can resubmit it.
|
|
35
63
|
*/
|
|
36
|
-
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, instance, loading, onDataSourceStateChange, onResubmitFormChange, onResubmitInstance, onUploadAttachment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
64
|
+
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, fieldAccess, fieldLabelMarkers, fill, instance, loading, onDataSourceStateChange, onResubmitFormChange, onReloadAfterConflict, onResubmitInstance, onUploadAttachment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ResolvedFieldAccess } from '@rytass/bpm-core-shared';
|
|
3
|
+
import { FormDefinitionSchema, FormFieldDefinition } from '@rytass/bpm-core-shared/form';
|
|
3
4
|
import { ApprovalInstanceRecord, WorkflowFormData } from '@rytass/bpm-core-client/workflow';
|
|
4
5
|
import { FormDataSourceFieldState } from '../../../forms/renderer/form-data-source-field.js';
|
|
6
|
+
/** The fill state of the viewer's own task at a node that fills in fields. */
|
|
7
|
+
export interface InstanceFormSectionFill {
|
|
8
|
+
/** Field errors from the page's check or the server's, keyed by path. */
|
|
9
|
+
readonly errors: Readonly<Record<string, string>>;
|
|
10
|
+
/** How many fields this node lets the viewer fill in. */
|
|
11
|
+
readonly fieldCount: number;
|
|
12
|
+
/** Called with the whole form value whenever a fill field changes. */
|
|
13
|
+
readonly onChange: (values: WorkflowFormData) => void;
|
|
14
|
+
/** The form as this approver sees it (fill fields required per node). */
|
|
15
|
+
readonly schema: FormDefinitionSchema;
|
|
16
|
+
/** The stored form data with the draft fill on top. */
|
|
17
|
+
readonly value: WorkflowFormData;
|
|
18
|
+
}
|
|
5
19
|
export interface InstanceFormSectionProps {
|
|
20
|
+
/**
|
|
21
|
+
* What the viewer may see and edit per field (`readViewerFieldAccess`).
|
|
22
|
+
* Ignored while the applicant edits a returned instance.
|
|
23
|
+
*/
|
|
24
|
+
readonly fieldAccess?: Readonly<Record<string, ResolvedFieldAccess>>;
|
|
25
|
+
/** Marker after each approver-filled field's label (`readFillLabelMarkers`). */
|
|
26
|
+
readonly fieldLabelMarkers?: Readonly<Record<string, string>>;
|
|
27
|
+
/** Present when the viewer's task fills in fields; edits go through it. */
|
|
28
|
+
readonly fill?: InstanceFormSectionFill | null;
|
|
29
|
+
/**
|
|
30
|
+
* Present after approving failed because the form changed meanwhile; the
|
|
31
|
+
* draft fill is kept and re-applied after reloading.
|
|
32
|
+
*/
|
|
33
|
+
readonly onReloadAfterConflict?: (() => void) | null;
|
|
6
34
|
/** The loaded approval instance, or null while loading. */
|
|
7
35
|
readonly instance: ApprovalInstanceRecord | null;
|
|
8
36
|
/** Whether the instance is in a loading state. */
|
|
@@ -33,4 +61,4 @@ export interface InstanceFormSectionProps {
|
|
|
33
61
|
* Displays the form in read-only mode normally, or editable mode when the
|
|
34
62
|
* instance has been returned and the current member can resubmit it.
|
|
35
63
|
*/
|
|
36
|
-
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, instance, loading, onDataSourceStateChange, onResubmitFormChange, onResubmitInstance, onUploadAttachment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
64
|
+
export declare function InstanceFormSection({ canResubmitInstance, deciding, error, fieldAccess, fieldLabelMarkers, fill, instance, loading, onDataSourceStateChange, onResubmitFormChange, onReloadAfterConflict, onResubmitInstance, onUploadAttachment, resubmitFormData, resubmitFormErrors, }: InstanceFormSectionProps): ReactElement;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
1
2
|
import { ReactElement } from 'react';
|
|
2
3
|
import { ActivityLogRecord, ApprovalInstanceRecord, MemberProfileRecord, SignatureRecord, SignatureVerificationRecord, TaskDecisionRecord, TaskRecord, WorkflowTokenRecord } from '@rytass/bpm-core-client/workflow';
|
|
3
4
|
import { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';
|
|
@@ -10,6 +11,8 @@ export interface InstanceHistorySectionProps {
|
|
|
10
11
|
readonly workflowTokens: readonly WorkflowTokenRecord[];
|
|
11
12
|
/** The workflow definition snapshot, or null if not yet loaded. */
|
|
12
13
|
readonly workflowSnapshot: WorkflowDefinition | null;
|
|
14
|
+
/** The instance's form schema, to name the fields an approval filled in. */
|
|
15
|
+
readonly formSchema?: FormDefinitionSchema | null;
|
|
13
16
|
/** The current state of the instance. */
|
|
14
17
|
readonly instanceState: ApprovalInstanceRecord['state'];
|
|
15
18
|
/** Member profiles indexed by memberId. */
|
|
@@ -26,4 +29,4 @@ export interface InstanceHistorySectionProps {
|
|
|
26
29
|
* Computes the step records from the provided data and renders them as a
|
|
27
30
|
* vertical dot stepper.
|
|
28
31
|
*/
|
|
29
|
-
export declare function InstanceHistorySection({ activityLogs, instanceState, memberProfilesById, signatureVerification, signaturesById, taskDecisionsByTaskId, tasks, workflowSnapshot, workflowTokens, }: InstanceHistorySectionProps): ReactElement;
|
|
32
|
+
export declare function InstanceHistorySection({ activityLogs, formSchema, instanceState, memberProfilesById, signatureVerification, signaturesById, taskDecisionsByTaskId, tasks, workflowSnapshot, workflowTokens, }: InstanceHistorySectionProps): ReactElement;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
1
2
|
import { ReactElement } from 'react';
|
|
2
3
|
import { ActivityLogRecord, ApprovalInstanceRecord, MemberProfileRecord, SignatureRecord, SignatureVerificationRecord, TaskDecisionRecord, TaskRecord, WorkflowTokenRecord } from '@rytass/bpm-core-client/workflow';
|
|
3
4
|
import { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';
|
|
@@ -10,6 +11,8 @@ export interface InstanceHistorySectionProps {
|
|
|
10
11
|
readonly workflowTokens: readonly WorkflowTokenRecord[];
|
|
11
12
|
/** The workflow definition snapshot, or null if not yet loaded. */
|
|
12
13
|
readonly workflowSnapshot: WorkflowDefinition | null;
|
|
14
|
+
/** The instance's form schema, to name the fields an approval filled in. */
|
|
15
|
+
readonly formSchema?: FormDefinitionSchema | null;
|
|
13
16
|
/** The current state of the instance. */
|
|
14
17
|
readonly instanceState: ApprovalInstanceRecord['state'];
|
|
15
18
|
/** Member profiles indexed by memberId. */
|
|
@@ -26,4 +29,4 @@ export interface InstanceHistorySectionProps {
|
|
|
26
29
|
* Computes the step records from the provided data and renders them as a
|
|
27
30
|
* vertical dot stepper.
|
|
28
31
|
*/
|
|
29
|
-
export declare function InstanceHistorySection({ activityLogs, instanceState, memberProfilesById, signatureVerification, signaturesById, taskDecisionsByTaskId, tasks, workflowSnapshot, workflowTokens, }: InstanceHistorySectionProps): ReactElement;
|
|
32
|
+
export declare function InstanceHistorySection({ activityLogs, formSchema, instanceState, memberProfilesById, signatureVerification, signaturesById, taskDecisionsByTaskId, tasks, workflowSnapshot, workflowTokens, }: InstanceHistorySectionProps): ReactElement;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AdhocDirectiveRecord, ApprovalInstanceRecord, MemberProfileRecord, TaskRecord } from '@rytass/bpm-core-client/workflow';
|
|
2
|
+
import { FillSummaryItem } from '../../approver-filled-form.cjs';
|
|
2
3
|
/**
|
|
3
4
|
* Imperative handle exposed by InstanceTasksSection via ref.
|
|
4
5
|
* The container uses these to wire PageHeader action buttons to the
|
|
@@ -29,7 +30,27 @@ export interface InstanceTasksSectionHandle {
|
|
|
29
30
|
/** Opens the approve-comment modal. */
|
|
30
31
|
handleApprove(): void;
|
|
31
32
|
}
|
|
33
|
+
/** What approving the viewer's fill task sends along with the decision. */
|
|
34
|
+
export interface InstanceTasksSectionFill {
|
|
35
|
+
/** `ApprovalInstance.formDataFingerprint` the fill was made against. */
|
|
36
|
+
readonly expectedFormDataFingerprint: string;
|
|
37
|
+
/** Every key the node lets the approver fill (`readFillPayload`). */
|
|
38
|
+
readonly formData: Readonly<Record<string, unknown>>;
|
|
39
|
+
/** One line per fill field, listed in the approve dialog. */
|
|
40
|
+
readonly summary: readonly FillSummaryItem[];
|
|
41
|
+
}
|
|
32
42
|
export interface InstanceTasksSectionProps {
|
|
43
|
+
/**
|
|
44
|
+
* Present when the viewer's task fills in fields: approving sends it, and
|
|
45
|
+
* the approve dialog lists it. The container validates before opening.
|
|
46
|
+
*/
|
|
47
|
+
readonly fill?: InstanceTasksSectionFill | null;
|
|
48
|
+
/**
|
|
49
|
+
* Gets the server's message when approving with `fill` fails. Returning
|
|
50
|
+
* `true` means the container showed it (a conflict or field errors), so the
|
|
51
|
+
* dialog closes instead of repeating it.
|
|
52
|
+
*/
|
|
53
|
+
readonly onFillApproveError?: (message: string) => boolean;
|
|
33
54
|
/** All tasks for this instance. */
|
|
34
55
|
readonly tasks: readonly TaskRecord[];
|
|
35
56
|
/** Ad-hoc directives recorded on this instance. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AdhocDirectiveRecord, ApprovalInstanceRecord, MemberProfileRecord, TaskRecord } from '@rytass/bpm-core-client/workflow';
|
|
2
|
+
import { FillSummaryItem } from '../../approver-filled-form.js';
|
|
2
3
|
/**
|
|
3
4
|
* Imperative handle exposed by InstanceTasksSection via ref.
|
|
4
5
|
* The container uses these to wire PageHeader action buttons to the
|
|
@@ -29,7 +30,27 @@ export interface InstanceTasksSectionHandle {
|
|
|
29
30
|
/** Opens the approve-comment modal. */
|
|
30
31
|
handleApprove(): void;
|
|
31
32
|
}
|
|
33
|
+
/** What approving the viewer's fill task sends along with the decision. */
|
|
34
|
+
export interface InstanceTasksSectionFill {
|
|
35
|
+
/** `ApprovalInstance.formDataFingerprint` the fill was made against. */
|
|
36
|
+
readonly expectedFormDataFingerprint: string;
|
|
37
|
+
/** Every key the node lets the approver fill (`readFillPayload`). */
|
|
38
|
+
readonly formData: Readonly<Record<string, unknown>>;
|
|
39
|
+
/** One line per fill field, listed in the approve dialog. */
|
|
40
|
+
readonly summary: readonly FillSummaryItem[];
|
|
41
|
+
}
|
|
32
42
|
export interface InstanceTasksSectionProps {
|
|
43
|
+
/**
|
|
44
|
+
* Present when the viewer's task fills in fields: approving sends it, and
|
|
45
|
+
* the approve dialog lists it. The container validates before opening.
|
|
46
|
+
*/
|
|
47
|
+
readonly fill?: InstanceTasksSectionFill | null;
|
|
48
|
+
/**
|
|
49
|
+
* Gets the server's message when approving with `fill` fails. Returning
|
|
50
|
+
* `true` means the container showed it (a conflict or field errors), so the
|
|
51
|
+
* dialog closes instead of repeating it.
|
|
52
|
+
*/
|
|
53
|
+
readonly onFillApproveError?: (message: string) => boolean;
|
|
33
54
|
/** All tasks for this instance. */
|
|
34
55
|
readonly tasks: readonly TaskRecord[];
|
|
35
56
|
/** Ad-hoc directives recorded on this instance. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActivityLogRecord, AdhocDirectiveRecord, ApprovalInstanceRecord, MemberProfileRecord, TaskDecisionRecord, TaskRecord } from '@rytass/bpm-core-client/workflow';
|
|
2
|
-
export {
|
|
2
|
+
export { readActingTask, readErrorMessage, readInstanceStateLabel, readNodeRuntimeState, } from './shared.cjs';
|
|
3
3
|
export declare function readMemberProfilesForTimeline({ activityLogs, adhocDirectives, instance, tasks, }: {
|
|
4
4
|
readonly activityLogs: readonly ActivityLogRecord[];
|
|
5
5
|
readonly adhocDirectives?: readonly AdhocDirectiveRecord[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActivityLogRecord, AdhocDirectiveRecord, ApprovalInstanceRecord, MemberProfileRecord, TaskDecisionRecord, TaskRecord } from '@rytass/bpm-core-client/workflow';
|
|
2
|
-
export {
|
|
2
|
+
export { readActingTask, readErrorMessage, readInstanceStateLabel, readNodeRuntimeState, } from './shared.js';
|
|
3
3
|
export declare function readMemberProfilesForTimeline({ activityLogs, adhocDirectives, instance, tasks, }: {
|
|
4
4
|
readonly activityLogs: readonly ActivityLogRecord[];
|
|
5
5
|
readonly adhocDirectives?: readonly AdhocDirectiveRecord[];
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
1
2
|
import { ActivityLogRecord, ApprovalInstanceRecord, AttachmentRecord, MemberProfileRecord, SignatureRecord, SignatureVerificationRecord, TaskDecisionRecord, TaskRecord, WorkflowTokenRecord } from '@rytass/bpm-core-client/workflow';
|
|
2
3
|
import { WorkflowDefinition, WorkflowNode } from '@rytass/bpm-core-shared/workflow';
|
|
3
4
|
export type TaskRow = Readonly<Record<string, unknown> & TaskRecord & {
|
|
4
5
|
assigneeLabel: string;
|
|
6
|
+
/** Fields still to fill on this open task (0 when none or ad hoc). */
|
|
7
|
+
fillFieldCount: number;
|
|
5
8
|
key: string;
|
|
6
9
|
nodeLabel: string;
|
|
7
10
|
statusLabel: string;
|
|
@@ -80,6 +83,12 @@ export declare function readNodeDisplayLabel(nodeId: string, workflow: WorkflowD
|
|
|
80
83
|
export declare function readMemberDisplayText(memberId: string | null, memberProfilesById: ReadonlyMap<string, MemberProfileRecord>): string;
|
|
81
84
|
export declare function readTaskAssigneeLabel(task: TaskRecord, memberProfilesById?: ReadonlyMap<string, MemberProfileRecord>): string;
|
|
82
85
|
export declare function canMemberActOnTask(task: TaskRecord, memberId: string | null): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* The task the member may act on now. A member who holds both an ad-hoc task
|
|
88
|
+
* and the node's own task gets the node's own one: only it may fill in the
|
|
89
|
+
* node's fields. Among the same kind, the first in `tasks` order wins.
|
|
90
|
+
*/
|
|
91
|
+
export declare function readActingTask(tasks: readonly TaskRecord[], memberId: string | null): TaskRecord | null;
|
|
83
92
|
export declare function readReturnTargetOptions(workflow: WorkflowDefinition, node: WorkflowNode): readonly {
|
|
84
93
|
readonly id: string;
|
|
85
94
|
readonly name: string;
|
|
@@ -127,11 +136,11 @@ export declare function readActivityEventLabel(eventType: string, payload: Reado
|
|
|
127
136
|
export declare function readActivityPayload(activityLog: ActivityLogRecord): Readonly<Record<string, unknown>>;
|
|
128
137
|
export declare function isActivityError(activityLog: ActivityLogRecord, payload: Readonly<Record<string, unknown>>): boolean;
|
|
129
138
|
export declare function formatActivityDateTime(value: string): string;
|
|
130
|
-
export declare function readActivityDetailParts(activityLog: ActivityLogRecord, payload: Readonly<Record<string, unknown>>, workflow: WorkflowDefinition | null, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null, memberProfilesById: ReadonlyMap<string, MemberProfileRecord
|
|
139
|
+
export declare function readActivityDetailParts(activityLog: ActivityLogRecord, payload: Readonly<Record<string, unknown>>, workflow: WorkflowDefinition | null, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null, memberProfilesById: ReadonlyMap<string, MemberProfileRecord>, formSchema?: FormDefinitionSchema | null): readonly ActivityStepDescriptionPart[];
|
|
131
140
|
export declare function isFutureTimelineNode(node: WorkflowNode, tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], instanceState: ApprovalInstanceRecord['state'], representedNodeIds: ReadonlySet<string>): boolean;
|
|
132
141
|
export declare function readFutureTimelineNodes(workflow: WorkflowDefinition, tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], instanceState: ApprovalInstanceRecord['state'], representedNodeIds: ReadonlySet<string>): readonly WorkflowNode[];
|
|
133
142
|
export declare function readFutureNodeStepTitle(node: WorkflowNode): string;
|
|
134
|
-
export declare function readActivityStepRecords(activityLogs: readonly ActivityLogRecord[], tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], workflow: WorkflowDefinition | null, instanceState: ApprovalInstanceRecord['state'], memberProfilesById: ReadonlyMap<string, MemberProfileRecord>, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null): ActivityStepRecord[];
|
|
143
|
+
export declare function readActivityStepRecords(activityLogs: readonly ActivityLogRecord[], tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], workflow: WorkflowDefinition | null, instanceState: ApprovalInstanceRecord['state'], memberProfilesById: ReadonlyMap<string, MemberProfileRecord>, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null, formSchema?: FormDefinitionSchema | null): ActivityStepRecord[];
|
|
135
144
|
type RuntimeTone = 'cancelled' | 'completed' | 'current' | 'neutral' | 'waiting';
|
|
136
145
|
export declare function readNodeRuntimeState(node: WorkflowNode, tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], instanceState: string): Readonly<{
|
|
137
146
|
secondaryLabel: string;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
1
2
|
import { ActivityLogRecord, ApprovalInstanceRecord, AttachmentRecord, MemberProfileRecord, SignatureRecord, SignatureVerificationRecord, TaskDecisionRecord, TaskRecord, WorkflowTokenRecord } from '@rytass/bpm-core-client/workflow';
|
|
2
3
|
import { WorkflowDefinition, WorkflowNode } from '@rytass/bpm-core-shared/workflow';
|
|
3
4
|
export type TaskRow = Readonly<Record<string, unknown> & TaskRecord & {
|
|
4
5
|
assigneeLabel: string;
|
|
6
|
+
/** Fields still to fill on this open task (0 when none or ad hoc). */
|
|
7
|
+
fillFieldCount: number;
|
|
5
8
|
key: string;
|
|
6
9
|
nodeLabel: string;
|
|
7
10
|
statusLabel: string;
|
|
@@ -80,6 +83,12 @@ export declare function readNodeDisplayLabel(nodeId: string, workflow: WorkflowD
|
|
|
80
83
|
export declare function readMemberDisplayText(memberId: string | null, memberProfilesById: ReadonlyMap<string, MemberProfileRecord>): string;
|
|
81
84
|
export declare function readTaskAssigneeLabel(task: TaskRecord, memberProfilesById?: ReadonlyMap<string, MemberProfileRecord>): string;
|
|
82
85
|
export declare function canMemberActOnTask(task: TaskRecord, memberId: string | null): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* The task the member may act on now. A member who holds both an ad-hoc task
|
|
88
|
+
* and the node's own task gets the node's own one: only it may fill in the
|
|
89
|
+
* node's fields. Among the same kind, the first in `tasks` order wins.
|
|
90
|
+
*/
|
|
91
|
+
export declare function readActingTask(tasks: readonly TaskRecord[], memberId: string | null): TaskRecord | null;
|
|
83
92
|
export declare function readReturnTargetOptions(workflow: WorkflowDefinition, node: WorkflowNode): readonly {
|
|
84
93
|
readonly id: string;
|
|
85
94
|
readonly name: string;
|
|
@@ -127,11 +136,11 @@ export declare function readActivityEventLabel(eventType: string, payload: Reado
|
|
|
127
136
|
export declare function readActivityPayload(activityLog: ActivityLogRecord): Readonly<Record<string, unknown>>;
|
|
128
137
|
export declare function isActivityError(activityLog: ActivityLogRecord, payload: Readonly<Record<string, unknown>>): boolean;
|
|
129
138
|
export declare function formatActivityDateTime(value: string): string;
|
|
130
|
-
export declare function readActivityDetailParts(activityLog: ActivityLogRecord, payload: Readonly<Record<string, unknown>>, workflow: WorkflowDefinition | null, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null, memberProfilesById: ReadonlyMap<string, MemberProfileRecord
|
|
139
|
+
export declare function readActivityDetailParts(activityLog: ActivityLogRecord, payload: Readonly<Record<string, unknown>>, workflow: WorkflowDefinition | null, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null, memberProfilesById: ReadonlyMap<string, MemberProfileRecord>, formSchema?: FormDefinitionSchema | null): readonly ActivityStepDescriptionPart[];
|
|
131
140
|
export declare function isFutureTimelineNode(node: WorkflowNode, tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], instanceState: ApprovalInstanceRecord['state'], representedNodeIds: ReadonlySet<string>): boolean;
|
|
132
141
|
export declare function readFutureTimelineNodes(workflow: WorkflowDefinition, tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], instanceState: ApprovalInstanceRecord['state'], representedNodeIds: ReadonlySet<string>): readonly WorkflowNode[];
|
|
133
142
|
export declare function readFutureNodeStepTitle(node: WorkflowNode): string;
|
|
134
|
-
export declare function readActivityStepRecords(activityLogs: readonly ActivityLogRecord[], tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], workflow: WorkflowDefinition | null, instanceState: ApprovalInstanceRecord['state'], memberProfilesById: ReadonlyMap<string, MemberProfileRecord>, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null): ActivityStepRecord[];
|
|
143
|
+
export declare function readActivityStepRecords(activityLogs: readonly ActivityLogRecord[], tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], workflow: WorkflowDefinition | null, instanceState: ApprovalInstanceRecord['state'], memberProfilesById: ReadonlyMap<string, MemberProfileRecord>, taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>, signaturesById: ReadonlyMap<string, SignatureRecord>, signatureVerification: SignatureVerificationRecord | null, formSchema?: FormDefinitionSchema | null): ActivityStepRecord[];
|
|
135
144
|
type RuntimeTone = 'cancelled' | 'completed' | 'current' | 'neutral' | 'waiting';
|
|
136
145
|
export declare function readNodeRuntimeState(node: WorkflowNode, tasks: readonly TaskRecord[], tokens: readonly WorkflowTokenRecord[], instanceState: string): Readonly<{
|
|
137
146
|
secondaryLabel: string;
|