@rytass/bpm-core-react 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -0
- package/dist/chunks/FormBuilderView-B_KGPjlp.cjs +3 -0
- package/dist/chunks/FormBuilderView-B_KGPjlp.cjs.map +1 -0
- package/dist/chunks/FormBuilderView-D8DrQOXD.js +1090 -0
- package/dist/chunks/FormBuilderView-D8DrQOXD.js.map +1 -0
- package/dist/chunks/{approval-instance-list-page-UNIIgUZy.cjs → approval-instance-list-page-BMUKxzcz.cjs} +2 -2
- package/dist/chunks/{approval-instance-list-page-UNIIgUZy.cjs.map → approval-instance-list-page-BMUKxzcz.cjs.map} +1 -1
- package/dist/chunks/{approval-instance-list-page-BtEc8Cs3.js → approval-instance-list-page-YZcGGDD8.js} +3 -3
- package/dist/chunks/{approval-instance-list-page-BtEc8Cs3.js.map → approval-instance-list-page-YZcGGDD8.js.map} +1 -1
- package/dist/chunks/{auth-provider-D2P-qWmY.cjs → auth-provider-4BeCw7cI.cjs} +2 -2
- package/dist/chunks/{auth-provider-D2P-qWmY.cjs.map → auth-provider-4BeCw7cI.cjs.map} +1 -1
- package/dist/chunks/{auth-provider-TTO9eNZV.js → auth-provider-B5oPmvk2.js} +2 -2
- package/dist/chunks/{auth-provider-TTO9eNZV.js.map → auth-provider-B5oPmvk2.js.map} +1 -1
- package/dist/chunks/compose-PMrmi-LE.js +451 -0
- package/dist/chunks/compose-PMrmi-LE.js.map +1 -0
- package/dist/chunks/compose-ziVbRYdo.cjs +2 -0
- package/dist/chunks/compose-ziVbRYdo.cjs.map +1 -0
- package/dist/chunks/{dashboard-page-CQRBJxze.js → dashboard-page-DJ9vOPga.js} +4 -4
- package/dist/chunks/{dashboard-page-CQRBJxze.js.map → dashboard-page-DJ9vOPga.js.map} +1 -1
- package/dist/chunks/{dashboard-page-DrDChhg1.cjs → dashboard-page-DwHQY6Ki.cjs} +2 -2
- package/dist/chunks/{dashboard-page-DrDChhg1.cjs.map → dashboard-page-DwHQY6Ki.cjs.map} +1 -1
- package/dist/chunks/{delegations-CFXaJrdX.cjs → delegations-C2wLWsDQ.cjs} +2 -2
- package/dist/chunks/{delegations-CFXaJrdX.cjs.map → delegations-C2wLWsDQ.cjs.map} +1 -1
- package/dist/chunks/{delegations-DwbYkNUg.cjs → delegations-DDEk-WI6.cjs} +2 -2
- package/dist/chunks/{delegations-DwbYkNUg.cjs.map → delegations-DDEk-WI6.cjs.map} +1 -1
- package/dist/chunks/{delegations-FTLaWo1Y.js → delegations-ZNtodFaD.js} +2 -2
- package/dist/chunks/{delegations-FTLaWo1Y.js.map → delegations-ZNtodFaD.js.map} +1 -1
- package/dist/chunks/{delegations-D5pPEWsP.js → delegations-iVnRi3QE.js} +2 -2
- package/dist/chunks/{delegations-D5pPEWsP.js.map → delegations-iVnRi3QE.js.map} +1 -1
- package/dist/chunks/designer-DCn6_v4b.cjs +65 -0
- package/dist/chunks/designer-DCn6_v4b.cjs.map +1 -0
- package/dist/chunks/designer-mOMxJ0Py.js +2576 -0
- package/dist/chunks/designer-mOMxJ0Py.js.map +1 -0
- package/dist/chunks/detail-Bml-vXHX.js +1622 -0
- package/dist/chunks/detail-Bml-vXHX.js.map +1 -0
- package/dist/chunks/detail-CWeCrmtC.cjs +2 -0
- package/dist/chunks/detail-CWeCrmtC.cjs.map +1 -0
- package/dist/chunks/{login-BfmfCclF.cjs → login-9bCXyjbX.cjs} +2 -2
- package/dist/chunks/{login-BfmfCclF.cjs.map → login-9bCXyjbX.cjs.map} +1 -1
- package/dist/chunks/{login-xgI4wLHe.js → login-BKxpLibd.js} +3 -3
- package/dist/chunks/{login-xgI4wLHe.js.map → login-BKxpLibd.js.map} +1 -1
- package/dist/chunks/{notifications-a-FCxV02.cjs → notifications-BKs4--96.cjs} +2 -2
- package/dist/chunks/{notifications-a-FCxV02.cjs.map → notifications-BKs4--96.cjs.map} +1 -1
- package/dist/chunks/{notifications-BoNa1BXD.js → notifications-CSulztkU.js} +2 -2
- package/dist/chunks/{notifications-BoNa1BXD.js.map → notifications-CSulztkU.js.map} +1 -1
- package/dist/chunks/router-adapter--gYs13E8.cjs +2 -0
- package/dist/chunks/{router-adapter-BybHrCNP.cjs.map → router-adapter--gYs13E8.cjs.map} +1 -1
- package/dist/chunks/{router-adapter-BdHZXLS3.js → router-adapter-DftlFTOd.js} +2 -2
- package/dist/chunks/{router-adapter-BdHZXLS3.js.map → router-adapter-DftlFTOd.js.map} +1 -1
- package/dist/chunks/{routes-config-dxahImVe.js → routes-config-RBYQtUd0.js} +2 -3
- package/dist/chunks/routes-config-RBYQtUd0.js.map +1 -0
- package/dist/chunks/routes-config-fDVHmvXi.cjs +2 -0
- package/dist/chunks/routes-config-fDVHmvXi.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +270 -130
- package/dist/index.js.map +1 -1
- package/dist/lib/routes-config.d.ts +6 -4
- package/dist/next/BPMNextProviders.d.ts +1 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.js +14 -24
- package/dist/next/index.js.map +1 -1
- package/dist/next/workflow-chat-route.cjs +19 -0
- package/dist/next/workflow-chat-route.cjs.map +1 -0
- package/dist/next/workflow-chat-route.d.ts +17 -0
- package/dist/next/workflow-chat-route.js +31 -0
- package/dist/next/workflow-chat-route.js.map +1 -0
- package/dist/pages/admin/delegations/index.cjs +1 -1
- package/dist/pages/admin/delegations/index.js +1 -1
- package/dist/pages/delegations/index.cjs +1 -1
- package/dist/pages/delegations/index.js +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/login/index.cjs +1 -1
- package/dist/pages/login/index.js +1 -1
- package/dist/pages/settings/notifications/index.cjs +1 -1
- package/dist/pages/settings/notifications/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +2 -0
- package/dist/pages/templates/compose/index.cjs.map +1 -0
- package/dist/pages/templates/compose/index.d.ts +13 -0
- package/dist/pages/templates/compose/index.js +14 -0
- package/dist/pages/templates/compose/index.js.map +1 -0
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.cjs.map +1 -1
- package/dist/pages/templates/designer/index.js +7 -2
- package/dist/pages/templates/designer/index.js.map +1 -1
- package/dist/pages/templates/index.cjs +1 -1
- package/dist/pages/templates/index.cjs.map +1 -1
- package/dist/pages/templates/index.js +3 -3
- package/dist/pages/templates/index.js.map +1 -1
- package/dist/views/admin/delegations/index.cjs +1 -1
- package/dist/views/admin/delegations/index.js +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.js +1 -1
- package/dist/views/cc/index.cjs +1 -1
- package/dist/views/cc/index.js +1 -1
- package/dist/views/dashboard/index.cjs +1 -1
- package/dist/views/dashboard/index.js +1 -1
- package/dist/views/delegations/index.cjs +1 -1
- package/dist/views/delegations/index.js +1 -1
- package/dist/views/forms/builder/FormBuilderView.d.ts +13 -4
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/builder/json-code-editor.d.ts +1 -1
- package/dist/views/inbox/index.cjs +1 -1
- package/dist/views/inbox/index.js +3 -3
- package/dist/views/instances/detail/InstanceDetailView.d.ts +11 -1
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.d.ts +5 -0
- package/dist/views/instances/detail/index.js +2 -2
- package/dist/views/instances/detail/sections/InstanceAttachmentsSection.d.ts +15 -0
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +33 -0
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +29 -0
- package/dist/views/instances/detail/sections/InstanceSignaturesSection.d.ts +14 -0
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +44 -0
- package/dist/views/instances/detail/sections/container-helpers.d.ts +8 -0
- package/dist/views/instances/detail/sections/shared.d.ts +103 -0
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.js +3 -3
- package/dist/views/login/index.cjs +1 -1
- package/dist/views/login/index.js +1 -1
- package/dist/views/search/index.cjs +1 -1
- package/dist/views/search/index.js +1 -1
- package/dist/views/sent/index.cjs +1 -1
- package/dist/views/sent/index.js +1 -1
- package/dist/views/settings/index.cjs +1 -1
- package/dist/views/settings/index.js +1 -1
- package/dist/views/settings/notifications/index.cjs +1 -1
- package/dist/views/settings/notifications/index.js +1 -1
- package/dist/views/templates/TemplatesView.d.ts +5 -0
- package/dist/views/templates/compose/TemplateComposeWizardView.d.ts +8 -0
- package/dist/views/templates/compose/index.cjs +1 -0
- package/dist/views/templates/compose/index.d.ts +2 -0
- package/dist/views/templates/compose/index.js +2 -0
- package/dist/views/templates/compose/steps/ComposeFormStep.d.ts +15 -0
- package/dist/views/templates/compose/steps/ComposeReviewStep.d.ts +12 -0
- package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.ts +11 -0
- package/dist/views/templates/compose/use-template-compose-wizard.d.ts +46 -0
- package/dist/views/templates/designer/TemplateDesignerView.d.ts +60 -2
- package/dist/views/templates/designer/chrome-workflow-chat.d.ts +12 -0
- package/dist/views/templates/designer/index.cjs +1 -51
- package/dist/views/templates/designer/index.js +2 -2272
- package/dist/views/templates/designer/use-workflow-chat.d.ts +21 -0
- package/dist/views/templates/designer/use-workflow-designer-controller.d.ts +41 -0
- package/dist/views/templates/designer/workflow-chat-drawer.d.ts +16 -0
- package/dist/views/templates/index.cjs +2 -1
- package/dist/views/templates/index.cjs.map +1 -0
- package/dist/views/templates/index.js +265 -4
- package/dist/views/templates/index.js.map +1 -0
- package/dist/views/templates/versions/index.cjs +1 -1
- package/dist/views/templates/versions/index.cjs.map +1 -1
- package/dist/views/templates/versions/index.js +39 -43
- package/dist/views/templates/versions/index.js.map +1 -1
- package/package.json +22 -19
- package/dist/chunks/builder-C3E-8OJu.js +0 -1300
- package/dist/chunks/builder-C3E-8OJu.js.map +0 -1
- package/dist/chunks/builder-f-Q_0NUs.cjs +0 -3
- package/dist/chunks/builder-f-Q_0NUs.cjs.map +0 -1
- package/dist/chunks/detail-B9JkYNHc.cjs +0 -2
- package/dist/chunks/detail-B9JkYNHc.cjs.map +0 -1
- package/dist/chunks/detail-CSxI04gB.js +0 -1518
- package/dist/chunks/detail-CSxI04gB.js.map +0 -1
- package/dist/chunks/form-name-modal-C3OEvkCV.js +0 -64
- package/dist/chunks/form-name-modal-C3OEvkCV.js.map +0 -1
- package/dist/chunks/form-name-modal-uZCHbtRH.cjs +0 -2
- package/dist/chunks/form-name-modal-uZCHbtRH.cjs.map +0 -1
- package/dist/chunks/router-adapter-BybHrCNP.cjs +0 -2
- package/dist/chunks/routes-config-2aKbWq2H.cjs +0 -2
- package/dist/chunks/routes-config-2aKbWq2H.cjs.map +0 -1
- package/dist/chunks/routes-config-dxahImVe.js.map +0 -1
- package/dist/chunks/templates-CL8bPvgn.cjs +0 -2
- package/dist/chunks/templates-CL8bPvgn.cjs.map +0 -1
- package/dist/chunks/templates-DNfDOPGm.js +0 -380
- package/dist/chunks/templates-DNfDOPGm.js.map +0 -1
- package/dist/pages/forms/builder/index.cjs +0 -2
- package/dist/pages/forms/builder/index.cjs.map +0 -1
- package/dist/pages/forms/builder/index.d.ts +0 -21
- package/dist/pages/forms/builder/index.js +0 -15
- package/dist/pages/forms/builder/index.js.map +0 -1
- package/dist/pages/forms/index.cjs +0 -2
- package/dist/pages/forms/index.cjs.map +0 -1
- package/dist/pages/forms/index.d.ts +0 -17
- package/dist/pages/forms/index.js +0 -14
- package/dist/pages/forms/index.js.map +0 -1
- package/dist/views/forms/FormsView.d.ts +0 -2
- package/dist/views/forms/form-name-modal.d.ts +0 -12
- package/dist/views/forms/index.cjs +0 -2
- package/dist/views/forms/index.cjs.map +0 -1
- package/dist/views/forms/index.d.ts +0 -2
- package/dist/views/forms/index.js +0 -186
- package/dist/views/forms/index.js.map +0 -1
- package/dist/views/templates/designer/index.cjs.map +0 -1
- package/dist/views/templates/designer/index.js.map +0 -1
- package/dist/views/templates/template-name-modal.d.ts +0 -22
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detail-CSxI04gB.js","names":[],"sources":["../../src/components/pdf-preview.module.scss","../../src/components/pdf-preview.tsx","../../src/views/instances/detail/InstanceDetailView.tsx"],"sourcesContent":[".root {\n display: grid;\n gap: 12px;\n width: min(86vw, 1080px);\n}\n\n.toolbar {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: space-between;\n}\n\n.pageControls,\n.zoomControls {\n align-items: center;\n display: flex;\n gap: 8px;\n}\n\n.counter {\n min-width: 92px;\n text-align: center;\n white-space: nowrap;\n}\n\n.viewport {\n align-items: flex-start;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n display: flex;\n height: min(72vh, 760px);\n justify-content: center;\n min-height: 420px;\n overflow: auto;\n padding: 16px;\n}\n\n.page {\n background: #ffffff;\n box-shadow: 0 12px 32px rgb(15 23 42 / 14%);\n color: #111827;\n}\n\n.state {\n align-items: center;\n display: flex;\n justify-content: center;\n min-height: 320px;\n width: 100%;\n}\n\n@media (max-width: 720px) {\n .root {\n width: 92vw;\n }\n\n .toolbar {\n align-items: stretch;\n display: grid;\n }\n\n .pageControls,\n .zoomControls {\n justify-content: space-between;\n }\n\n .counter {\n min-width: 84px;\n }\n\n .viewport {\n height: 68vh;\n min-height: 360px;\n padding: 12px;\n }\n}\n","'use client';\n\nimport {\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Button, Typography } from '@mezzanine-ui/react';\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n DownloadIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@mezzanine-ui/icons';\nimport { Document, Page, pdfjs } from 'react-pdf';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport styles from './pdf-preview.module.scss';\n\n// pdfjs ships its worker as a separate chunk. Consumers should call\n// `configurePdfWorker(url)` (or set `pdfjs.GlobalWorkerOptions.workerSrc`\n// directly) before the first `<PDFPreview>` mounts. The library does not\n// hard-bundle a worker path because consumer bundlers may need to resolve\n// it through CDN, public/ asset pipeline, or pinned version.\nexport function configurePdfWorker(workerSrc: string): void {\n pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;\n}\n\nconst DEFAULT_VIEWPORT_WIDTH = 760;\nconst MAX_PAGE_WIDTH = 920;\nconst MIN_PAGE_WIDTH = 320;\nconst PAGE_HORIZONTAL_PADDING = 32;\nconst MIN_SCALE = 0.75;\nconst MAX_SCALE = 1.75;\nconst SCALE_STEP = 0.25;\n\nexport interface PDFPreviewProps {\n readonly filename: string;\n readonly fileUrl: string;\n readonly onDownload?: () => void;\n}\n\n/**\n * Mezzanine-styled PDF preview powered by `react-pdf`. Used by the instance\n * detail view to preview PDF attachments inline.\n */\nexport function PDFPreview({\n filename,\n fileUrl,\n onDownload,\n}: PDFPreviewProps): ReactElement {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const [numPages, setNumPages] = useState<number | null>(null);\n const [pageNumber, setPageNumber] = useState(1);\n const [scale, setScale] = useState(1);\n const [viewportWidth, setViewportWidth] = useState(DEFAULT_VIEWPORT_WIDTH);\n\n useEffect((): (() => void) | undefined => {\n const viewport = viewportRef.current;\n\n if (!viewport || typeof ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const observer = new ResizeObserver((entries): void => {\n const nextWidth = entries[0]?.contentRect.width;\n\n if (nextWidth) {\n setViewportWidth(nextWidth);\n }\n });\n\n observer.observe(viewport);\n\n return (): void => observer.disconnect();\n }, []);\n\n useEffect((): void => {\n setNumPages(null);\n setPageNumber(1);\n setScale(1);\n }, [fileUrl]);\n\n const pageWidth = useMemo((): number => {\n const availableWidth = Math.max(\n MIN_PAGE_WIDTH,\n viewportWidth - PAGE_HORIZONTAL_PADDING,\n );\n const baseWidth = Math.min(MAX_PAGE_WIDTH, availableWidth);\n\n return Math.round(baseWidth * scale);\n }, [scale, viewportWidth]);\n\n const loadDocument = useCallback((document: PDFDocumentProxy): void => {\n setNumPages(document.numPages);\n setPageNumber(1);\n }, []);\n\n const hasPreviousPage = pageNumber > 1;\n const hasNextPage = numPages !== null && pageNumber < numPages;\n const canZoomOut = scale > MIN_SCALE;\n const canZoomIn = scale < MAX_SCALE;\n const pageLabel =\n numPages === null\n ? `第 ${pageNumber} 頁`\n : `第 ${pageNumber} / ${numPages} 頁`;\n const zoomLabel = `${Math.round(scale * 100)}%`;\n\n return (\n <section aria-label={`${filename} PDF 預覽`} className={styles.root}>\n <div className={styles.toolbar}>\n <div className={styles.pageControls} aria-label=\"頁面切換\">\n <Button\n aria-label=\"上一頁\"\n disabled={!hasPreviousPage}\n icon={ChevronLeftIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n Math.max(1, currentPageNumber - 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {pageLabel}\n </Typography>\n <Button\n aria-label=\"下一頁\"\n disabled={!hasNextPage}\n icon={ChevronRightIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n numPages === null\n ? currentPageNumber\n : Math.min(numPages, currentPageNumber + 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n <div className={styles.zoomControls} aria-label=\"縮放\">\n <Button\n aria-label=\"縮小\"\n disabled={!canZoomOut}\n icon={ZoomOutIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.max(MIN_SCALE, currentScale - SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {zoomLabel}\n </Typography>\n <Button\n aria-label=\"放大\"\n disabled={!canZoomIn}\n icon={ZoomInIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.min(MAX_SCALE, currentScale + SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n {onDownload ? (\n <Button\n icon={DownloadIcon}\n iconType=\"leading\"\n onClick={onDownload}\n size=\"minor\"\n variant=\"base-primary\"\n >\n 下載\n </Button>\n ) : null}\n </div>\n <div className={styles.viewport} ref={viewportRef}>\n <Document\n error={<PDFPreviewState message=\"PDF 無法載入。\" />}\n file={fileUrl}\n loading={<PDFPreviewState message=\"正在載入 PDF...\" />}\n noData={<PDFPreviewState message=\"沒有可預覽的 PDF。\" />}\n onLoadSuccess={loadDocument}\n >\n <Page\n className={styles.page}\n loading={<PDFPreviewState message=\"正在載入頁面...\" />}\n pageNumber={pageNumber}\n renderAnnotationLayer\n renderTextLayer\n width={pageWidth}\n />\n </Document>\n </div>\n </section>\n );\n}\n\nfunction PDFPreviewState({\n message,\n}: {\n readonly message: string;\n}): ReactElement {\n return (\n <div className={styles.state}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {message}\n </Typography>\n </div>\n );\n}\n","'use client';\n\nimport {\n ChangeEvent,\n CSSProperties,\n Fragment,\n RefCallback,\n ReactElement,\n forwardRef,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Background,\n Controls,\n Handle,\n Position,\n ReactFlow,\n type Edge as FlowEdge,\n type Node as FlowNode,\n type NodeProps,\n} from '@xyflow/react';\nimport * as dagre from 'dagre';\nimport {\n AutoComplete,\n Button,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Stepper,\n Table,\n Textarea,\n Tooltip,\n Typography,\n type StepProps,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { stepClasses } from '@mezzanine-ui/core/stepper';\nimport {\n CheckedIcon,\n DangerousOutlineIcon,\n DownloadIcon,\n FileSearchIcon,\n RefreshCcwIcon,\n ShareIcon,\n UserIcon,\n} from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport {\n focusFormRendererField,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n ActivityLogRecord,\n AttachmentRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n cancelApprovalInstance,\n decideTask,\n listAttachments,\n listTaskDecisions,\n readApprovalInstance,\n readAttachmentDownloadUrl,\n readAttachmentPreviewUrl,\n readInstanceSignatures,\n resubmitApprovalInstance,\n resolveMemberProfiles,\n searchMembers,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowFormData,\n WorkflowTokenRecord,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport { PDFPreview } from '../../../components/pdf-preview';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst BUTTON_ROW_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nconst FLOW_NODE_LAYOUT_WIDTH = 184;\nconst FLOW_NODE_LAYOUT_HEIGHT = 96;\n\nconst FLOW_MODAL_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst REJECT_REASON_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst REJECT_REASON_TEXTAREA_STYLE: CSSProperties = {\n minWidth: '100%',\n width: '100%',\n};\n\nconst MODAL_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst FLOW_CANVAS_STYLE: CSSProperties = {\n background: '#f8fafc',\n border: '1px solid #e2e8f0',\n borderRadius: 8,\n height: 'min(64vh, 620px)',\n minHeight: 440,\n overflow: 'hidden',\n width: 'min(80vw, 1040px)',\n};\n\nconst NODE_STYLE: CSSProperties = {\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n boxShadow: '0 8px 18px rgba(15, 23, 42, 0.08)',\n display: 'grid',\n gap: 6,\n minHeight: 82,\n padding: 12,\n width: 184,\n};\n\nconst NODE_STATUS_STYLE: CSSProperties = {\n borderRadius: 999,\n fontSize: 12,\n fontWeight: 600,\n justifySelf: 'start',\n lineHeight: '18px',\n padding: '0 8px',\n};\n\nconst NODE_SECONDARY_STYLE: CSSProperties = {\n color: '#64748b',\n fontSize: 12,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nconst NODE_HANDLE_STYLE: CSSProperties = {\n opacity: 0,\n};\n\nconst EDGE_SUMMARY_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nconst EDGE_SUMMARY_ITEM_STYLE: CSSProperties = {\n alignItems: 'center',\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n color: '#334155',\n display: 'inline-flex',\n fontSize: 12,\n fontWeight: 600,\n gap: 6,\n lineHeight: '20px',\n padding: '4px 8px',\n};\n\nconst HISTORY_MEMBER_NAME_STYLE: CSSProperties = {\n cursor: 'help',\n textDecoration: 'underline dotted',\n textUnderlineOffset: 3,\n};\n\nconst HISTORY_DANGER_TEXT_STYLE: CSSProperties = {\n color: 'var(--mzn-color-text-error)',\n};\n\nfunction applyFullWidthTextareaHost(element: HTMLDivElement | null): void {\n if (!element) {\n return;\n }\n\n element.style.width = '100%';\n}\n\nconst READONLY_FLOW_NODE_TYPES = {\n workflowRuntime: WorkflowRuntimeNodeCard,\n};\n\ntype RuntimeTone =\n | 'cancelled'\n | 'completed'\n | 'current'\n | 'neutral'\n | 'waiting';\n\ninterface RuntimeNodeData extends Record<string, unknown> {\n readonly kindLabel: string;\n readonly label: string;\n readonly secondaryLabel: string;\n readonly statusLabel: string;\n readonly tone: RuntimeTone;\n}\n\ntype RuntimeFlowNode = FlowNode<RuntimeNodeData, 'workflowRuntime'>;\ntype RuntimeFlowEdge = FlowEdge<\n Readonly<Record<string, unknown>>,\n 'smoothstep'\n>;\n\ntype TaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n assigneeLabel: string;\n key: string;\n nodeLabel: string;\n statusLabel: string;\n }\n>;\n\ntype AttachmentRow = Readonly<\n Record<string, unknown> & {\n attachment: AttachmentRecord;\n createdAt: string;\n filename: string;\n id: string;\n key: string;\n mimeType: string;\n sizeLabel: string;\n }\n>;\n\ntype SignatureRow = Readonly<\n Record<string, unknown> & {\n algorithm: string;\n hashLabel: string;\n key: string;\n keyVersion: number;\n signedAtLabel: string;\n signerMemberId: string;\n }\n>;\n\ntype MemberOption = Readonly<{\n email: string | null;\n id: string;\n name: string;\n}>;\n\ninterface ActivityStepRecord {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly error: boolean;\n readonly forcePending?: boolean;\n readonly id: string;\n readonly title: string;\n}\n\ntype ActivityStepDescriptionPart =\n | Readonly<{ text: string; type: 'text' }>\n | Readonly<{ text: string; type: 'dangerText' }>\n | Readonly<{\n email: string | null;\n label: string;\n memberId: string | null;\n prefix: string;\n type: 'member';\n }>;\n\nexport interface InstanceDetailViewProps {\n /** Approval instance id (Next.js `params.id` resolved by the page shim). */\n readonly instanceId: string;\n}\n\n/**\n * Framework-agnostic view for the BPM approval instance detail page.\n * Mechanical port of `apps/client/src/app/instances/[id]/page.tsx`. The\n * `instanceId` is provided by the host page wrapper (typically resolved\n * from `params.id` in the Next.js Server Component shim).\n */\nexport function InstanceDetailView({\n instanceId,\n}: InstanceDetailViewProps): ReactElement {\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activityLogs, setActivityLogs] = useState<\n readonly ActivityLogRecord[]\n >([]);\n const [instance, setInstance] = useState<ApprovalInstanceRecord | null>(null);\n const [taskDecisions, setTaskDecisions] = useState<\n readonly TaskDecisionRecord[]\n >([]);\n const [attachments, setAttachments] = useState<readonly AttachmentRecord[]>(\n [],\n );\n const [signatures, setSignatures] = useState<readonly SignatureRecord[]>([]);\n const [signatureVerification, setSignatureVerification] =\n useState<SignatureVerificationRecord | null>(null);\n const [tasks, setTasks] = useState<readonly TaskRecord[]>([]);\n const [workflowTokens, setWorkflowTokens] = useState<\n readonly WorkflowTokenRecord[]\n >([]);\n const [memberProfiles, setMemberProfiles] = useState<\n readonly MemberProfileRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [deciding, setDeciding] = useState(false);\n const [workflowModalOpen, setWorkflowModalOpen] = useState(false);\n const [cancelComment, setCancelComment] = useState('');\n const [cancelModalOpen, setCancelModalOpen] = useState(false);\n const [rejectReason, setRejectReason] = useState('');\n const [rejectReasonError, setRejectReasonError] = useState<string | null>(\n null,\n );\n const [rejectReasonModalOpen, setRejectReasonModalOpen] = useState(false);\n const [returnComment, setReturnComment] = useState('');\n const [returnModalOpen, setReturnModalOpen] = useState(false);\n const [returnTargetNodeId, setReturnTargetNodeId] = useState<string | null>(\n null,\n );\n const [transferComment, setTransferComment] = useState('');\n const [transferMember, setTransferMember] = useState<MemberOption | null>(\n null,\n );\n const [transferMemberLoading, setTransferMemberLoading] = useState(false);\n const [transferMemberOptions, setTransferMemberOptions] = useState<\n readonly MemberOption[]\n >([]);\n const [transferModalOpen, setTransferModalOpen] = useState(false);\n const [resubmitFormErrors, setResubmitFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [resubmitFormData, setResubmitFormData] = useState<WorkflowFormData>(\n {},\n );\n const [previewAttachment, setPreviewAttachment] =\n useState<AttachmentRecord | null>(null);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const trimmedRejectReason = rejectReason.trim();\n const trimmedCancelComment = cancelComment.trim();\n const trimmedReturnComment = returnComment.trim();\n const trimmedTransferComment = transferComment.trim();\n\n useEffect((): void => {\n void refreshInstance();\n }, [currentMemberId, instanceId]);\n\n useEffect((): void => {\n setResubmitFormData(instance?.formData ?? {});\n }, [instance]);\n\n const currentTask = useMemo(\n (): TaskRecord | null =>\n tasks.find(\n (task) =>\n canMemberActOnTask(task, currentMemberId) &&\n (task.status === 'PENDING' || task.status === 'IN_PROGRESS'),\n ) ?? null,\n [currentMemberId, tasks],\n );\n const currentTaskNode = useMemo(\n (): WorkflowNode | null =>\n currentTask && instance\n ? (instance.workflowSnapshot.nodes.find(\n (node) => node.id === currentTask.nodeId,\n ) ?? null)\n : null,\n [currentTask, instance],\n );\n const returnTargetOptions = useMemo(\n (): readonly { readonly id: string; readonly name: string }[] =>\n currentTaskNode && instance\n ? readReturnTargetOptions(instance.workflowSnapshot, currentTaskNode)\n : [],\n [currentTaskNode, instance],\n );\n const canReturnCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.allowReturn;\n const selectedReturnTargetOption =\n returnTargetOptions.find((option) => option.id === returnTargetNodeId) ??\n returnTargetOptions[0] ??\n null;\n const canCancelInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n (instance.state === 'RUNNING' || instance.state === 'RETURNED'),\n );\n const canResubmitInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n instance.state === 'RETURNED',\n );\n const memberProfilesById = useMemo(\n (): ReadonlyMap<string, MemberProfileRecord> =>\n new Map(memberProfiles.map((profile) => [profile.memberId, profile])),\n [memberProfiles],\n );\n const taskRows = useMemo(\n (): TaskRow[] =>\n tasks.map((task) => ({\n ...task,\n assigneeLabel: readTaskAssigneeLabel(task, memberProfilesById),\n key: task.id,\n nodeLabel: readNodeDisplayLabel(\n task.nodeId,\n instance?.workflowSnapshot ?? null,\n ),\n statusLabel: readTaskStatusLabel(task.status),\n })),\n [instance, memberProfilesById, tasks],\n );\n const taskDecisionsByTaskId = useMemo(\n (): ReadonlyMap<string, TaskDecisionRecord> =>\n readLatestTaskDecisionsByTaskId(taskDecisions),\n [taskDecisions],\n );\n const signaturesById = useMemo(\n (): ReadonlyMap<string, SignatureRecord> =>\n new Map(signatures.map((signature) => [signature.id, signature])),\n [signatures],\n );\n const activitySteps = useMemo(\n (): ActivityStepRecord[] =>\n readActivityStepRecords(\n activityLogs,\n tasks,\n workflowTokens,\n instance?.workflowSnapshot ?? null,\n instance?.state ?? 'RUNNING',\n memberProfilesById,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n ),\n [\n activityLogs,\n instance,\n memberProfilesById,\n signatureVerification,\n signaturesById,\n taskDecisionsByTaskId,\n tasks,\n workflowTokens,\n ],\n );\n const currentActivityStep = useMemo(\n (): number => readCurrentActivityStep(activitySteps),\n [activitySteps],\n );\n const layoutedWorkflowSnapshot = useMemo(\n (): WorkflowDefinition | null =>\n instance\n ? layoutRuntimeWorkflowDefinition(instance.workflowSnapshot)\n : null,\n [instance],\n );\n const flowNodes = useMemo(\n (): RuntimeFlowNode[] =>\n instance && layoutedWorkflowSnapshot\n ? readRuntimeFlowNodes(\n layoutedWorkflowSnapshot,\n tasks,\n workflowTokens,\n instance.state,\n )\n : [],\n [instance, layoutedWorkflowSnapshot, tasks, workflowTokens],\n );\n const flowEdges = useMemo(\n (): RuntimeFlowEdge[] =>\n layoutedWorkflowSnapshot\n ? readRuntimeFlowEdges(layoutedWorkflowSnapshot)\n : [],\n [layoutedWorkflowSnapshot],\n );\n const edgeSummaries = useMemo(\n (): readonly string[] =>\n instance ? readEdgeSummaries(instance.workflowSnapshot) : [],\n [instance],\n );\n const taskColumns = useMemo(\n (): TableColumn<TaskRow>[] => [\n { dataIndex: 'nodeLabel', key: 'nodeLabel', title: '節點', width: 180 },\n {\n key: 'assigneeMemberId',\n title: '處理者',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.assigneeLabel}\n </Typography>\n ),\n width: 180,\n },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'createdAt',\n render: (record: TaskRow): 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 attachmentRows = useMemo(\n (): AttachmentRow[] =>\n attachments.map((attachment) => ({\n attachment,\n createdAt: attachment.createdAt,\n filename: attachment.filename,\n id: attachment.id,\n key: attachment.id,\n mimeType: attachment.mimeType,\n sizeLabel: formatFileSize(Number(attachment.sizeBytes)),\n })),\n [attachments],\n );\n const attachmentColumns = useMemo(\n (): TableColumn<AttachmentRow>[] => [\n { dataIndex: 'filename', key: 'filename', title: '檔名', width: 260 },\n { dataIndex: 'mimeType', key: 'mimeType', title: '類型', width: 180 },\n { dataIndex: 'sizeLabel', key: 'sizeLabel', title: '大小', width: 120 },\n {\n key: 'createdAt',\n render: (record: AttachmentRow): 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 attachmentActions = useMemo(\n (): TableActions<AttachmentRow> => ({\n render: (record): ReturnType<TableActions<AttachmentRow>['render']> => [\n ...(record.mimeType === 'application/pdf'\n ? [\n {\n icon: FileSearchIcon,\n iconType: 'leading' as const,\n name: '預覽',\n onClick: (): void => {\n void handlePreviewAttachment(record.attachment);\n },\n },\n ]\n : []),\n {\n icon: DownloadIcon,\n iconType: 'leading',\n name: '下載',\n onClick: (): void => {\n void handleDownloadAttachment(record.attachment);\n },\n },\n ],\n variant: 'base-secondary',\n width: 160,\n }),\n [],\n );\n const signatureRows = useMemo(\n (): SignatureRow[] =>\n signatures.map((signature) => ({\n algorithm: signature.algorithm,\n hashLabel: readShortHash(signature.signedPayloadHash),\n key: signature.id,\n keyVersion: signature.keyVersion,\n signedAtLabel: formatDateTime(signature.signedAt),\n signerMemberId: signature.signerMemberId,\n })),\n [signatures],\n );\n const signatureColumns = useMemo(\n (): TableColumn<SignatureRow>[] => [\n {\n dataIndex: 'signerMemberId',\n key: 'signerMemberId',\n title: '簽章者',\n width: 160,\n },\n { dataIndex: 'algorithm', key: 'algorithm', title: '演算法', width: 150 },\n {\n dataIndex: 'keyVersion',\n key: 'keyVersion',\n title: 'Key 版本',\n width: 100,\n },\n {\n dataIndex: 'hashLabel',\n key: 'hashLabel',\n title: 'Payload Hash',\n width: 180,\n },\n {\n dataIndex: 'signedAtLabel',\n key: 'signedAtLabel',\n title: '簽章時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function refreshInstance(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n const nextRecord = await readApprovalInstance(instanceId);\n setActivityLogs(nextRecord.activityLogs);\n setInstance(nextRecord.instance);\n setTasks(nextRecord.tasks);\n setWorkflowTokens(nextRecord.workflowTokens);\n const [\n nextTaskDecisions,\n nextMemberProfiles,\n nextAttachments,\n nextSignatures,\n ] = await Promise.all([\n readTaskDecisionsForTasks(nextRecord.tasks),\n readMemberProfilesForTimeline(nextRecord),\n listAttachments(nextRecord.instance.id),\n readInstanceSignatures(nextRecord.instance.id),\n ]);\n setTaskDecisions(nextTaskDecisions);\n setMemberProfiles(nextMemberProfiles);\n setAttachments(nextAttachments);\n setSignatures(nextSignatures.signatures);\n setSignatureVerification(nextSignatures.verification);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n async function handleDownloadAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentDownloadUrl({\n id: attachment.id,\n });\n\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n\n async function handlePreviewAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentPreviewUrl({\n id: attachment.id,\n });\n\n setPreviewAttachment(attachment);\n setPreviewUrl(url);\n }\n\n async function handleDecision({\n action,\n comment,\n returnToNodeId = null,\n transferToMemberId = null,\n }: Readonly<{\n action: 'APPROVED' | 'REJECTED' | 'RETURNED' | 'TRANSFERRED';\n comment: string | null;\n returnToNodeId?: string | null;\n transferToMemberId?: string | null;\n }>): Promise<void> {\n if (!currentMemberId || !currentTask) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await decideTask({\n action,\n comment,\n decidedByMemberId: currentMemberId,\n returnToNodeId,\n taskId: currentTask.id,\n transferToMemberId,\n });\n setRejectReasonModalOpen(false);\n setReturnModalOpen(false);\n setTransferModalOpen(false);\n setRejectReason('');\n setReturnComment('');\n setTransferComment('');\n setTransferMember(null);\n setReturnTargetNodeId(null);\n setRejectReasonError(null);\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n function openRejectReasonModal(): void {\n setRejectReason('');\n setRejectReasonError(null);\n setRejectReasonModalOpen(true);\n }\n\n function closeRejectReasonModal(): void {\n if (deciding) {\n return;\n }\n\n setRejectReasonModalOpen(false);\n setRejectReason('');\n setRejectReasonError(null);\n }\n\n function openReturnModal(): void {\n setReturnComment('');\n setReturnTargetNodeId(returnTargetOptions[0]?.id ?? null);\n setReturnModalOpen(true);\n }\n\n function closeReturnModal(): void {\n if (deciding) {\n return;\n }\n\n setReturnModalOpen(false);\n setReturnComment('');\n setReturnTargetNodeId(null);\n }\n\n function openTransferModal(): void {\n setTransferComment('');\n setTransferMember(null);\n setTransferModalOpen(true);\n void handleSearchTransferMembers('');\n }\n\n function closeTransferModal(): void {\n if (deciding) {\n return;\n }\n\n setTransferModalOpen(false);\n setTransferComment('');\n setTransferMember(null);\n }\n\n async function handleSearchTransferMembers(\n searchText: string,\n ): Promise<void> {\n setTransferMemberLoading(true);\n\n try {\n setTransferMemberOptions(\n (await searchMembers(searchText))\n .filter((searchedMember) => searchedMember.memberId !== currentMemberId)\n .map(readMemberOption),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setTransferMemberLoading(false);\n }\n }\n\n async function handleRejectConfirm(): Promise<void> {\n if (!trimmedRejectReason) {\n setRejectReasonError('請輸入拒絕原因');\n return;\n }\n\n await handleDecision({\n action: 'REJECTED',\n comment: trimmedRejectReason,\n });\n }\n\n async function handleTransferConfirm(): Promise<void> {\n if (!transferMember) {\n setError('請選擇轉派對象');\n return;\n }\n\n await handleDecision({\n action: 'TRANSFERRED',\n comment: trimmedTransferComment || null,\n transferToMemberId: transferMember.id,\n });\n }\n\n async function handleReturnConfirm(): Promise<void> {\n await handleDecision({\n action: 'RETURNED',\n comment: trimmedReturnComment || null,\n returnToNodeId: selectedReturnTargetOption?.id ?? null,\n });\n }\n\n async function handleCancelInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canCancelInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n setResubmitFormErrors({});\n\n if (\n instance.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema\n ) {\n const validation = validateFormRendererValues({\n schema: instance.formDefinitionSnapshot.schema,\n uiSchema: instance.formDefinitionSnapshot.uiSchema,\n values: resubmitFormData,\n });\n\n if (!validation.valid) {\n setResubmitFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setDeciding(false);\n\n return;\n }\n }\n\n try {\n await cancelApprovalInstance({\n cancelledByMemberId: currentMemberId,\n comment: trimmedCancelComment || null,\n instanceId: instance.id,\n });\n setCancelComment('');\n setCancelModalOpen(false);\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n async function handleResubmitInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canResubmitInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await resubmitApprovalInstance({\n formData: resubmitFormData,\n initiatorMemberId: currentMemberId,\n instanceId: instance.id,\n title: instance.title,\n });\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n instance\n ? `${readInstanceStateLabel(instance.state)} · ${formatDateTime(\n instance.startedAt,\n )}`\n : '載入案件內容。'\n }\n title={instance?.title ?? '簽核案件'}\n >\n {instance ? (\n <Button\n aria-label=\"查看流程圖\"\n icon={ShareIcon}\n iconType=\"icon-only\"\n onClick={(): void => setWorkflowModalOpen(true)}\n title=\"查看流程圖\"\n variant=\"base-secondary\"\n >\n 流程圖\n </Button>\n ) : null}\n {canCancelInstance ? (\n <Button\n disabled={deciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n onClick={(): void => setCancelModalOpen(true)}\n variant=\"destructive-secondary\"\n >\n 取消案件\n </Button>\n ) : null}\n {currentTask ? (\n <>\n {canReturnCurrentTask ? (\n <Button\n disabled={deciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n onClick={openReturnModal}\n variant=\"base-secondary\"\n >\n 退回\n </Button>\n ) : null}\n <Button\n disabled={deciding}\n icon={UserIcon}\n iconType=\"leading\"\n onClick={openTransferModal}\n variant=\"base-secondary\"\n >\n 轉派\n </Button>\n <Button\n disabled={deciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n onClick={openRejectReasonModal}\n variant=\"destructive-secondary\"\n >\n 拒絕\n </Button>\n <Button\n disabled={deciding}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={(): void =>\n void handleDecision({ action: 'APPROVED', comment: null })\n }\n variant=\"base-primary\"\n >\n 同意\n </Button>\n </>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={SECTION_BODY_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n {instance?.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema ? (\n <>\n <FormRenderer\n errors={resubmitFormErrors}\n onChange={(values): void => {\n setResubmitFormData(values);\n setResubmitFormErrors({});\n }}\n onUploadAttachment={\n canResubmitInstance ? handleUploadAttachment : undefined\n }\n readonly={!canResubmitInstance}\n schema={instance.formDefinitionSnapshot.schema}\n uiSchema={instance.formDefinitionSnapshot.uiSchema}\n value={\n canResubmitInstance ? resubmitFormData : instance.formData\n }\n />\n {canResubmitInstance ? (\n <div style={BUTTON_ROW_STYLE}>\n <Button\n disabled={deciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n onClick={(): void => void handleResubmitInstance()}\n variant=\"base-primary\"\n >\n 重新送出\n </Button>\n </div>\n ) : null}\n </>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有可顯示的表單快照。\n </Typography>\n )}\n </div>\n </Section>\n\n <Section>\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 附件\n </Typography>\n {attachmentRows.length > 0 ? (\n <Table\n actions={attachmentActions}\n columns={attachmentColumns}\n dataSource={attachmentRows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有附件。\n </Typography>\n )}\n </div>\n </Section>\n\n <Section>\n <Typography component=\"h2\" variant=\"h3\">\n 任務\n </Typography>\n <Table columns={taskColumns} dataSource={taskRows} fullWidth />\n </Section>\n\n <Section>\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 簽章\n </Typography>\n <Typography\n color={\n signatureVerification?.valid ? 'text-success' : 'text-error'\n }\n variant=\"body\"\n >\n {signatureVerification\n ? signatureVerification.valid\n ? `簽章鏈已驗證,共 ${signatureVerification.checkedCount} 筆。`\n : `簽章鏈驗證失敗:${signatureVerification.errors.join('、')}`\n : '尚無簽章紀錄。'}\n </Typography>\n {signatureRows.length > 0 ? (\n <Table\n columns={signatureColumns}\n dataSource={signatureRows}\n fullWidth\n />\n ) : null}\n </div>\n </Section>\n\n <Section>\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 歷程\n </Typography>\n {activitySteps.length > 0 ? (\n <Stepper\n currentStep={currentActivityStep}\n orientation=\"vertical\"\n type=\"dot\"\n >\n {activitySteps.map((activityStep) => (\n <ActivityHistoryStep\n descriptionParts={activityStep.descriptionParts}\n error={activityStep.error}\n forcePending={activityStep.forcePending}\n key={activityStep.id}\n title={activityStep.title}\n />\n ))}\n </Stepper>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 尚無歷程紀錄。\n </Typography>\n )}\n </div>\n </Section>\n </SectionGroup>\n\n {instance ? (\n <Modal\n modalType=\"standard\"\n onClose={(): void => setWorkflowModalOpen(false)}\n open={workflowModalOpen}\n showModalHeader\n size=\"wide\"\n supportingText={`${readInstanceStateLabel(\n instance.state,\n )} · ${formatDateTime(instance.startedAt)}`}\n title=\"流程圖\"\n >\n <div style={FLOW_MODAL_BODY_STYLE}>\n <div style={FLOW_CANVAS_STYLE}>\n <ReactFlow\n edges={flowEdges}\n fitView\n fitViewOptions={{ padding: 0.18 }}\n maxZoom={1.2}\n minZoom={0.2}\n nodes={flowNodes}\n nodesDraggable={false}\n nodesFocusable={false}\n nodeTypes={READONLY_FLOW_NODE_TYPES}\n panOnDrag\n proOptions={{ hideAttribution: true }}\n >\n <Background />\n <Controls showInteractive={false} />\n </ReactFlow>\n </div>\n {edgeSummaries.length > 0 ? (\n <div style={EDGE_SUMMARY_STYLE}>\n {edgeSummaries.map((summary) => (\n <span key={summary} style={EDGE_SUMMARY_ITEM_STYLE}>\n {summary}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n </Modal>\n ) : null}\n <Modal\n modalType=\"standard\"\n onClose={(): void => {\n setPreviewAttachment(null);\n setPreviewUrl(null);\n }}\n open={Boolean(previewAttachment && previewUrl)}\n showModalHeader\n size=\"wide\"\n supportingText={previewAttachment?.filename ?? undefined}\n title=\"PDF 預覽\"\n >\n {previewUrl ? (\n <PDFPreview\n filename={previewAttachment?.filename ?? 'PDF 預覽'}\n fileUrl={previewUrl}\n onDownload={\n previewAttachment\n ? (): void => void handleDownloadAttachment(previewAttachment)\n : undefined\n }\n />\n ) : null}\n </Modal>\n <Modal\n cancelText=\"保留案件\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"確認取消\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setCancelModalOpen(false)}\n onClose={(): void => setCancelModalOpen(false)}\n onConfirm={(): void => void handleCancelInstance()}\n open={cancelModalOpen}\n showModalFooter\n showModalHeader\n supportingText=\"取消後會關閉目前待簽任務與候選簽核人。\"\n title=\"取消案件\"\n >\n <div style={SECTION_BODY_STYLE}>\n <Typography variant=\"body\">\n 確定要取消「{instance?.title ?? ''}」嗎?\n </Typography>\n <BPMFormField label=\"取消原因\" name=\"cancelComment\">\n <Textarea\n onChange={(event): void =>\n setCancelComment(event.target.value)\n }\n placeholder=\"可填寫取消原因\"\n resize=\"vertical\"\n rows={3}\n value={cancelComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !trimmedRejectReason,\n variant: 'destructive-primary',\n }}\n confirmText=\"送出拒絕\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={closeRejectReasonModal}\n onClose={closeRejectReasonModal}\n onConfirm={(): void => void handleRejectConfirm()}\n open={rejectReasonModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"拒絕案件時必須留下原因,供發起人與後續追蹤查看。\"\n title=\"拒絕原因\"\n >\n <div style={REJECT_REASON_FORM_STYLE}>\n <BPMFormField label=\"拒絕原因\" name=\"rejectReason\" required>\n <Textarea\n autoFocus\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setRejectReason(event.target.value);\n setRejectReasonError(null);\n }}\n placeholder=\"請說明拒絕原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n type={rejectReasonError ? 'error' : 'default'}\n value={rejectReason}\n />\n </BPMFormField>\n {rejectReasonError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {rejectReasonError}\n </Typography>\n ) : null}\n </div>\n </Modal>\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !transferMember,\n }}\n confirmText=\"送出轉派\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeTransferModal}\n onClose={closeTransferModal}\n onConfirm={(): void => void handleTransferConfirm()}\n open={transferModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"轉派後,原任務會保留轉派紀錄,新的待簽任務會指派給指定成員。\"\n title=\"轉派簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"轉派對象\" name=\"transferToMemberId\" required>\n <AutoComplete\n asyncData\n disabledOptionsFilter\n emptyText=\"沒有符合的成員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name: 'transfer-member-search',\n spellCheck: false,\n }}\n loading={transferMemberLoading}\n loadingText=\"搜尋成員中...\"\n mode=\"single\"\n onChange={(option): void =>\n setTransferMember(readMemberOptionFromValue(option))\n }\n onSearch={handleSearchTransferMembers}\n onSearchTextChange={(searchText): void =>\n setTransferMember(\n readUniqueMemberOption(searchText, transferMemberOptions),\n )\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearchTransferMembers('');\n }\n }}\n options={[...transferMemberOptions]}\n placeholder=\"搜尋姓名或信箱\"\n searchDebounceTime={300}\n value={transferMember}\n />\n </BPMFormField>\n <BPMFormField label=\"轉派說明\" name=\"transferComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setTransferComment(event.target.value)\n }\n placeholder=\"可補充轉派原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={transferComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !selectedReturnTargetOption,\n }}\n confirmText=\"送出退回\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeReturnModal}\n onClose={closeReturnModal}\n onConfirm={(): void => void handleReturnConfirm()}\n open={returnModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"退回後,流程會回到指定節點並等待重新處理。\"\n title=\"退回簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"退回節點\" name=\"returnTargetNodeId\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setReturnTargetNodeId(option?.id ?? null)\n }\n options={[...returnTargetOptions]}\n placeholder=\"選擇退回節點\"\n value={selectedReturnTargetOption}\n />\n </BPMFormField>\n <BPMFormField label=\"退回說明\" name=\"returnComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setReturnComment(event.target.value)\n }\n placeholder=\"可補充需要修改的內容\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={returnComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nfunction formatFileSize(sizeBytes: number): string {\n if (!Number.isFinite(sizeBytes) || sizeBytes <= 0) {\n return '-';\n }\n\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n if (sizeBytes < 1024 * 1024) {\n return `${(sizeBytes / 1024).toFixed(1)} KB`;\n }\n\n return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\nfunction readShortHash(hash: string): string {\n return hash.length > 16 ? `${hash.slice(0, 12)}...` : hash;\n}\n\nfunction joinClassNames(\n ...classNames: readonly (string | null | undefined)[]\n): string {\n return classNames\n .filter((className): className is string =>\n isPresentText(className ?? null),\n )\n .join(' ');\n}\n\ninterface ActivityHistoryStepProps extends StepProps {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly forcePending?: boolean;\n}\n\nconst ActivityHistoryStep = forwardRef<\n HTMLDivElement,\n ActivityHistoryStepProps\n>(function ActivityHistoryStep(\n {\n className,\n descriptionParts,\n error,\n forcePending = false,\n index = 0,\n orientation,\n status = 'pending',\n title,\n type = 'number',\n ...rest\n },\n ref,\n): ReactElement {\n const displayStatus = forcePending ? 'pending' : status;\n\n return (\n <div\n {...rest}\n className={joinClassNames(\n stepClasses.host,\n type === 'dot' ? stepClasses.dot : null,\n error && displayStatus !== 'processing' ? stepClasses.error : null,\n orientation === 'horizontal' ? stepClasses.horizontal : null,\n type === 'number' ? stepClasses.number : null,\n displayStatus === 'pending' ? stepClasses.pending : null,\n displayStatus === 'processing' ? stepClasses.processing : null,\n error && displayStatus === 'processing'\n ? stepClasses.processingError\n : null,\n !error && displayStatus === 'succeeded' ? stepClasses.succeeded : null,\n orientation === 'vertical' ? stepClasses.vertical : null,\n className,\n )}\n ref={ref}\n >\n {type === 'dot' ? (\n <span\n className={joinClassNames(\n stepClasses.statusIndicator,\n stepClasses.statusIndicatorDot,\n )}\n />\n ) : (\n <span className={stepClasses.statusIndicator}>{index + 1}</span>\n )}\n <div className={stepClasses.textContainer}>\n <Typography\n className={stepClasses.title}\n variant=\"label-primary-highlight\"\n >\n {title}\n <span className={stepClasses.titleConnectLine} />\n </Typography>\n {descriptionParts.length > 0 ? (\n <Typography className={stepClasses.description} variant=\"caption\">\n {descriptionParts.map((part, partIndex) => (\n <Fragment key={`${part.type}-${partIndex}`}>\n {partIndex > 0 ? ' · ' : null}\n {renderActivityDescriptionPart(part)}\n </Fragment>\n ))}\n </Typography>\n ) : null}\n </div>\n </div>\n );\n});\n\nfunction renderActivityDescriptionPart(\n part: ActivityStepDescriptionPart,\n): ReactElement | string {\n if (part.type === 'text') {\n return part.text;\n }\n\n if (part.type === 'dangerText') {\n return <span style={HISTORY_DANGER_TEXT_STYLE}>{part.text}</span>;\n }\n\n if (!part.email) {\n return `${part.prefix}:${part.label}`;\n }\n\n return (\n <>\n {part.prefix}:\n <Tooltip title={part.email}>\n {({ onMouseEnter, onMouseLeave, ref }): ReactElement => (\n <span\n data-testid={\n part.memberId ? `member-tooltip-${part.memberId}` : undefined\n }\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n ref={ref as RefCallback<HTMLSpanElement>}\n style={HISTORY_MEMBER_NAME_STYLE}\n >\n {part.label}\n </span>\n )}\n </Tooltip>\n </>\n );\n}\n\nasync function readMemberProfilesForTimeline({\n activityLogs,\n tasks,\n}: {\n readonly activityLogs: readonly ActivityLogRecord[];\n readonly tasks: readonly TaskRecord[];\n}): Promise<readonly MemberProfileRecord[]> {\n const memberIds = [\n ...new Set(\n [\n ...activityLogs.map((activityLog) => activityLog.actorMemberId),\n ...tasks.map((task) => task.assigneeMemberId),\n ...tasks.map((task) => task.originalAssigneeMemberId),\n ...tasks.flatMap((task) => task.candidateMemberIds),\n ...tasks.flatMap((task) =>\n readDelegationChain(task.delegationChainJson).flatMap((step) => [\n step.from,\n step.to,\n ]),\n ),\n ].filter(isPresentText),\n ),\n ];\n\n try {\n return await resolveMemberProfiles(memberIds);\n } catch {\n return [];\n }\n}\n\nasync function readTaskDecisionsForTasks(\n tasks: readonly TaskRecord[],\n): Promise<readonly TaskDecisionRecord[]> {\n const decisionLists = await Promise.all(\n tasks.map((task) => listTaskDecisions(task.id)),\n );\n\n return decisionLists.flat();\n}\n\nfunction readLatestTaskDecisionsByTaskId(\n taskDecisions: readonly TaskDecisionRecord[],\n): ReadonlyMap<string, TaskDecisionRecord> {\n return taskDecisions.reduce<ReadonlyMap<string, TaskDecisionRecord>>(\n (decisionsByTaskId, decision) => {\n const currentDecision = decisionsByTaskId.get(decision.taskId);\n const nextDecision =\n !currentDecision ||\n new Date(decision.decidedAt).getTime() >\n new Date(currentDecision.decidedAt).getTime()\n ? decision\n : currentDecision;\n\n return new Map(decisionsByTaskId).set(decision.taskId, nextDecision);\n },\n new Map(),\n );\n}\n\nfunction readActivityStepRecords(\n activityLogs: readonly ActivityLogRecord[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n workflow: WorkflowDefinition | null,\n instanceState: ApprovalInstanceRecord['state'],\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n): ActivityStepRecord[] {\n const historySteps = activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog): ActivityStepRecord => {\n const payload = readActivityPayload(activityLog);\n const nodeLabel = readActivityNodeLabel(activityLog.nodeId, workflow);\n const descriptionParts = [\n readTextDescriptionPart(\n nodeLabel ? `節點:${nodeLabel}` : '節點:全流程',\n ),\n readMemberDescriptionPart(\n '操作者',\n activityLog.actorMemberId,\n memberProfilesById,\n '系統',\n ),\n readTextDescriptionPart(\n `時間:${formatActivityDateTime(activityLog.createdAt)}`,\n ),\n ...readActivityDetailParts(\n activityLog,\n payload,\n workflow,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n memberProfilesById,\n ),\n ].filter(isActivityDescriptionPart);\n\n return {\n descriptionParts,\n error: isActivityError(activityLog, payload),\n id: activityLog.id,\n title: readActivityEventLabel(activityLog.eventType, payload),\n };\n });\n const pendingTaskSteps = tasks.filter(isPendingTask).map(\n (task): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `節點:${readNodeDisplayLabel(task.nodeId, workflow)}`,\n ),\n readMemberDescriptionPart(\n '處理者',\n task.assigneeMemberId,\n memberProfilesById,\n '未指定',\n ),\n readTextDescriptionPart(\n `建立時間:${formatActivityDateTime(task.createdAt)}`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n id: `pending-task-${task.id}`,\n title: task.status === 'IN_PROGRESS' ? '簽核處理中' : '等待簽核處理',\n }),\n );\n const representedNodeIds = new Set(\n [\n ...activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog) => activityLog.nodeId),\n ...tasks.map((task) => task.nodeId),\n ].filter(isPresentText),\n );\n const futureNodeSteps = workflow\n ? readFutureTimelineNodes(\n workflow,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ).map(\n (node): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `${readNodeKindLabel(node.type)} · 尚未抵達`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n forcePending: true,\n id: `future-node-${node.id}`,\n title: readFutureNodeStepTitle(node),\n }),\n )\n : [];\n\n return [...historySteps, ...pendingTaskSteps, ...futureNodeSteps];\n}\n\nfunction readTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'text' } : null;\n}\n\nfunction readDangerTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'dangerText' } : null;\n}\n\nfunction readMemberDescriptionPart(\n prefix: string,\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n fallbackLabel: string,\n): ActivityStepDescriptionPart {\n const profile = memberId ? memberProfilesById.get(memberId) : null;\n\n return {\n email: profile?.email ?? null,\n label: profile?.name ?? fallbackLabel,\n memberId,\n prefix,\n type: 'member',\n };\n}\n\nfunction readMemberDisplayText(\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n if (!memberId) {\n return '-';\n }\n\n const profile = memberProfilesById.get(memberId);\n\n return profile ? `${profile.name}(${profile.email})` : memberId;\n}\n\nfunction isActivityDescriptionPart(\n part: ActivityStepDescriptionPart | null,\n): part is ActivityStepDescriptionPart {\n return Boolean(part);\n}\n\nfunction readCurrentActivityStep(\n activitySteps: readonly ActivityStepRecord[],\n): number {\n const firstPendingStepIndex = activitySteps.findIndex(\n (activityStep) =>\n activityStep.id.startsWith('pending-task-') ||\n activityStep.id.startsWith('future-node-'),\n );\n\n return firstPendingStepIndex === -1\n ? activitySteps.length\n : firstPendingStepIndex;\n}\n\nfunction isUserMeaningfulActivity(activityLog: ActivityLogRecord): boolean {\n return (\n activityLog.eventType === 'INSTANCE_STARTED' ||\n activityLog.eventType === 'TASK_DECIDED' ||\n activityLog.eventType === 'SLA_TRIGGERED'\n );\n}\n\nfunction isFutureTimelineNode(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): boolean {\n if (node.type === 'startEvent' || representedNodeIds.has(node.id)) {\n return false;\n }\n\n if (instanceState === 'REJECTED') {\n return true;\n }\n\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return state.tone === 'neutral' || state.tone === 'waiting';\n}\n\nfunction readFutureTimelineNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): readonly WorkflowNode[] {\n if (instanceState !== 'RUNNING' && instanceState !== 'REJECTED') {\n return [];\n }\n\n const futureNodes = workflow.nodes.filter((node) =>\n isFutureTimelineNode(\n node,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ),\n );\n const reachableDistances = readReachableFutureNodeDistances(\n workflow,\n futureNodes,\n tasks,\n tokens,\n representedNodeIds,\n );\n const originalNodeIndexes = new Map(\n workflow.nodes.map((node, index) => [node.id, index]),\n );\n\n return futureNodes\n .filter((node) => reachableDistances.has(node.id))\n .sort((left, right) => {\n const leftDistance = reachableDistances.get(left.id) ?? 0;\n const rightDistance = reachableDistances.get(right.id) ?? 0;\n\n if (leftDistance !== rightDistance) {\n return leftDistance - rightDistance;\n }\n\n if (left.position.x !== right.position.x) {\n return left.position.x - right.position.x;\n }\n\n if (left.position.y !== right.position.y) {\n return left.position.y - right.position.y;\n }\n\n return (\n (originalNodeIndexes.get(left.id) ?? 0) -\n (originalNodeIndexes.get(right.id) ?? 0)\n );\n });\n}\n\nfunction readReachableFutureNodeDistances(\n workflow: WorkflowDefinition,\n futureNodes: readonly WorkflowNode[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const futureNodeIds = new Set(futureNodes.map((node) => node.id));\n const outgoingNodeIds = workflow.edges.reduce<\n ReadonlyMap<string, readonly string[]>\n >((groups, edge) => {\n const nextTargets = [...(groups.get(edge.source) ?? []), edge.target];\n\n return new Map(groups).set(edge.source, nextTargets);\n }, new Map());\n const frontierNodeIds = readFutureTimelineFrontierNodeIds(\n workflow,\n tasks,\n tokens,\n representedNodeIds,\n );\n\n return frontierNodeIds.reduce<ReadonlyMap<string, number>>(\n (distances, nodeId) =>\n mergeFutureNodeDistances(\n distances,\n readFutureNodeDistancesFrom(nodeId, outgoingNodeIds, futureNodeIds),\n ),\n new Map(),\n );\n}\n\nfunction readFutureTimelineFrontierNodeIds(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): readonly string[] {\n const tokenNodeIds = tokens\n .filter((token) => token.status === 'ACTIVE' || token.status === 'WAITING')\n .map((token) => token.currentNodeId);\n const pendingTaskNodeIds = tasks\n .filter(isPendingTask)\n .map((task) => task.nodeId);\n const representedFrontierNodeIds = workflow.nodes\n .filter((node) => representedNodeIds.has(node.id))\n .map((node) => node.id);\n const activeFrontierNodeIds = [\n ...new Set([\n ...tokenNodeIds,\n ...pendingTaskNodeIds,\n ...representedFrontierNodeIds,\n ]),\n ];\n const startNodeIds = workflow.nodes\n .filter((node) => node.type === 'startEvent')\n .map((node) => node.id);\n\n return activeFrontierNodeIds.length > 0\n ? activeFrontierNodeIds\n : startNodeIds;\n}\n\nfunction readFutureNodeDistancesFrom(\n startNodeId: string,\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const initialQueue: readonly {\n readonly distance: number;\n readonly nodeId: string;\n }[] = [{ distance: 0, nodeId: startNodeId }];\n\n return walkFutureNodeDistances(initialQueue, outgoingNodeIds, futureNodeIds);\n}\n\nfunction walkFutureNodeDistances(\n queue: readonly { readonly distance: number; readonly nodeId: string }[],\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n visitedNodeIds: ReadonlySet<string> = new Set(),\n distances: ReadonlyMap<string, number> = new Map(),\n): ReadonlyMap<string, number> {\n const [current, ...restQueue] = queue;\n\n if (!current) {\n return distances;\n }\n\n if (visitedNodeIds.has(current.nodeId)) {\n return walkFutureNodeDistances(\n restQueue,\n outgoingNodeIds,\n futureNodeIds,\n visitedNodeIds,\n distances,\n );\n }\n\n const nextVisitedNodeIds = new Set(visitedNodeIds).add(current.nodeId);\n const nextDistances = futureNodeIds.has(current.nodeId)\n ? new Map(distances).set(\n current.nodeId,\n Math.min(\n distances.get(current.nodeId) ?? current.distance,\n current.distance,\n ),\n )\n : distances;\n const nextQueue = [\n ...restQueue,\n ...(outgoingNodeIds.get(current.nodeId) ?? []).map((nodeId) => ({\n distance: current.distance + 1,\n nodeId,\n })),\n ];\n\n return walkFutureNodeDistances(\n nextQueue,\n outgoingNodeIds,\n futureNodeIds,\n nextVisitedNodeIds,\n nextDistances,\n );\n}\n\nfunction mergeFutureNodeDistances(\n currentDistances: ReadonlyMap<string, number>,\n nextDistances: ReadonlyMap<string, number>,\n): ReadonlyMap<string, number> {\n return [...nextDistances.entries()].reduce<ReadonlyMap<string, number>>(\n (mergedDistances, [nodeId, distance]) =>\n new Map(mergedDistances).set(\n nodeId,\n Math.min(mergedDistances.get(nodeId) ?? distance, distance),\n ),\n currentDistances,\n );\n}\n\nfunction readFutureNodeStepTitle(node: WorkflowNode): string {\n if (node.type === 'userTask') {\n return `未來簽核:${node.data.label}`;\n }\n\n if (node.type === 'serviceTask') {\n return `未來知會:${node.data.label}`;\n }\n\n if (node.type === 'exclusiveGateway') {\n return `未來分流:${node.data.label}`;\n }\n\n if (node.type === 'parallelGateway') {\n return `未來匯合:${node.data.label}`;\n }\n\n if (node.type === 'endEvent') {\n return `流程完成:${node.data.label}`;\n }\n\n return `未來節點:${node.data.label}`;\n}\n\nfunction readActivityPayload(\n activityLog: ActivityLogRecord,\n): Readonly<Record<string, unknown>> {\n try {\n const payload = JSON.parse(activityLog.payloadJson) as unknown;\n\n return isRecord(payload) ? payload : {};\n } catch {\n return {};\n }\n}\n\nfunction readActivityEventLabel(\n eventType: string,\n payload: Readonly<Record<string, unknown>>,\n): string {\n if (eventType === 'INSTANCE_STARTED') {\n return '案件已發起';\n }\n\n if (eventType === 'TOKEN_CREATED') {\n return '流程路徑已建立';\n }\n\n if (eventType === 'ENGINE_PROCESS_REQUESTED') {\n return '流程引擎已處理';\n }\n\n if (eventType === 'TOKEN_ADVANCED') {\n return '流程已前進';\n }\n\n if (eventType === 'TASK_CREATED') {\n return '待簽任務已建立';\n }\n\n if (eventType === 'TASK_DECIDED') {\n return readTaskDecisionEventLabel(readStringField(payload, 'action'));\n }\n\n if (eventType === 'SLA_TRIGGERED') {\n return '時限提醒已觸發';\n }\n\n return eventType;\n}\n\nfunction readTaskDecisionEventLabel(action: string | null): 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 readActivityDetail(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string | null {\n if (activityLog.eventType === 'TASK_CREATED') {\n const assigneeMemberId = readStringField(payload, 'assigneeMemberId');\n const originalAssigneeMemberId = readStringField(\n payload,\n 'originalAssigneeMemberId',\n );\n\n if (!assigneeMemberId) {\n const candidateMemberIds = readStringArrayField(\n payload,\n 'candidateMemberIds',\n );\n\n return candidateMemberIds.length\n ? `候選簽核人:${candidateMemberIds\n .map((memberId) =>\n readMemberDisplayText(memberId, memberProfilesById),\n )\n .join('、')}`\n : null;\n }\n\n const assigneeLabel = readMemberDisplayText(\n assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n originalAssigneeMemberId,\n memberProfilesById,\n );\n\n return originalAssigneeMemberId &&\n originalAssigneeMemberId !== assigneeMemberId\n ? `待簽人:${assigneeLabel}(原簽核人:${originalAssigneeLabel})`\n : `待簽人:${assigneeLabel}`;\n }\n\n if (activityLog.eventType === 'TASK_DECIDED') {\n const action = readStringField(payload, 'action');\n const comment = readStringField(payload, 'comment');\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n const transferToMemberId = readStringField(payload, 'transferToMemberId');\n\n return action === 'REJECTED' && comment\n ? [decisionLabel, `拒絕原因:${comment}`]\n .filter(isPresentText)\n .join(' · ')\n : action === 'TRANSFERRED'\n ? [\n decisionLabel,\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n ]\n .filter(isPresentText)\n .join(' · ')\n : decisionLabel;\n }\n\n if (activityLog.eventType === 'TOKEN_ADVANCED') {\n const action = readStringField(payload, 'action');\n\n if (action) {\n return `流程結果:${readTaskDecisionActionLabel(action)}`;\n }\n\n const arrivedCount = readNumberField(payload, 'arrivedCount');\n const requiredCount = readNumberField(payload, 'requiredCount');\n\n if (arrivedCount !== null && requiredCount !== null) {\n return `等待匯合:${arrivedCount}/${requiredCount}`;\n }\n\n const fromNodeId = readStringField(payload, 'fromNodeId');\n const toNodeId = readStringField(payload, 'toNodeId');\n\n if (fromNodeId && toNodeId) {\n return `由 ${readNodeDisplayLabel(fromNodeId, workflow)} 前進至 ${readNodeDisplayLabel(toNodeId, workflow)}`;\n }\n }\n\n if (activityLog.eventType === 'ENGINE_PROCESS_REQUESTED') {\n const state = readStringField(payload, 'state');\n\n return state ? `案件狀態:${readInstanceStateLabel(state)}` : null;\n }\n\n return null;\n}\n\nfunction readActivityDetailParts(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): readonly ActivityStepDescriptionPart[] {\n if (activityLog.eventType !== 'TASK_DECIDED') {\n return [\n readTextDescriptionPart(\n readActivityDetail(\n activityLog,\n payload,\n workflow,\n memberProfilesById,\n ),\n ),\n ].filter(isActivityDescriptionPart);\n }\n\n const taskDecision = activityLog.taskId\n ? taskDecisionsByTaskId.get(activityLog.taskId)\n : null;\n const action =\n readStringField(payload, 'action') ?? taskDecision?.action ?? null;\n const comment =\n readStringField(payload, 'comment') ?? taskDecision?.comment ?? null;\n const transferToMemberId =\n readStringField(payload, 'transferToMemberId') ??\n taskDecision?.transferToMemberId ??\n null;\n const signatureId =\n readStringField(payload, 'signatureId') ??\n taskDecision?.signatureId ??\n null;\n const signature = signatureId ? signaturesById.get(signatureId) : null;\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n return [\n readTextDescriptionPart(decisionLabel),\n action === 'REJECTED'\n ? readDangerTextDescriptionPart(`拒絕原因:${comment ?? '-'}`)\n : null,\n action === 'RETURNED'\n ? readTextDescriptionPart(`退回說明:${comment ?? '-'}`)\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n )\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(`轉派說明:${comment ?? '-'}`)\n : null,\n signature\n ? readTextDescriptionPart(\n signatureVerification?.valid\n ? `簽章:已驗證(${readShortHash(signature.signedPayloadHash)})`\n : `簽章:待檢查(${readShortHash(signature.signedPayloadHash)})`,\n )\n : null,\n ].filter(isActivityDescriptionPart);\n}\n\nfunction readActivityNodeLabel(\n nodeId: string | null,\n workflow: WorkflowDefinition | null,\n): string | null {\n return nodeId ? readNodeDisplayLabel(nodeId, workflow) : null;\n}\n\nfunction readNodeDisplayLabel(\n nodeId: string,\n workflow: WorkflowDefinition | null,\n): string {\n return (\n workflow?.nodes.find((node) => node.id === nodeId)?.data.label ?? nodeId\n );\n}\n\nfunction readReturnTargetOptions(\n workflow: WorkflowDefinition,\n node: WorkflowNode,\n): readonly { readonly id: string; readonly name: string }[] {\n if (node.type !== 'userTask' || !node.data.returnBehavior.allowReturn) {\n return [];\n }\n\n if (node.data.returnBehavior.allowedTargets === 'ANY') {\n return workflow.nodes\n .filter((candidate) => candidate.id !== node.id)\n .map((candidate) => ({\n id: candidate.id,\n name: `${candidate.data.label}(${readNodeKindLabel(candidate.type)})`,\n }));\n }\n\n const targetNodeId =\n node.data.returnBehavior.allowedTargets === 'INITIATOR'\n ? workflow.nodes.find((candidate) => candidate.type === 'startEvent')?.id\n : workflow.edges.find((edge) => edge.target === node.id)?.source;\n const targetNode = workflow.nodes.find(\n (candidate) => candidate.id === targetNodeId,\n );\n\n return targetNode\n ? [\n {\n id: targetNode.id,\n name: `${targetNode.data.label}(${readNodeKindLabel(\n targetNode.type,\n )})`,\n },\n ]\n : [];\n}\n\nfunction readTaskDecisionActionLabel(action: string): 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 action;\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 === 'CANCELLED') {\n return '已取消';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n return status;\n}\n\nfunction readTaskAssigneeLabel(\n task: TaskRecord,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord> = new Map(),\n): string {\n const delegationChain = readDelegationChain(task.delegationChainJson);\n\n if (!task.assigneeMemberId) {\n return task.candidateMemberIds.length\n ? `候選 ${task.candidateMemberIds\n .map((memberId) => readMemberDisplayText(memberId, memberProfilesById))\n .join('、')}`\n : '未指定';\n }\n\n const assigneeLabel = readMemberDisplayText(\n task.assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n task.originalAssigneeMemberId,\n memberProfilesById,\n );\n\n if (\n delegationChain.length === 0 ||\n task.originalAssigneeMemberId === task.assigneeMemberId\n ) {\n return assigneeLabel;\n }\n\n return `${assigneeLabel}(原:${originalAssigneeLabel})`;\n}\n\nfunction canMemberActOnTask(\n task: TaskRecord,\n memberId: string | null,\n): boolean {\n if (!memberId) {\n return false;\n }\n\n return (\n task.assigneeMemberId === memberId ||\n task.candidateMemberIds.includes(memberId)\n );\n}\n\nfunction readInstanceStateLabel(state: string): string {\n if (state === 'APPROVED') {\n return '已同意';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n return state;\n}\n\nfunction isActivityError(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n): boolean {\n return (\n activityLog.eventType === 'SLA_TRIGGERED' ||\n readStringField(payload, 'action') === 'REJECTED' ||\n readStringField(payload, 'instanceState') === 'REJECTED'\n );\n}\n\nfunction formatActivityDateTime(value: string): string {\n return formatDateTime(value);\n}\n\nfunction readStringField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): string | null {\n const value = record[key];\n\n return typeof value === 'string' ? value : null;\n}\n\nfunction readStringArrayField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): readonly string[] {\n const value = record[key];\n\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nfunction readMemberOption(profile: MemberProfileRecord): MemberOption {\n return {\n email: profile.email,\n id: profile.memberId,\n name: `${profile.name} · ${profile.email}`,\n };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const email = value.email;\n const id = value.id;\n const name = value.name;\n\n return typeof id === 'string' && typeof name === 'string'\n ? { email: typeof email === 'string' ? email : null, id, name }\n : null;\n}\n\nfunction readUniqueMemberOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalizedSearchText = searchText.trim().toLocaleLowerCase();\n\n if (!normalizedSearchText) {\n return null;\n }\n\n const matches = options.filter((option) =>\n [option.id, option.name, option.email ?? ''].some((value) =>\n value.toLocaleLowerCase().includes(normalizedSearchText),\n ),\n );\n\n return matches.length === 1 ? (matches[0] ?? null) : null;\n}\n\ninterface DelegationChainStep {\n readonly from: string;\n readonly reason: string;\n readonly ruleId: string | null;\n readonly to: string;\n}\n\nfunction readDelegationChain(value: string): readonly DelegationChainStep[] {\n try {\n const parsed = JSON.parse(value) as unknown;\n\n return Array.isArray(parsed)\n ? parsed\n .map((item): DelegationChainStep | null =>\n isRecord(item) ? readDelegationChainStep(item) : null,\n )\n .filter((item): item is DelegationChainStep => item !== null)\n : [];\n } catch {\n return [];\n }\n}\n\nfunction readDelegationChainStep(\n item: Readonly<Record<string, unknown>>,\n): DelegationChainStep | null {\n const from = readStringField(item, 'from');\n const to = readStringField(item, 'to');\n const reason = readStringField(item, 'reason');\n\n if (!from || !to || !reason) {\n return null;\n }\n\n return {\n from,\n reason,\n ruleId: readStringField(item, 'ruleId'),\n to,\n };\n}\n\nfunction readNumberField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): number | null {\n const value = record[key];\n\n return typeof value === 'number' ? value : null;\n}\n\nfunction isPresentText(value: string | null): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isPendingTask(task: TaskRecord): boolean {\n return task.status === 'PENDING' || task.status === 'IN_PROGRESS';\n}\n\nfunction WorkflowRuntimeNodeCard({\n data,\n}: NodeProps<RuntimeFlowNode>): ReactElement {\n return (\n <div style={readNodeStyle(data.tone)}>\n <Handle\n isConnectable={false}\n position={Position.Left}\n style={NODE_HANDLE_STYLE}\n type=\"target\"\n />\n <Typography\n component=\"span\"\n ellipsis\n title={data.label}\n variant=\"label-primary\"\n >\n {data.label}\n </Typography>\n <span style={readNodeStatusStyle(data.tone)}>{data.statusLabel}</span>\n <span title={data.secondaryLabel} style={NODE_SECONDARY_STYLE}>\n {data.secondaryLabel || data.kindLabel}\n </span>\n <Handle\n isConnectable={false}\n position={Position.Right}\n style={NODE_HANDLE_STYLE}\n type=\"source\"\n />\n </div>\n );\n}\n\nfunction readRuntimeFlowNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): RuntimeFlowNode[] {\n return workflow.nodes.map((node): RuntimeFlowNode => {\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return {\n data: {\n kindLabel: readNodeKindLabel(node.type),\n label: node.data.label,\n secondaryLabel: state.secondaryLabel,\n statusLabel: state.statusLabel,\n tone: state.tone,\n },\n id: node.id,\n position: node.position,\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n type: 'workflowRuntime',\n };\n });\n}\n\nfunction layoutRuntimeWorkflowDefinition(\n workflow: WorkflowDefinition,\n): WorkflowDefinition {\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n nodesep: 56,\n rankdir: 'LR',\n ranksep: 120,\n });\n workflow.nodes.forEach((node): void => {\n graph.setNode(node.id, {\n height: FLOW_NODE_LAYOUT_HEIGHT,\n width: FLOW_NODE_LAYOUT_WIDTH,\n });\n });\n workflow.edges.forEach((edge): void => {\n graph.setEdge(edge.source, edge.target);\n });\n dagre.layout(graph);\n\n return {\n ...workflow,\n nodes: workflow.nodes.map((node): WorkflowNode => {\n const positionedNode = graph.node(node.id) as\n | { readonly x: number; readonly y: number }\n | undefined;\n\n return positionedNode\n ? {\n ...node,\n position: {\n x: positionedNode.x - FLOW_NODE_LAYOUT_WIDTH / 2,\n y: positionedNode.y - FLOW_NODE_LAYOUT_HEIGHT / 2,\n },\n }\n : node;\n }),\n };\n}\n\nfunction readRuntimeFlowEdges(workflow: WorkflowDefinition): RuntimeFlowEdge[] {\n return workflow.edges.map((edge): RuntimeFlowEdge => {\n const label = readEdgeLabel(edge);\n\n return {\n animated: false,\n id: edge.id,\n label,\n labelBgBorderRadius: 6,\n labelBgPadding: [8, 4],\n labelBgStyle: {\n fill: edge.data.isDefault ? '#f8fafc' : '#eff6ff',\n stroke: edge.data.isDefault ? '#64748b' : '#2563eb',\n strokeWidth: 1,\n },\n labelShowBg: Boolean(label),\n labelStyle: {\n fill: edge.data.isDefault ? '#475569' : '#2563eb',\n fontSize: 12,\n fontWeight: 600,\n },\n source: edge.source,\n style: {\n stroke: '#475569',\n strokeWidth: 1.5,\n },\n target: edge.target,\n type: edge.type ?? 'smoothstep',\n };\n });\n}\n\nfunction readNodeRuntimeState(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): Readonly<{\n secondaryLabel: string;\n statusLabel: string;\n tone: RuntimeTone;\n}> {\n const nodeTasks = tasks.filter((task) => task.nodeId === node.id);\n const pendingTask = nodeTasks.find(\n (task) => task.status === 'PENDING' || task.status === 'IN_PROGRESS',\n );\n const cancelledTask = nodeTasks.find((task) => task.status === 'CANCELLED');\n const completedTask = nodeTasks.find((task) => task.status === 'COMPLETED');\n const nodeTokens = tokens.filter((token) => token.currentNodeId === node.id);\n const activeToken = nodeTokens.find((token) => token.status === 'ACTIVE');\n const waitingToken = nodeTokens.find((token) => token.status === 'WAITING');\n\n if (pendingTask) {\n return {\n secondaryLabel: `處理者 ${readTaskAssigneeLabel(pendingTask)}`,\n statusLabel: '待處理',\n tone: 'current',\n };\n }\n\n if (cancelledTask) {\n return {\n secondaryLabel: `已取消 ${readTaskAssigneeLabel(cancelledTask)}`,\n statusLabel: '已取消',\n tone: 'cancelled',\n };\n }\n\n if (completedTask) {\n return {\n secondaryLabel: `已完成 ${readTaskAssigneeLabel(completedTask)}`,\n statusLabel: '已完成',\n tone: 'completed',\n };\n }\n\n if (activeToken) {\n return {\n secondaryLabel: `token ${activeToken.id}`,\n statusLabel: '執行中',\n tone: 'current',\n };\n }\n\n if (waitingToken) {\n return {\n secondaryLabel: `token ${waitingToken.id}`,\n statusLabel: '等待前置',\n tone: 'waiting',\n };\n }\n\n if (node.type === 'startEvent') {\n return {\n secondaryLabel: '流程已發起',\n statusLabel: '已發起',\n tone: 'completed',\n };\n }\n\n if (node.type === 'endEvent' && instanceState !== 'RUNNING') {\n return {\n secondaryLabel: instanceState,\n statusLabel: instanceState === 'REJECTED' ? '已拒絕' : '已完成',\n tone: instanceState === 'REJECTED' ? 'cancelled' : 'completed',\n };\n }\n\n return {\n secondaryLabel: readNodeKindLabel(node.type),\n statusLabel: '未抵達',\n tone: 'neutral',\n };\n}\n\nfunction readNodeKindLabel(type: WorkflowNode['type']): string {\n if (type === 'startEvent') {\n return '開始';\n }\n\n if (type === 'endEvent') {\n return '完成';\n }\n\n if (type === 'userTask') {\n return '簽核節點';\n }\n\n if (type === 'serviceTask') {\n return '知會節點';\n }\n\n if (type === 'exclusiveGateway') {\n return '條件分流';\n }\n\n return '平行處理';\n}\n\nfunction readNodeStyle(tone: RuntimeTone): CSSProperties {\n if (tone === 'current') {\n return {\n ...NODE_STYLE,\n border: '1px solid var(--mzn-color-primary, #0057ff)',\n boxShadow: '0 0 0 3px rgba(0, 87, 255, 0.14)',\n };\n }\n\n if (tone === 'completed') {\n return {\n ...NODE_STYLE,\n border: '1px solid #16a34a',\n };\n }\n\n if (tone === 'cancelled') {\n return {\n ...NODE_STYLE,\n border: '1px solid #dc2626',\n opacity: 0.72,\n };\n }\n\n if (tone === 'waiting') {\n return {\n ...NODE_STYLE,\n border: '1px dashed #64748b',\n };\n }\n\n return NODE_STYLE;\n}\n\nfunction readNodeStatusStyle(tone: RuntimeTone): CSSProperties {\n const baseStyle = NODE_STATUS_STYLE;\n\n if (tone === 'current') {\n return { ...baseStyle, background: '#eff6ff', color: '#2563eb' };\n }\n\n if (tone === 'completed') {\n return { ...baseStyle, background: '#f0fdf4', color: '#15803d' };\n }\n\n if (tone === 'cancelled') {\n return { ...baseStyle, background: '#fef2f2', color: '#dc2626' };\n }\n\n if (tone === 'waiting') {\n return { ...baseStyle, background: '#f8fafc', color: '#475569' };\n }\n\n return { ...baseStyle, background: '#f1f5f9', color: '#64748b' };\n}\n\nfunction readEdgeLabel(edge: WorkflowDefinition['edges'][number]): string {\n if (edge.data.label) {\n return edge.data.label;\n }\n\n if (edge.data.isDefault) {\n return '其他情況';\n }\n\n return edge.data.condition ?? '';\n}\n\nfunction readEdgeSummaries(workflow: WorkflowDefinition): readonly string[] {\n return workflow.edges\n .map(readEdgeLabel)\n .filter((label) => label.trim().length > 0);\n}\n"],"mappings":"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"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { t as e } from "./bpm-form-field-Cao0rMol.js";
|
|
3
|
-
import { useEffect as t, useState as n } from "react";
|
|
4
|
-
import { Input as r, Modal as i, Typography as a } from "@mezzanine-ui/react";
|
|
5
|
-
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
6
|
-
//#region src/views/forms/form-name-modal.tsx
|
|
7
|
-
function c({ confirmText: c, initialName: u, loading: d, onClose: f, onSubmit: p, open: m, title: h }) {
|
|
8
|
-
let [g, _] = n(u), [v, y] = n(null), b = g.trim();
|
|
9
|
-
t(() => {
|
|
10
|
-
m && (_(u), y(null));
|
|
11
|
-
}, [u, m]);
|
|
12
|
-
async function x() {
|
|
13
|
-
if (!b) {
|
|
14
|
-
y("請輸入表單名稱");
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
try {
|
|
18
|
-
await p(b);
|
|
19
|
-
} catch (e) {
|
|
20
|
-
y(l(e));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return /* @__PURE__ */ s(i, {
|
|
24
|
-
cancelText: "取消",
|
|
25
|
-
confirmButtonProps: { disabled: !b },
|
|
26
|
-
confirmText: c,
|
|
27
|
-
loading: d,
|
|
28
|
-
modalType: "standard",
|
|
29
|
-
onCancel: f,
|
|
30
|
-
onClose: f,
|
|
31
|
-
onConfirm: () => void x(),
|
|
32
|
-
open: m,
|
|
33
|
-
showModalFooter: !0,
|
|
34
|
-
showModalHeader: !0,
|
|
35
|
-
size: "narrow",
|
|
36
|
-
title: h,
|
|
37
|
-
children: [/* @__PURE__ */ o(e, {
|
|
38
|
-
label: "表單名稱",
|
|
39
|
-
name: "formName",
|
|
40
|
-
required: !0,
|
|
41
|
-
children: /* @__PURE__ */ o(r, {
|
|
42
|
-
autoFocus: !0,
|
|
43
|
-
fullWidth: !0,
|
|
44
|
-
onChange: (e) => {
|
|
45
|
-
_(e.target.value), y(null);
|
|
46
|
-
},
|
|
47
|
-
placeholder: "例如:費用申請單",
|
|
48
|
-
value: g,
|
|
49
|
-
variant: "base"
|
|
50
|
-
})
|
|
51
|
-
}), v ? /* @__PURE__ */ o(a, {
|
|
52
|
-
color: "text-error",
|
|
53
|
-
variant: "body",
|
|
54
|
-
children: v
|
|
55
|
-
}) : null]
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
function l(e) {
|
|
59
|
-
return e instanceof Error ? e.message : "發生未知錯誤";
|
|
60
|
-
}
|
|
61
|
-
//#endregion
|
|
62
|
-
export { c as t };
|
|
63
|
-
|
|
64
|
-
//# sourceMappingURL=form-name-modal-C3OEvkCV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"form-name-modal-C3OEvkCV.js","names":[],"sources":["../../src/views/forms/form-name-modal.tsx"],"sourcesContent":["'use client';\n\nimport { ChangeEvent, ReactElement, useEffect, useState } from 'react';\nimport { Input, Modal, Typography } from '@mezzanine-ui/react';\nimport { BPMFormField } from '../../components/bpm-form-field';\n\ninterface FormNameModalProps {\n readonly confirmText: string;\n readonly initialName: string;\n readonly loading: boolean;\n readonly onClose: () => void;\n readonly onSubmit: (name: string) => Promise<void>;\n readonly open: boolean;\n readonly title: string;\n}\n\nexport function FormNameModal({\n confirmText,\n initialName,\n loading,\n onClose,\n onSubmit,\n open,\n title,\n}: FormNameModalProps): ReactElement {\n const [name, setName] = useState(initialName);\n const [error, setError] = useState<string | null>(null);\n const trimmedName = name.trim();\n\n useEffect((): void => {\n if (!open) {\n return;\n }\n\n setName(initialName);\n setError(null);\n }, [initialName, open]);\n\n async function handleConfirm(): Promise<void> {\n if (!trimmedName) {\n setError('請輸入表單名稱');\n return;\n }\n\n try {\n await onSubmit(trimmedName);\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !trimmedName }}\n confirmText={confirmText}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={open}\n showModalFooter\n showModalHeader\n size=\"narrow\"\n title={title}\n >\n <BPMFormField label=\"表單名稱\" name=\"formName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:費用申請單\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":";;;;;;AAgBA,SAAgB,EAAc,EAC5B,gBACA,gBACA,YACA,YACA,aACA,SACA,YACmC;CACnC,IAAM,CAAC,GAAM,KAAW,EAAS,CAAW,GACtC,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,IAAc,EAAK,KAAK;CAE9B,QAAsB;EACf,MAIL,EAAQ,CAAW,GACnB,EAAS,IAAI;CACf,GAAG,CAAC,GAAa,CAAI,CAAC;CAEtB,eAAe,IAA+B;EAC5C,IAAI,CAAC,GAAa;GAChB,EAAS,SAAS;GAClB;EACF;EAEA,IAAI;GACF,MAAM,EAAS,CAAW;EAC5B,SAAS,GAAsB;GAC7B,EAAS,EAAiB,CAAW,CAAC;EACxC;CACF;CAEA,OACE,kBAAC,GAAD;EACE,YAAW;EACX,oBAAoB,EAAE,UAAU,CAAC,EAAY;EAChC;EACJ;EACT,WAAU;EACV,UAAU;EACD;EACT,iBAAuB,KAAK,EAAc;EACpC;EACN,iBAAA;EACA,iBAAA;EACA,MAAK;EACE;YAbT,CAeE,kBAAC,GAAD;GAAc,OAAM;GAAO,MAAK;GAAW,UAAA;aACzC,kBAAC,GAAD;IACE,WAAA;IACA,WAAA;IACA,WAAW,MAA+C;KAExD,AADA,EAAQ,EAAM,OAAO,KAAK,GAC1B,EAAS,IAAI;IACf;IACA,aAAY;IACZ,OAAO;IACP,SAAQ;GACT,CAAA;EACW,CAAA,GACb,IACC,kBAAC,GAAD;GAAY,OAAM;GAAa,SAAQ;aACpC;EACS,CAAA,IACV,IACC;;AAEX;AAEA,SAAS,EAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";const e=require("./bpm-form-field-Bc6k4ZEO.cjs");let t=require("react"),n=require("@mezzanine-ui/react"),r=require("react/jsx-runtime");function i({confirmText:i,initialName:o,loading:s,onClose:c,onSubmit:l,open:u,title:d}){let[f,p]=(0,t.useState)(o),[m,h]=(0,t.useState)(null),g=f.trim();(0,t.useEffect)(()=>{u&&(p(o),h(null))},[o,u]);async function _(){if(!g){h(`請輸入表單名稱`);return}try{await l(g)}catch(e){h(a(e))}}return(0,r.jsxs)(n.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!g},confirmText:i,loading:s,modalType:`standard`,onCancel:c,onClose:c,onConfirm:()=>void _(),open:u,showModalFooter:!0,showModalHeader:!0,size:`narrow`,title:d,children:[(0,r.jsx)(e.t,{label:`表單名稱`,name:`formName`,required:!0,children:(0,r.jsx)(n.Input,{autoFocus:!0,fullWidth:!0,onChange:e=>{p(e.target.value),h(null)},placeholder:`例如:費用申請單`,value:f,variant:`base`})}),m?(0,r.jsx)(n.Typography,{color:`text-error`,variant:`body`,children:m}):null]})}function a(e){return e instanceof Error?e.message:`發生未知錯誤`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
|
|
2
|
-
//# sourceMappingURL=form-name-modal-uZCHbtRH.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"form-name-modal-uZCHbtRH.cjs","names":[],"sources":["../../src/views/forms/form-name-modal.tsx"],"sourcesContent":["'use client';\n\nimport { ChangeEvent, ReactElement, useEffect, useState } from 'react';\nimport { Input, Modal, Typography } from '@mezzanine-ui/react';\nimport { BPMFormField } from '../../components/bpm-form-field';\n\ninterface FormNameModalProps {\n readonly confirmText: string;\n readonly initialName: string;\n readonly loading: boolean;\n readonly onClose: () => void;\n readonly onSubmit: (name: string) => Promise<void>;\n readonly open: boolean;\n readonly title: string;\n}\n\nexport function FormNameModal({\n confirmText,\n initialName,\n loading,\n onClose,\n onSubmit,\n open,\n title,\n}: FormNameModalProps): ReactElement {\n const [name, setName] = useState(initialName);\n const [error, setError] = useState<string | null>(null);\n const trimmedName = name.trim();\n\n useEffect((): void => {\n if (!open) {\n return;\n }\n\n setName(initialName);\n setError(null);\n }, [initialName, open]);\n\n async function handleConfirm(): Promise<void> {\n if (!trimmedName) {\n setError('請輸入表單名稱');\n return;\n }\n\n try {\n await onSubmit(trimmedName);\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !trimmedName }}\n confirmText={confirmText}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={open}\n showModalFooter\n showModalHeader\n size=\"narrow\"\n title={title}\n >\n <BPMFormField label=\"表單名稱\" name=\"formName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:費用申請單\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"qJAgBA,SAAgB,EAAc,CAC5B,cACA,cACA,UACA,UACA,WACA,OACA,SACmC,CACnC,GAAM,CAAC,EAAM,IAAA,EAAA,EAAA,UAAoB,CAAW,EACtC,CAAC,EAAO,IAAA,EAAA,EAAA,UAAoC,IAAI,EAChD,EAAc,EAAK,KAAK,GAE9B,EAAA,EAAA,eAAsB,CACf,IAIL,EAAQ,CAAW,EACnB,EAAS,IAAI,EACf,EAAG,CAAC,EAAa,CAAI,CAAC,EAEtB,eAAe,GAA+B,CAC5C,GAAI,CAAC,EAAa,CAChB,EAAS,SAAS,EAClB,MACF,CAEA,GAAI,CACF,MAAM,EAAS,CAAW,CAC5B,OAAS,EAAsB,CAC7B,EAAS,EAAiB,CAAW,CAAC,CACxC,CACF,CAEA,OACE,EAAA,EAAA,MAAC,EAAA,MAAD,CACE,WAAW,KACX,mBAAoB,CAAE,SAAU,CAAC,CAAY,EAChC,cACJ,UACT,UAAU,WACV,SAAU,EACD,UACT,cAAuB,KAAK,EAAc,EACpC,OACN,gBAAA,GACA,gBAAA,GACA,KAAK,SACE,iBAbT,EAeE,EAAA,EAAA,KAAC,EAAA,EAAD,CAAc,MAAM,OAAO,KAAK,WAAW,SAAA,aACzC,EAAA,EAAA,KAAC,EAAA,MAAD,CACE,UAAA,GACA,UAAA,GACA,SAAW,GAA+C,CACxD,EAAQ,EAAM,OAAO,KAAK,EAC1B,EAAS,IAAI,CACf,EACA,YAAY,WACZ,MAAO,EACP,QAAQ,MACT,CAAA,CACW,CAAA,EACb,GACC,EAAA,EAAA,KAAC,EAAA,WAAD,CAAY,MAAM,aAAa,QAAQ,gBACpC,CACS,CAAA,EACV,IACC,GAEX,CAEA,SAAS,EAAiB,EAAwB,CAChD,OAAO,aAAiB,MAAQ,EAAM,QAAU,QAClD"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";let e=require("react"),t=require("react/jsx-runtime");var n=(0,e.createContext)(null);function r({value:e,children:r}){return(0,t.jsx)(n.Provider,{value:e,children:r})}function i(){let t=(0,e.useContext)(n);if(!t)throw Error("useRouterAdapter must be used inside <RouterAdapterProvider>. In Next.js, wrap your app with <NextRouterAdapterProvider> from `@rytass/bpm-core-react/pages/router-adapter`.");return t}function a(){return typeof window>`u`?new URLSearchParams:new URLSearchParams(window.location.search)}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return r}});
|
|
2
|
-
//# sourceMappingURL=router-adapter-BybHrCNP.cjs.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";let e=require("react"),t=require("react/jsx-runtime");function n(){return{dashboard:()=>`/dashboard`,inbox:()=>`/inbox`,sent:()=>`/sent`,cc:()=>`/cc`,search:()=>`/search`,delegations:()=>`/delegations`,notifications:()=>`/notifications`,caseDetail:e=>`/instances/${e}`,caseNew:e=>e?`/instances/new?templateId=${encodeURIComponent(e)}`:`/instances/new`,templates:()=>`/templates`,templateDesigner:e=>`/templates/${e}/designer`,templateVersions:e=>`/templates/${e}/versions`,templateCategories:()=>`/templates/categories`,forms:()=>`/forms`,formBuilder:e=>`/forms/${e}/builder`,notificationSettings:()=>`/settings/notifications`,adminOrgs:()=>`/admin/orgs`,adminUsers:()=>`/admin/users`,adminDelegations:()=>`/admin/delegations`}}var r=(0,e.createContext)(null);function i({value:i,children:a}){let o=(0,e.useMemo)(()=>i??n(),[i]);return(0,t.jsx)(r.Provider,{value:o,children:a})}function a(){return(0,e.useContext)(r)??o}var o=n();Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
|
|
2
|
-
//# sourceMappingURL=routes-config-2aKbWq2H.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routes-config-2aKbWq2H.cjs","names":[],"sources":["../../src/lib/routes-config.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from 'react';\n\n/**\n * Framework-agnostic path mapping every BPM view uses for internal\n * cross-navigation. When a host embeds BPM under a non-root prefix\n * (e.g. `/workspace/bpm/*`) it provides its own implementation through\n * `<BPMRoutesProvider value={...}>`; otherwise the default factory\n * preserves the historical `/instances/:id`, `/templates`, etc. paths.\n *\n * Function-shape (instead of string templates) means:\n * - Optional and multi-param routes can branch on argument presence\n * (`caseNew(templateId?)`).\n * - Query-string composition stays inside the host's resolver, not the\n * view.\n * - TypeScript flags missing arguments at compile time.\n *\n * Mirror sibling: {@link RouterAdapter} owns *navigation primitives*\n * (`push`, `replace`, `pathname`); `BPMRoutes` owns *path strings*. The\n * two compose: views call `router.push(routes.caseDetail(id))`.\n */\nexport interface BPMRoutes {\n /** Workflow dashboard landing. Used by sidebar + dashboard tiles. */\n dashboard(): string;\n /** Inbox (待簽) — pending tasks assigned to the current member. */\n inbox(): string;\n /** Sent (我發起的) — instances the current member initiated. */\n sent(): string;\n /** CC (抄送給我) — instances the current member is copied on. */\n cc(): string;\n /** Cross-view search. */\n search(): string;\n /** Personal delegation rules. */\n delegations(): string;\n /**\n * Reserved for hosts that want a dedicated `/notifications` page —\n * BPM's built-in views do **not** navigate here by default (the\n * notification drawer mounted by `<BPMNextProviders>` is the primary\n * unread-notification UX). The `createDefaultBPMRoutes()` factory\n * returns `'/notifications'` so consumers can mount their own page\n * at that path if desired; no BPM-shipped `pages/notifications`\n * shim exists.\n */\n notifications(): string;\n\n /**\n * Detail page for one approval instance.\n *\n * @example default → `/instances/abc123`\n */\n caseDetail(instanceId: string): string;\n /**\n * Launch a new approval instance. When `templateId` is passed, the\n * launch form is pre-populated for that template — by default this is\n * appended as a `?templateId=` query string so the path itself stays\n * stable for routing.\n *\n * @example default `caseNew()` → `/instances/new`\n * @example default `caseNew('tpl-1')` → `/instances/new?templateId=tpl-1`\n */\n caseNew(templateId?: string): string;\n\n /** Template index. */\n templates(): string;\n /** Template designer (xyflow canvas). */\n templateDesigner(templateId: string): string;\n /** Template version history. */\n templateVersions(templateId: string): string;\n /** Template categories admin. */\n templateCategories(): string;\n\n /** Form definitions index. */\n forms(): string;\n /** Form-builder (CodeMirror schema editor + preview). */\n formBuilder(formId: string): string;\n\n /** Per-member notification preferences. */\n notificationSettings(): string;\n\n /** Admin: organization tree management. */\n adminOrgs(): string;\n /** Admin: member directory mapping. */\n adminUsers(): string;\n /** Admin: delegation rule management. */\n adminDelegations(): string;\n}\n\n/**\n * Factory for the default `BPMRoutes` value. Reproduces the exact path\n * literals BPM views used before `BPMRoutesContext` existed, so existing\n * hosts (no provider mounted) keep working unchanged.\n */\nexport function createDefaultBPMRoutes(): BPMRoutes {\n return {\n dashboard: () => '/dashboard',\n inbox: () => '/inbox',\n sent: () => '/sent',\n cc: () => '/cc',\n search: () => '/search',\n delegations: () => '/delegations',\n notifications: () => '/notifications',\n\n caseDetail: (instanceId) => `/instances/${instanceId}`,\n caseNew: (templateId) =>\n templateId\n ? `/instances/new?templateId=${encodeURIComponent(templateId)}`\n : '/instances/new',\n\n templates: () => '/templates',\n templateDesigner: (templateId) => `/templates/${templateId}/designer`,\n templateVersions: (templateId) => `/templates/${templateId}/versions`,\n templateCategories: () => '/templates/categories',\n\n forms: () => '/forms',\n formBuilder: (formId) => `/forms/${formId}/builder`,\n\n notificationSettings: () => '/settings/notifications',\n\n adminOrgs: () => '/admin/orgs',\n adminUsers: () => '/admin/users',\n adminDelegations: () => '/admin/delegations',\n };\n}\n\nconst BPMRoutesContext = createContext<BPMRoutes | null>(null);\n\nexport interface BPMRoutesProviderProps {\n /**\n * Override the path mapping. Provide a full implementation, or spread\n * the default and override individual entries:\n *\n * ```tsx\n * <BPMRoutesProvider value={{\n * ...createDefaultBPMRoutes(),\n * caseDetail: (id) => `/workspace/cases/${id}`,\n * }}>\n * ```\n */\n readonly value?: BPMRoutes;\n readonly children: ReactNode;\n}\n\n/**\n * Wraps the BPM React tree with a {@link BPMRoutes} value. Mounting the\n * provider is **optional** — `useBPMRoutes()` falls back to\n * {@link createDefaultBPMRoutes} when no provider is present. Use it\n * only when the host needs to remap BPM's internal paths.\n */\nexport function BPMRoutesProvider({\n value,\n children,\n}: BPMRoutesProviderProps): ReactElement {\n const resolved = useMemo(() => value ?? createDefaultBPMRoutes(), [value]);\n return (\n <BPMRoutesContext.Provider value={resolved}>\n {children}\n </BPMRoutesContext.Provider>\n );\n}\n\n/**\n * Reads the host-configured {@link BPMRoutes}. Falls back to\n * {@link createDefaultBPMRoutes} when no `<BPMRoutesProvider>` ancestor\n * is mounted, so views remain self-contained.\n */\nexport function useBPMRoutes(): BPMRoutes {\n const value = useContext(BPMRoutesContext);\n return value ?? DEFAULT_ROUTES;\n}\n\nconst DEFAULT_ROUTES: BPMRoutes = createDefaultBPMRoutes();\n"],"mappings":"mEAmGA,SAAgB,GAAoC,CAClD,MAAO,CACL,cAAiB,aACjB,UAAa,SACb,SAAY,QACZ,OAAU,MACV,WAAc,UACd,gBAAmB,eACnB,kBAAqB,iBAErB,WAAa,GAAe,cAAc,IAC1C,QAAU,GACR,EACI,6BAA6B,mBAAmB,CAAU,IAC1D,iBAEN,cAAiB,aACjB,iBAAmB,GAAe,cAAc,EAAW,WAC3D,iBAAmB,GAAe,cAAc,EAAW,WAC3D,uBAA0B,wBAE1B,UAAa,SACb,YAAc,GAAW,UAAU,EAAO,UAE1C,yBAA4B,0BAE5B,cAAiB,cACjB,eAAkB,eAClB,qBAAwB,oBAC1B,CACF,CAEA,IAAM,GAAA,EAAA,EAAA,eAAmD,IAAI,EAwB7D,SAAgB,EAAkB,CAChC,QACA,YACuC,CACvC,IAAM,GAAA,EAAA,EAAA,aAAyB,GAAS,EAAuB,EAAG,CAAC,CAAK,CAAC,EACzE,OACE,EAAA,EAAA,KAAC,EAAiB,SAAlB,CAA2B,MAAO,EAC/B,UACwB,CAAA,CAE/B,CAOA,SAAgB,GAA0B,CAExC,OAAA,EAAA,EAAA,YADyB,CAClB,GAAS,CAClB,CAEA,IAAM,EAA4B,EAAuB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routes-config-dxahImVe.js","names":[],"sources":["../../src/lib/routes-config.tsx"],"sourcesContent":["'use client';\n\nimport {\n createContext,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from 'react';\n\n/**\n * Framework-agnostic path mapping every BPM view uses for internal\n * cross-navigation. When a host embeds BPM under a non-root prefix\n * (e.g. `/workspace/bpm/*`) it provides its own implementation through\n * `<BPMRoutesProvider value={...}>`; otherwise the default factory\n * preserves the historical `/instances/:id`, `/templates`, etc. paths.\n *\n * Function-shape (instead of string templates) means:\n * - Optional and multi-param routes can branch on argument presence\n * (`caseNew(templateId?)`).\n * - Query-string composition stays inside the host's resolver, not the\n * view.\n * - TypeScript flags missing arguments at compile time.\n *\n * Mirror sibling: {@link RouterAdapter} owns *navigation primitives*\n * (`push`, `replace`, `pathname`); `BPMRoutes` owns *path strings*. The\n * two compose: views call `router.push(routes.caseDetail(id))`.\n */\nexport interface BPMRoutes {\n /** Workflow dashboard landing. Used by sidebar + dashboard tiles. */\n dashboard(): string;\n /** Inbox (待簽) — pending tasks assigned to the current member. */\n inbox(): string;\n /** Sent (我發起的) — instances the current member initiated. */\n sent(): string;\n /** CC (抄送給我) — instances the current member is copied on. */\n cc(): string;\n /** Cross-view search. */\n search(): string;\n /** Personal delegation rules. */\n delegations(): string;\n /**\n * Reserved for hosts that want a dedicated `/notifications` page —\n * BPM's built-in views do **not** navigate here by default (the\n * notification drawer mounted by `<BPMNextProviders>` is the primary\n * unread-notification UX). The `createDefaultBPMRoutes()` factory\n * returns `'/notifications'` so consumers can mount their own page\n * at that path if desired; no BPM-shipped `pages/notifications`\n * shim exists.\n */\n notifications(): string;\n\n /**\n * Detail page for one approval instance.\n *\n * @example default → `/instances/abc123`\n */\n caseDetail(instanceId: string): string;\n /**\n * Launch a new approval instance. When `templateId` is passed, the\n * launch form is pre-populated for that template — by default this is\n * appended as a `?templateId=` query string so the path itself stays\n * stable for routing.\n *\n * @example default `caseNew()` → `/instances/new`\n * @example default `caseNew('tpl-1')` → `/instances/new?templateId=tpl-1`\n */\n caseNew(templateId?: string): string;\n\n /** Template index. */\n templates(): string;\n /** Template designer (xyflow canvas). */\n templateDesigner(templateId: string): string;\n /** Template version history. */\n templateVersions(templateId: string): string;\n /** Template categories admin. */\n templateCategories(): string;\n\n /** Form definitions index. */\n forms(): string;\n /** Form-builder (CodeMirror schema editor + preview). */\n formBuilder(formId: string): string;\n\n /** Per-member notification preferences. */\n notificationSettings(): string;\n\n /** Admin: organization tree management. */\n adminOrgs(): string;\n /** Admin: member directory mapping. */\n adminUsers(): string;\n /** Admin: delegation rule management. */\n adminDelegations(): string;\n}\n\n/**\n * Factory for the default `BPMRoutes` value. Reproduces the exact path\n * literals BPM views used before `BPMRoutesContext` existed, so existing\n * hosts (no provider mounted) keep working unchanged.\n */\nexport function createDefaultBPMRoutes(): BPMRoutes {\n return {\n dashboard: () => '/dashboard',\n inbox: () => '/inbox',\n sent: () => '/sent',\n cc: () => '/cc',\n search: () => '/search',\n delegations: () => '/delegations',\n notifications: () => '/notifications',\n\n caseDetail: (instanceId) => `/instances/${instanceId}`,\n caseNew: (templateId) =>\n templateId\n ? `/instances/new?templateId=${encodeURIComponent(templateId)}`\n : '/instances/new',\n\n templates: () => '/templates',\n templateDesigner: (templateId) => `/templates/${templateId}/designer`,\n templateVersions: (templateId) => `/templates/${templateId}/versions`,\n templateCategories: () => '/templates/categories',\n\n forms: () => '/forms',\n formBuilder: (formId) => `/forms/${formId}/builder`,\n\n notificationSettings: () => '/settings/notifications',\n\n adminOrgs: () => '/admin/orgs',\n adminUsers: () => '/admin/users',\n adminDelegations: () => '/admin/delegations',\n };\n}\n\nconst BPMRoutesContext = createContext<BPMRoutes | null>(null);\n\nexport interface BPMRoutesProviderProps {\n /**\n * Override the path mapping. Provide a full implementation, or spread\n * the default and override individual entries:\n *\n * ```tsx\n * <BPMRoutesProvider value={{\n * ...createDefaultBPMRoutes(),\n * caseDetail: (id) => `/workspace/cases/${id}`,\n * }}>\n * ```\n */\n readonly value?: BPMRoutes;\n readonly children: ReactNode;\n}\n\n/**\n * Wraps the BPM React tree with a {@link BPMRoutes} value. Mounting the\n * provider is **optional** — `useBPMRoutes()` falls back to\n * {@link createDefaultBPMRoutes} when no provider is present. Use it\n * only when the host needs to remap BPM's internal paths.\n */\nexport function BPMRoutesProvider({\n value,\n children,\n}: BPMRoutesProviderProps): ReactElement {\n const resolved = useMemo(() => value ?? createDefaultBPMRoutes(), [value]);\n return (\n <BPMRoutesContext.Provider value={resolved}>\n {children}\n </BPMRoutesContext.Provider>\n );\n}\n\n/**\n * Reads the host-configured {@link BPMRoutes}. Falls back to\n * {@link createDefaultBPMRoutes} when no `<BPMRoutesProvider>` ancestor\n * is mounted, so views remain self-contained.\n */\nexport function useBPMRoutes(): BPMRoutes {\n const value = useContext(BPMRoutesContext);\n return value ?? DEFAULT_ROUTES;\n}\n\nconst DEFAULT_ROUTES: BPMRoutes = createDefaultBPMRoutes();\n"],"mappings":";;;;AAmGA,SAAgB,IAAoC;CAClD,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,YAAY;EACZ,UAAU;EACV,cAAc;EACd,mBAAmB;EACnB,qBAAqB;EAErB,aAAa,MAAe,cAAc;EAC1C,UAAU,MACR,IACI,6BAA6B,mBAAmB,CAAU,MAC1D;EAEN,iBAAiB;EACjB,mBAAmB,MAAe,cAAc,EAAW;EAC3D,mBAAmB,MAAe,cAAc,EAAW;EAC3D,0BAA0B;EAE1B,aAAa;EACb,cAAc,MAAW,UAAU,EAAO;EAE1C,4BAA4B;EAE5B,iBAAiB;EACjB,kBAAkB;EAClB,wBAAwB;CAC1B;AACF;AAEA,IAAM,IAAmB,EAAgC,IAAI;AAwB7D,SAAgB,EAAkB,EAChC,UACA,eACuC;CACvC,IAAM,IAAW,QAAc,KAAS,EAAuB,GAAG,CAAC,CAAK,CAAC;CACzE,OACE,kBAAC,EAAiB,UAAlB;EAA2B,OAAO;EAC/B;CACwB,CAAA;AAE/B;AAOA,SAAgB,IAA0B;CAExC,OADc,EAAW,CAClB,KAAS;AAClB;AAEA,IAAM,IAA4B,EAAuB"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";const e=require("./chunk-CMqjfN_6.cjs"),t=require("./router-adapter-BybHrCNP.cjs"),n=require("./format-date-time-XxBzF0F5.cjs"),r=require("./routes-config-2aKbWq2H.cjs"),i=require("./bpm-form-field-Bc6k4ZEO.cjs"),a=require("./categories-B6QZKZRt.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/core/form"),f=require("@mezzanine-ui/icons"),p=require("@rytass/bpm-core-client/template");function m({confirmText:e,categoryOptions:t,initialName:n,loading:r,onClose:a,onSubmit:l,open:u,title:d}){let[f,p]=(0,o.useState)(n),[m,v]=(0,o.useState)(t[0]??g),[y,b]=(0,o.useState)(null),x=f.trim();(0,o.useEffect)(()=>{u&&(p(n),v(t[0]??g),b(null))},[t,n,u]);async function S(){if(!x){b(`請輸入模板名稱`);return}try{await l({categoryId:m.categoryId,name:x})}catch(e){b(h(e))}}return(0,c.jsxs)(s.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!x},confirmText:e,loading:r,modalType:`standard`,onCancel:a,onClose:a,onConfirm:()=>void S(),open:u,showModalFooter:!0,showModalHeader:!0,size:`narrow`,title:d,children:[(0,c.jsx)(i.t,{label:`模板名稱`,name:`templateName`,required:!0,children:(0,c.jsx)(s.Input,{autoFocus:!0,fullWidth:!0,onChange:e=>{p(e.target.value),b(null)},placeholder:`例如:費用申請流程`,value:f,variant:`base`})}),(0,c.jsx)(i.t,{label:`分類`,name:`templateCategory`,children:(0,c.jsx)(s.Select,{clearable:!1,fullWidth:!0,onChange:e=>{v(_(e,t)),b(null)},options:[...t],placeholder:`選擇分類`,value:m})}),y?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:y}):null]})}function h(e){return e instanceof Error?e.message:`發生未知錯誤`}var g={categoryId:null,id:`UNCATEGORIZED`,name:`未分類`};function _(e,t){if(!v(e))return g;let n=typeof e.id==`string`?e.id:null;return t.find(e=>e.id===n)??g}function v(e){return typeof e==`object`&&!!e}var y=[10,20,50],b=[{key:`ALL`,label:`全部`},{key:`PUBLISHED`,label:`已發布`},{key:`DRAFT`,label:`草稿`}],x=100;function S(){let e=t.r(),i=r.r(),[h,_]=(0,o.useState)([]),[v,S]=(0,o.useState)(E),[j,M]=(0,o.useState)([]),[N,P]=(0,o.useState)(new Set),[F,I]=(0,o.useState)(!1),[L,R]=(0,o.useState)(!1),[z,B]=(0,o.useState)(null),[V,H]=(0,o.useState)(!0),[U,W]=(0,o.useState)(1),[G,K]=(0,o.useState)(10),[q,J]=(0,o.useState)(``),[Y,X]=(0,o.useState)(`ALL`),[Z,Q]=(0,o.useState)(0),$=(0,o.useCallback)(async()=>{H(!0),B(null);try{let[e,t,n]=await Promise.all([(0,p.listApprovalTemplatesPage)({categoryId:v.categoryId,page:U,pageSize:G,searchText:q,status:Y===`ALL`?null:Y}),(0,l.listLaunchableTemplates)(),(0,p.listApprovalTemplateCategoriesPage)({page:1,pageSize:x,searchText:``,status:`ACTIVE`})]);M([...n.categories.map(D)]),_(e.templates),Q(e.totalCount),P(new Set(t.map(e=>e.id)))}catch(e){B(ee(e))}finally{H(!1)}},[v,U,G,q,Y]);(0,o.useEffect)(()=>{$()},[$]);let te=(0,o.useMemo)(()=>h.map(e=>({...e,categoryLabel:A(e),key:e.id,status:e.currentVersionId?`PUBLISHED`:`DRAFT`,updatedAt:n.t(e.updatedAt)})),[h]),ne=(0,o.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`模板名稱`,width:220},{key:`status`,render:e=>(0,c.jsx)(w,{status:e.status}),title:`狀態`,width:120},{key:`category`,render:e=>(0,c.jsx)(T,{record:e}),title:`分類`,width:160},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:220}],[]),re=(0,o.useMemo)(()=>({render:t=>[{disabled:e=>!N.has(e.id),name:`發起`,onClick:()=>e.push(i.caseNew(t.id)),variant:`base-primary`},{name:`設計`,onClick:()=>e.push(i.templateDesigner(t.id))},{name:`版本`,onClick:()=>e.push(i.templateVersions(t.id))}],variant:`base-secondary`,width:192}),[N,e]);async function ie({categoryId:t,name:n}){R(!0),B(null);try{let r=await(0,p.createApprovalTemplate)({categoryId:t,name:n});I(!1),e.push(i.templateDesigner(r))}finally{R(!1)}}return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(s.PageHeader,{children:(0,c.jsx)(u.default,{description:`建立流程模板、維護草稿與發布版本。`,title:`簽核模板`,children:(0,c.jsx)(s.Button,{disabled:L,icon:f.PlusIcon,iconType:`leading`,onClick:()=>I(!0),variant:`base-primary`,children:`建立模板`})})}),(0,c.jsx)(s.SectionGroup,{children:(0,c.jsxs)(s.Section,{filterArea:(0,c.jsx)(s.FilterArea,{className:a.n.templateFilterArea,size:`sub`,children:(0,c.jsxs)(s.FilterLine,{children:[(0,c.jsx)(s.Filter,{span:3,children:(0,c.jsx)(s.FormField,{fullWidth:!0,layout:d.FormFieldLayout.VERTICAL,name:`templateSearchText`,children:(0,c.jsx)(s.Input,{fullWidth:!0,onChange:e=>{J(e.target.value),W(1)},placeholder:`關鍵字:搜尋模板名稱、分類或描述`,size:`sub`,value:q,variant:`base`})})}),(0,c.jsx)(s.Filter,{span:2,children:(0,c.jsx)(s.FormField,{fullWidth:!0,layout:d.FormFieldLayout.VERTICAL,name:`templateCategoryFilter`,children:(0,c.jsx)(s.Select,{clearable:!1,fullWidth:!0,onChange:e=>{S(O(e,j)),W(1)},options:[E,...j],placeholder:`分類`,renderValue:e=>`分類:${k(e)}`,size:`sub`,value:v})})})]})}),tab:(0,c.jsx)(s.Tab,{activeKey:Y,onChange:e=>{X(C(e)),W(1)},children:b.map(e=>(0,c.jsx)(s.TabItem,{children:e.label},e.key))}),children:[z?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:z}):null,(0,c.jsx)(s.Table,{actions:re,columns:ne,dataSource:te,fullWidth:!0,loading:V,pagination:{current:U,onChange:e=>{W(e)},onChangePageSize:e=>{W(1),K(e)},pageSize:G,pageSizeLabel:`每頁筆數`,pageSizeOptions:y,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:Z}})]})})]}),(0,c.jsx)(m,{categoryOptions:[g,...j],confirmText:`建立`,initialName:``,loading:L,onClose:()=>I(!1),onSubmit:ie,open:F,title:`建立簽核模板`})]})}function ee(e){return e instanceof Error?e.message:`發生未知錯誤`}function C(e){return e===`PUBLISHED`||e===`DRAFT`?e:`ALL`}function w({status:e}){return e===`PUBLISHED`?(0,c.jsx)(s.Badge,{size:`sub`,text:`已發布`,variant:`dot-success`}):(0,c.jsx)(s.Badge,{size:`sub`,text:`草稿`,variant:`dot-inactive`})}function T({record:e}){return e.categoryDetail?.isActive===!1?(0,c.jsx)(s.Badge,{size:`sub`,text:`${e.categoryLabel}(停用)`,variant:`dot-inactive`}):(0,c.jsx)(s.Typography,{component:`span`,variant:`body`,children:e.categoryLabel})}var E={categoryId:null,id:`ALL_CATEGORIES`,name:`全部分類`};function D(e){return{categoryId:e.id,id:e.id,name:e.name}}function O(e,t){if(!j(e))return E;let n=typeof e.id==`string`?e.id:null;return n===E.id?E:t.find(e=>e.id===n)??E}function k(e){return Array.isArray(e)||!j(e)?E.name:typeof e.name==`string`?e.name:E.name}function A(e){return e.categoryDetail?.name??e.category??`未分類`}function j(e){return typeof e==`object`&&!!e}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return S}});
|
|
2
|
-
//# sourceMappingURL=templates-CL8bPvgn.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"templates-CL8bPvgn.cjs","names":[],"sources":["../../src/views/templates/template-name-modal.tsx","../../src/views/templates/TemplatesView.tsx"],"sourcesContent":["'use client';\n\nimport { ChangeEvent, ReactElement, useEffect, useState } from 'react';\nimport { Input, Modal, Select, Typography } from '@mezzanine-ui/react';\nimport { BPMFormField } from '../../components/bpm-form-field';\n\nexport interface TemplateCategoryOption {\n readonly categoryId: string | null;\n readonly id: string;\n readonly name: string;\n}\n\ninterface TemplateNameModalProps {\n readonly confirmText: string;\n readonly categoryOptions: readonly TemplateCategoryOption[];\n readonly initialName: string;\n readonly loading: boolean;\n readonly onClose: () => void;\n readonly onSubmit: (input: {\n readonly categoryId: string | null;\n readonly name: string;\n }) => Promise<void>;\n readonly open: boolean;\n readonly title: string;\n}\n\nexport function TemplateNameModal({\n confirmText,\n categoryOptions,\n initialName,\n loading,\n onClose,\n onSubmit,\n open,\n title,\n}: TemplateNameModalProps): ReactElement {\n const [name, setName] = useState(initialName);\n const [category, setCategory] = useState<TemplateCategoryOption>(\n categoryOptions[0] ?? UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION,\n );\n const [error, setError] = useState<string | null>(null);\n const trimmedName = name.trim();\n\n useEffect((): void => {\n if (!open) {\n return;\n }\n\n setName(initialName);\n setCategory(categoryOptions[0] ?? UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION);\n setError(null);\n }, [categoryOptions, initialName, open]);\n\n async function handleConfirm(): Promise<void> {\n if (!trimmedName) {\n setError('請輸入模板名稱');\n return;\n }\n\n try {\n await onSubmit({ categoryId: category.categoryId, name: trimmedName });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !trimmedName }}\n confirmText={confirmText}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={open}\n showModalFooter\n showModalHeader\n size=\"narrow\"\n title={title}\n >\n <BPMFormField label=\"模板名稱\" name=\"templateName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:費用申請流程\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"分類\" name=\"templateCategory\">\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setCategory(readCategoryOption(option, categoryOptions));\n setError(null);\n }}\n options={[...categoryOptions]}\n placeholder=\"選擇分類\"\n value={category}\n />\n </BPMFormField>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nexport const UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION: TemplateCategoryOption = {\n categoryId: null,\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nfunction readCategoryOption(\n value: unknown,\n options: readonly TemplateCategoryOption[],\n): TemplateCategoryOption {\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION;\n }\n\n const id = typeof value.id === 'string' ? value.id : null;\n\n return (\n options.find((option) => option.id === id) ??\n UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION\n );\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n","'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\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 { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport styles from './templates.module.scss';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\nimport {\n TemplateCategoryOption,\n TemplateNameModal,\n UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION,\n} from './template-name-modal';\nimport {\n ApprovalTemplateListStatus,\n ApprovalTemplateRecord,\n ApprovalTemplateCategoryRecord,\n createApprovalTemplate,\n listApprovalTemplateCategoriesPage,\n listApprovalTemplatesPage,\n} from '@rytass/bpm-core-client/template';\nimport { listLaunchableTemplates } from '@rytass/bpm-core-client/workflow';\n\nconst TEMPLATE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst TEMPLATE_STATUS_TABS: readonly {\n readonly key: TemplateStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'PUBLISHED', label: '已發布' },\n { key: 'DRAFT', label: '草稿' },\n];\n\nconst TEMPLATE_CATEGORY_PAGE_SIZE = 100;\n\ntype TemplateStatusTabKey = 'ALL' | ApprovalTemplateListStatus;\n\ntype TemplateRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateRecord & {\n categoryLabel: string;\n key: string;\n status: ApprovalTemplateListStatus;\n }\n>;\n\n\nexport function TemplatesView(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [categoryFilter, setCategoryFilter] = useState<TemplateCategoryOption>(\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n );\n const [categoryOptions, setCategoryOptions] = useState<\n readonly TemplateCategoryOption[]\n >([]);\n const [launchableTemplateIds, setLaunchableTemplateIds] = useState<\n ReadonlySet<string>\n >(new Set());\n const [createModalOpen, setCreateModalOpen] = useState(false);\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [templatePage, setTemplatePage] = useState(1);\n const [templatePageSize, setTemplatePageSize] = useState(10);\n const [templateSearchText, setTemplateSearchText] = useState('');\n const [templateStatus, setTemplateStatus] =\n useState<TemplateStatusTabKey>('ALL');\n const [templateTotalCount, setTemplateTotalCount] = useState(0);\n\n const refreshTemplates = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const [\n templatePageResult,\n nextLaunchableTemplates,\n activeCategoryPageResult,\n ] = await Promise.all([\n listApprovalTemplatesPage({\n categoryId: categoryFilter.categoryId,\n page: templatePage,\n pageSize: templatePageSize,\n searchText: templateSearchText,\n status: templateStatus === 'ALL' ? null : templateStatus,\n }),\n listLaunchableTemplates(),\n listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: TEMPLATE_CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n }),\n ]);\n\n setCategoryOptions([\n ...activeCategoryPageResult.categories.map(readCategoryOption),\n ]);\n setTemplates(templatePageResult.templates);\n setTemplateTotalCount(templatePageResult.totalCount);\n setLaunchableTemplateIds(\n new Set(nextLaunchableTemplates.map((template) => template.id)),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [\n categoryFilter,\n templatePage,\n templatePageSize,\n templateSearchText,\n templateStatus,\n ]);\n\n useEffect((): void => {\n void refreshTemplates();\n }, [refreshTemplates]);\n\n const rows = useMemo(\n (): TemplateRow[] =>\n templates.map((template) => ({\n ...template,\n categoryLabel: readTemplateCategoryLabel(template),\n key: template.id,\n status: template.currentVersionId ? 'PUBLISHED' : 'DRAFT',\n updatedAt: formatDateTime(template.updatedAt),\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<TemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 220 },\n {\n key: 'status',\n render: (record: TemplateRow): ReactElement => (\n <TemplateStatusBadge status={record.status} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'category',\n render: (record: TemplateRow): ReactElement => (\n <TemplateCategoryLabel record={record} />\n ),\n title: '分類',\n width: 160,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<TemplateRow> => ({\n render: (record): ReturnType<TableActions<TemplateRow>['render']> => [\n {\n disabled: (template): boolean =>\n !launchableTemplateIds.has(template.id),\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n {\n name: '設計',\n onClick: (): void => router.push(routes.templateDesigner(record.id)),\n },\n {\n name: '版本',\n onClick: (): void => router.push(routes.templateVersions(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [launchableTemplateIds, router],\n );\n\n async function handleCreateTemplate({\n categoryId,\n name,\n }: {\n readonly categoryId: string | null;\n readonly name: string;\n }): Promise<void> {\n setCreating(true);\n setError(null);\n\n try {\n const templateId = await createApprovalTemplate({ categoryId, name });\n setCreateModalOpen(false);\n router.push(routes.templateDesigner(templateId));\n } finally {\n setCreating(false);\n }\n }\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"建立流程模板、維護草稿與發布版本。\"\n title=\"簽核模板\"\n >\n <Button\n disabled={creating}\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => setCreateModalOpen(true)}\n variant=\"base-primary\"\n >\n 建立模板\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setTemplateSearchText(event.target.value);\n setTemplatePage(1);\n }}\n placeholder=\"關鍵字:搜尋模板名稱、分類或描述\"\n size=\"sub\"\n value={templateSearchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateCategoryFilter\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setCategoryFilter(\n readCategoryFilterOption(option, categoryOptions),\n );\n setTemplatePage(1);\n }}\n options={[\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n ...categoryOptions,\n ]}\n placeholder=\"分類\"\n renderValue={(value): string =>\n `分類:${readTemplateCategoryFilterLabel(value)}`\n }\n size=\"sub\"\n value={categoryFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={templateStatus}\n onChange={(activeKey): void => {\n setTemplateStatus(readTemplateStatusTabKey(activeKey));\n setTemplatePage(1);\n }}\n >\n {TEMPLATE_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n pagination={{\n current: templatePage,\n onChange: (page): void => {\n setTemplatePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setTemplatePage(1);\n setTemplatePageSize(pageSize);\n },\n pageSize: templatePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: TEMPLATE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: templateTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n\n <TemplateNameModal\n categoryOptions={[\n UNCATEGORIZED_TEMPLATE_CATEGORY_OPTION,\n ...categoryOptions,\n ]}\n confirmText=\"建立\"\n initialName=\"\"\n loading={creating}\n onClose={(): void => setCreateModalOpen(false)}\n onSubmit={handleCreateTemplate}\n open={createModalOpen}\n title=\"建立簽核模板\"\n />\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nfunction readTemplateStatusTabKey(activeKey: Key): TemplateStatusTabKey {\n if (activeKey === 'PUBLISHED' || activeKey === 'DRAFT') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction TemplateStatusBadge({\n status,\n}: {\n readonly status: ApprovalTemplateListStatus;\n}): ReactElement {\n if (status === 'PUBLISHED') {\n return <Badge size=\"sub\" text=\"已發布\" variant=\"dot-success\" />;\n }\n\n return <Badge size=\"sub\" text=\"草稿\" variant=\"dot-inactive\" />;\n}\n\nfunction TemplateCategoryLabel({\n record,\n}: {\n readonly record: TemplateRow;\n}): ReactElement {\n if (record.categoryDetail?.isActive === false) {\n return (\n <Badge\n size=\"sub\"\n text={`${record.categoryLabel}(停用)`}\n variant=\"dot-inactive\"\n />\n );\n }\n\n return (\n <Typography component=\"span\" variant=\"body\">\n {record.categoryLabel}\n </Typography>\n );\n}\n\nconst UNCATEGORIZED_TEMPLATE_FILTER_OPTION: TemplateCategoryOption = {\n categoryId: null,\n id: 'ALL_CATEGORIES',\n name: '全部分類',\n};\n\nfunction readCategoryOption(\n category: ApprovalTemplateCategoryRecord,\n): TemplateCategoryOption {\n return {\n categoryId: category.id,\n id: category.id,\n name: category.name,\n };\n}\n\nfunction readCategoryFilterOption(\n value: unknown,\n options: readonly TemplateCategoryOption[],\n): TemplateCategoryOption {\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n const id = typeof value.id === 'string' ? value.id : null;\n\n if (id === UNCATEGORIZED_TEMPLATE_FILTER_OPTION.id) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n return (\n options.find((option) => option.id === id) ??\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION\n );\n}\n\nfunction readTemplateCategoryFilterLabel(value: unknown): string {\n if (Array.isArray(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n return typeof value.name === 'string'\n ? value.name\n : UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n}\n\nfunction readTemplateCategoryLabel(template: ApprovalTemplateRecord): string {\n return template.categoryDetail?.name ?? template.category ?? '未分類';\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
|