@rytass/bpm-core-react 0.4.1 → 0.6.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.
Files changed (148) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +21 -0
  3. package/dist/chunks/FormBuilderView-B_KGPjlp.cjs +3 -0
  4. package/dist/chunks/FormBuilderView-B_KGPjlp.cjs.map +1 -0
  5. package/dist/chunks/FormBuilderView-D8DrQOXD.js +1090 -0
  6. package/dist/chunks/FormBuilderView-D8DrQOXD.js.map +1 -0
  7. package/dist/chunks/{approval-instance-list-page-C5ZKPHdA.cjs → approval-instance-list-page-BMUKxzcz.cjs} +2 -2
  8. package/dist/chunks/{approval-instance-list-page-C5ZKPHdA.cjs.map → approval-instance-list-page-BMUKxzcz.cjs.map} +1 -1
  9. package/dist/chunks/{approval-instance-list-page-BF2r5D2-.js → approval-instance-list-page-YZcGGDD8.js} +2 -2
  10. package/dist/chunks/{approval-instance-list-page-BF2r5D2-.js.map → approval-instance-list-page-YZcGGDD8.js.map} +1 -1
  11. package/dist/chunks/compose-PMrmi-LE.js +451 -0
  12. package/dist/chunks/compose-PMrmi-LE.js.map +1 -0
  13. package/dist/chunks/compose-ziVbRYdo.cjs +2 -0
  14. package/dist/chunks/compose-ziVbRYdo.cjs.map +1 -0
  15. package/dist/chunks/{dashboard-page-Ib8srCMy.js → dashboard-page-DJ9vOPga.js} +2 -2
  16. package/dist/chunks/{dashboard-page-Ib8srCMy.js.map → dashboard-page-DJ9vOPga.js.map} +1 -1
  17. package/dist/chunks/{dashboard-page-CddG1MnK.cjs → dashboard-page-DwHQY6Ki.cjs} +2 -2
  18. package/dist/chunks/{dashboard-page-CddG1MnK.cjs.map → dashboard-page-DwHQY6Ki.cjs.map} +1 -1
  19. package/dist/chunks/designer-DCn6_v4b.cjs +65 -0
  20. package/dist/chunks/designer-DCn6_v4b.cjs.map +1 -0
  21. package/dist/chunks/designer-mOMxJ0Py.js +2576 -0
  22. package/dist/chunks/designer-mOMxJ0Py.js.map +1 -0
  23. package/dist/chunks/detail-Cci9tnoC.cjs +2 -0
  24. package/dist/chunks/detail-Cci9tnoC.cjs.map +1 -0
  25. package/dist/chunks/detail-kyolfdBu.js +1957 -0
  26. package/dist/chunks/detail-kyolfdBu.js.map +1 -0
  27. package/dist/chunks/{routes-config-dxahImVe.js → routes-config-RBYQtUd0.js} +2 -3
  28. package/dist/chunks/routes-config-RBYQtUd0.js.map +1 -0
  29. package/dist/chunks/routes-config-fDVHmvXi.cjs +2 -0
  30. package/dist/chunks/routes-config-fDVHmvXi.cjs.map +1 -0
  31. package/dist/index.cjs +1 -1
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.js +268 -128
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib/routes-config.d.ts +6 -4
  36. package/dist/next/index.cjs +1 -1
  37. package/dist/next/index.js +1 -1
  38. package/dist/next/workflow-chat-route.cjs +19 -0
  39. package/dist/next/workflow-chat-route.cjs.map +1 -0
  40. package/dist/next/workflow-chat-route.d.ts +17 -0
  41. package/dist/next/workflow-chat-route.js +31 -0
  42. package/dist/next/workflow-chat-route.js.map +1 -0
  43. package/dist/pages/instances/detail/index.cjs +1 -1
  44. package/dist/pages/instances/detail/index.js +1 -1
  45. package/dist/pages/templates/compose/index.cjs +2 -0
  46. package/dist/pages/templates/compose/index.cjs.map +1 -0
  47. package/dist/pages/templates/compose/index.d.ts +13 -0
  48. package/dist/pages/templates/compose/index.js +14 -0
  49. package/dist/pages/templates/compose/index.js.map +1 -0
  50. package/dist/pages/templates/designer/index.cjs +1 -1
  51. package/dist/pages/templates/designer/index.cjs.map +1 -1
  52. package/dist/pages/templates/designer/index.js +7 -2
  53. package/dist/pages/templates/designer/index.js.map +1 -1
  54. package/dist/pages/templates/index.cjs +1 -1
  55. package/dist/pages/templates/index.cjs.map +1 -1
  56. package/dist/pages/templates/index.js +3 -3
  57. package/dist/pages/templates/index.js.map +1 -1
  58. package/dist/views/cc/index.cjs +1 -1
  59. package/dist/views/cc/index.js +1 -1
  60. package/dist/views/dashboard/index.cjs +1 -1
  61. package/dist/views/dashboard/index.js +1 -1
  62. package/dist/views/forms/builder/FormBuilderView.d.ts +13 -4
  63. package/dist/views/forms/builder/index.cjs +1 -1
  64. package/dist/views/forms/builder/index.js +1 -1
  65. package/dist/views/forms/builder/json-code-editor.d.ts +1 -1
  66. package/dist/views/inbox/index.cjs +1 -1
  67. package/dist/views/inbox/index.js +1 -1
  68. package/dist/views/instances/detail/InstanceDetailView.d.ts +11 -1
  69. package/dist/views/instances/detail/index.cjs +1 -1
  70. package/dist/views/instances/detail/index.d.ts +5 -0
  71. package/dist/views/instances/detail/index.js +2 -2
  72. package/dist/views/instances/detail/sections/InstanceAttachmentsSection.d.ts +15 -0
  73. package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +33 -0
  74. package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +29 -0
  75. package/dist/views/instances/detail/sections/InstanceSignaturesSection.d.ts +14 -0
  76. package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +51 -0
  77. package/dist/views/instances/detail/sections/container-helpers.d.ts +9 -0
  78. package/dist/views/instances/detail/sections/shared.d.ts +103 -0
  79. package/dist/views/instances/new/index.cjs +1 -1
  80. package/dist/views/instances/new/index.js +1 -1
  81. package/dist/views/search/index.cjs +1 -1
  82. package/dist/views/search/index.js +1 -1
  83. package/dist/views/sent/index.cjs +1 -1
  84. package/dist/views/sent/index.js +1 -1
  85. package/dist/views/templates/TemplatesView.d.ts +5 -0
  86. package/dist/views/templates/compose/TemplateComposeWizardView.d.ts +8 -0
  87. package/dist/views/templates/compose/index.cjs +1 -0
  88. package/dist/views/templates/compose/index.d.ts +2 -0
  89. package/dist/views/templates/compose/index.js +2 -0
  90. package/dist/views/templates/compose/steps/ComposeFormStep.d.ts +15 -0
  91. package/dist/views/templates/compose/steps/ComposeReviewStep.d.ts +12 -0
  92. package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.ts +11 -0
  93. package/dist/views/templates/compose/use-template-compose-wizard.d.ts +46 -0
  94. package/dist/views/templates/designer/TemplateDesignerView.d.ts +60 -2
  95. package/dist/views/templates/designer/chrome-workflow-chat.d.ts +12 -0
  96. package/dist/views/templates/designer/index.cjs +1 -51
  97. package/dist/views/templates/designer/index.js +2 -2272
  98. package/dist/views/templates/designer/use-workflow-chat.d.ts +21 -0
  99. package/dist/views/templates/designer/use-workflow-designer-controller.d.ts +41 -0
  100. package/dist/views/templates/designer/workflow-chat-drawer.d.ts +16 -0
  101. package/dist/views/templates/index.cjs +2 -1
  102. package/dist/views/templates/index.cjs.map +1 -0
  103. package/dist/views/templates/index.js +265 -4
  104. package/dist/views/templates/index.js.map +1 -0
  105. package/dist/views/templates/versions/index.cjs +1 -1
  106. package/dist/views/templates/versions/index.cjs.map +1 -1
  107. package/dist/views/templates/versions/index.js +38 -42
  108. package/dist/views/templates/versions/index.js.map +1 -1
  109. package/package.json +22 -19
  110. package/dist/chunks/builder-BLVnnpnP.js +0 -1300
  111. package/dist/chunks/builder-BLVnnpnP.js.map +0 -1
  112. package/dist/chunks/builder-DVE9zIKH.cjs +0 -3
  113. package/dist/chunks/builder-DVE9zIKH.cjs.map +0 -1
  114. package/dist/chunks/detail-Dcr5mM8g.cjs +0 -2
  115. package/dist/chunks/detail-Dcr5mM8g.cjs.map +0 -1
  116. package/dist/chunks/detail-u9DdLhDW.js +0 -1518
  117. package/dist/chunks/detail-u9DdLhDW.js.map +0 -1
  118. package/dist/chunks/form-name-modal-C3OEvkCV.js +0 -64
  119. package/dist/chunks/form-name-modal-C3OEvkCV.js.map +0 -1
  120. package/dist/chunks/form-name-modal-uZCHbtRH.cjs +0 -2
  121. package/dist/chunks/form-name-modal-uZCHbtRH.cjs.map +0 -1
  122. package/dist/chunks/routes-config-2aKbWq2H.cjs +0 -2
  123. package/dist/chunks/routes-config-2aKbWq2H.cjs.map +0 -1
  124. package/dist/chunks/routes-config-dxahImVe.js.map +0 -1
  125. package/dist/chunks/templates-D44FSB46.js +0 -380
  126. package/dist/chunks/templates-D44FSB46.js.map +0 -1
  127. package/dist/chunks/templates-w96t83N-.cjs +0 -2
  128. package/dist/chunks/templates-w96t83N-.cjs.map +0 -1
  129. package/dist/pages/forms/builder/index.cjs +0 -2
  130. package/dist/pages/forms/builder/index.cjs.map +0 -1
  131. package/dist/pages/forms/builder/index.d.ts +0 -21
  132. package/dist/pages/forms/builder/index.js +0 -15
  133. package/dist/pages/forms/builder/index.js.map +0 -1
  134. package/dist/pages/forms/index.cjs +0 -2
  135. package/dist/pages/forms/index.cjs.map +0 -1
  136. package/dist/pages/forms/index.d.ts +0 -17
  137. package/dist/pages/forms/index.js +0 -14
  138. package/dist/pages/forms/index.js.map +0 -1
  139. package/dist/views/forms/FormsView.d.ts +0 -2
  140. package/dist/views/forms/form-name-modal.d.ts +0 -12
  141. package/dist/views/forms/index.cjs +0 -2
  142. package/dist/views/forms/index.cjs.map +0 -1
  143. package/dist/views/forms/index.d.ts +0 -2
  144. package/dist/views/forms/index.js +0 -186
  145. package/dist/views/forms/index.js.map +0 -1
  146. package/dist/views/templates/designer/index.cjs.map +0 -1
  147. package/dist/views/templates/designer/index.js.map +0 -1
  148. package/dist/views/templates/template-name-modal.d.ts +0 -22
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-page-Ib8srCMy.js","names":[],"sources":["../../src/components/dashboard-page.module.scss","../../src/components/dashboard-page.tsx"],"sourcesContent":[".metricCard {\n color: inherit;\n cursor: pointer;\n text-decoration: none;\n}\n\n.metricCard:hover {\n text-decoration: none;\n}\n","'use client';\n\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n BaseCard,\n Button,\n CardGroup,\n PageHeader,\n Section,\n SectionGroup,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport {\n readWorkflowDashboardSummary,\n type WorkflowDashboardSummaryRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { useAuth } from '../lib/auth-provider';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport styles from './dashboard-page.module.scss';\n\n\ninterface Metric {\n readonly caption: string;\n readonly href: string;\n readonly label: string;\n readonly value: string;\n}\n\nconst EMPTY_DASHBOARD_SUMMARY: WorkflowDashboardSummaryRecord = {\n activeInstanceCount: 0,\n completedInstanceCount: 0,\n overdueTaskCount: 0,\n pendingTaskCount: 0,\n rejectedInstanceCount: 0,\n totalInstanceCount: 0,\n unreadNotificationCount: 0,\n};\n\n/**\n * Operator dashboard — shows pending/unread/active counts for the\n * currently-authenticated member. Reads {@link readWorkflowDashboardSummary}\n * and renders five metric tiles that navigate via {@link useRouterAdapter}.\n */\nexport function DashboardPage(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [summary, setSummary] = useState<WorkflowDashboardSummaryRecord>(\n EMPTY_DASHBOARD_SUMMARY,\n );\n\n const refreshSummary = useCallback(async (): Promise<void> => {\n if (!currentMemberId) {\n setLoading(false);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n setSummary(\n await readWorkflowDashboardSummary({\n currentMemberId,\n from: null,\n to: null,\n }),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [currentMemberId]);\n\n useEffect((): void => {\n void refreshSummary();\n }, [refreshSummary]);\n\n const metrics = useMemo(\n (): readonly Metric[] => [\n {\n caption: '目前需要你處理的任務',\n href: routes.inbox(),\n label: '待處理簽核',\n value: readMetricValue(summary.pendingTaskCount, loading),\n },\n {\n // 未讀通知 — clicking the tile routes to inbox where pending\n // tasks are the most actionable next step. The notification\n // drawer bell stays available globally for in-place review.\n // (Hosts that want a dedicated /notifications page can override\n // `routes.notifications` and swap this href accordingly.)\n caption: '尚未讀取的站內通知',\n href: routes.inbox(),\n label: '未讀通知',\n value: readMetricValue(summary.unreadNotificationCount, loading),\n },\n {\n caption: '目前仍在流程中的案件',\n href: routes.search(),\n label: '進行中案件',\n value: readMetricValue(summary.activeInstanceCount, loading),\n },\n {\n caption: '已超過 SLA 的待處理任務',\n href: routes.inbox(),\n label: '逾時任務',\n value: readMetricValue(summary.overdueTaskCount, loading),\n },\n {\n caption: '你有權限查看的全部案件',\n href: routes.search(),\n label: '案件總數',\n value: readMetricValue(summary.totalInstanceCount, loading),\n },\n ],\n [loading, routes, summary],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看待處理簽核、近期通知與你發起的案件進度。\"\n title=\"工作台\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <CardGroup>\n {metrics.map((metric) => (\n <BaseCard\n aria-label={`前往${metric.label}`}\n className={styles.metricCard}\n description={metric.value}\n key={metric.label}\n onClick={(): void => router.push(metric.href)}\n onKeyDown={(event: KeyboardEvent<HTMLElement>): void => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n router.push(metric.href);\n }\n }}\n role=\"link\"\n tabIndex={0}\n title={metric.label}\n >\n <Typography color=\"text-neutral\" variant=\"caption\">\n {metric.caption}\n </Typography>\n </BaseCard>\n ))}\n </CardGroup>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readMetricValue(value: number, loading: boolean): string {\n return loading ? '-' : String(value);\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取工作台摘要失敗。';\n}\n"],"mappings":";;;;;;;;;;gDCgCM,IAA0D;CAC9D,qBAAqB;CACrB,wBAAwB;CACxB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,oBAAoB;CACpB,yBAAyB;AAC3B;AAOA,SAAgB,IAA8B;CAC5C,IAAM,IAAS,EAAiB,GAC1B,IAAS,EAAa,GACtB,EAAE,cAAW,EAAQ,GACrB,IAAkB,GAAQ,YAAY,MACtC,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,CAAC,GAAS,KAAc,EAAS,EAAI,GACrC,CAAC,GAAS,KAAc,EAC5B,CACF,GAEM,IAAiB,EAAY,YAA2B;EAC5D,IAAI,CAAC,GAAiB;GACpB,EAAW,EAAK;GAChB;EACF;EAGA,AADA,EAAW,EAAI,GACf,EAAS,IAAI;EAEb,IAAI;GACF,EACE,MAAM,EAA6B;IACjC;IACA,MAAM;IACN,IAAI;GACN,CAAC,CACH;EACF,SAAS,GAAuB;GAC9B,EAAS,EAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAW,EAAK;EAClB;CACF,GAAG,CAAC,CAAe,CAAC;CAEpB,QAAsB;EACpB,EAAoB;CACtB,GAAG,CAAC,CAAc,CAAC;CAEnB,IAAM,IAAU,QACW;EACvB;GACE,SAAS;GACT,MAAM,EAAO,MAAM;GACnB,OAAO;GACP,OAAO,EAAgB,EAAQ,kBAAkB,CAAO;EAC1D;EACA;GAME,SAAS;GACT,MAAM,EAAO,MAAM;GACnB,OAAO;GACP,OAAO,EAAgB,EAAQ,yBAAyB,CAAO;EACjE;EACA;GACE,SAAS;GACT,MAAM,EAAO,OAAO;GACpB,OAAO;GACP,OAAO,EAAgB,EAAQ,qBAAqB,CAAO;EAC7D;EACA;GACE,SAAS;GACT,MAAM,EAAO,MAAM;GACnB,OAAO;GACP,OAAO,EAAgB,EAAQ,kBAAkB,CAAO;EAC1D;EACA;GACE,SAAS;GACT,MAAM,EAAO,OAAO;GACpB,OAAO;GACP,OAAO,EAAgB,EAAQ,oBAAoB,CAAO;EAC5D;CACF,GACA;EAAC;EAAS;EAAQ;CAAO,CAC3B;CAEA,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EACE,aAAY;EACZ,OAAM;YAEN,kBAAC,GAAD;GACE,MAAM;GACN,UAAS;GACT,eAAqB,EAAO,KAAK,EAAO,QAAQ,CAAC;GACjD,SAAQ;aACT;EAEO,CAAA;CACK,CAAA,EACL,CAAA,GAEZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA,CACG,IACC,kBAAC,GAAD;EAAY,OAAM;EAAa,SAAQ;YACpC;CACS,CAAA,IACV,MACJ,kBAAC,GAAD,EAAA,UACG,EAAQ,KAAK,MACZ,kBAAC,GAAD;EACE,cAAY,KAAK,EAAO;EACxB,WAAW,EAAO;EAClB,aAAa,EAAO;EAEpB,eAAqB,EAAO,KAAK,EAAO,IAAI;EAC5C,YAAY,MAA4C;GACtD,CAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,eAAe,GACrB,EAAO,KAAK,EAAO,IAAI;EAE3B;EACA,MAAK;EACL,UAAU;EACV,OAAO,EAAO;YAEd,kBAAC,GAAD;GAAY,OAAM;GAAe,SAAQ;aACtC,EAAO;EACE,CAAA;CACJ,GAfH,EAAO,KAeJ,CACX,EACQ,CAAA,CACJ,EAAA,CAAA,EACG,CAAA,CACd,EAAA,CAAA;AAEN;AAEA,SAAS,EAAgB,GAAe,GAA0B;CAChE,OAAO,IAAU,MAAM,OAAO,CAAK;AACrC;AAEA,SAAS,EAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD"}
1
+ {"version":3,"file":"dashboard-page-DJ9vOPga.js","names":[],"sources":["../../src/components/dashboard-page.module.scss","../../src/components/dashboard-page.tsx"],"sourcesContent":[".metricCard {\n color: inherit;\n cursor: pointer;\n text-decoration: none;\n}\n\n.metricCard:hover {\n text-decoration: none;\n}\n","'use client';\n\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n BaseCard,\n Button,\n CardGroup,\n PageHeader,\n Section,\n SectionGroup,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport {\n readWorkflowDashboardSummary,\n type WorkflowDashboardSummaryRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { useAuth } from '../lib/auth-provider';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport styles from './dashboard-page.module.scss';\n\n\ninterface Metric {\n readonly caption: string;\n readonly href: string;\n readonly label: string;\n readonly value: string;\n}\n\nconst EMPTY_DASHBOARD_SUMMARY: WorkflowDashboardSummaryRecord = {\n activeInstanceCount: 0,\n completedInstanceCount: 0,\n overdueTaskCount: 0,\n pendingTaskCount: 0,\n rejectedInstanceCount: 0,\n totalInstanceCount: 0,\n unreadNotificationCount: 0,\n};\n\n/**\n * Operator dashboard — shows pending/unread/active counts for the\n * currently-authenticated member. Reads {@link readWorkflowDashboardSummary}\n * and renders five metric tiles that navigate via {@link useRouterAdapter}.\n */\nexport function DashboardPage(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [summary, setSummary] = useState<WorkflowDashboardSummaryRecord>(\n EMPTY_DASHBOARD_SUMMARY,\n );\n\n const refreshSummary = useCallback(async (): Promise<void> => {\n if (!currentMemberId) {\n setLoading(false);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n setSummary(\n await readWorkflowDashboardSummary({\n currentMemberId,\n from: null,\n to: null,\n }),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [currentMemberId]);\n\n useEffect((): void => {\n void refreshSummary();\n }, [refreshSummary]);\n\n const metrics = useMemo(\n (): readonly Metric[] => [\n {\n caption: '目前需要你處理的任務',\n href: routes.inbox(),\n label: '待處理簽核',\n value: readMetricValue(summary.pendingTaskCount, loading),\n },\n {\n // 未讀通知 — clicking the tile routes to inbox where pending\n // tasks are the most actionable next step. The notification\n // drawer bell stays available globally for in-place review.\n // (Hosts that want a dedicated /notifications page can override\n // `routes.notifications` and swap this href accordingly.)\n caption: '尚未讀取的站內通知',\n href: routes.inbox(),\n label: '未讀通知',\n value: readMetricValue(summary.unreadNotificationCount, loading),\n },\n {\n caption: '目前仍在流程中的案件',\n href: routes.search(),\n label: '進行中案件',\n value: readMetricValue(summary.activeInstanceCount, loading),\n },\n {\n caption: '已超過 SLA 的待處理任務',\n href: routes.inbox(),\n label: '逾時任務',\n value: readMetricValue(summary.overdueTaskCount, loading),\n },\n {\n caption: '你有權限查看的全部案件',\n href: routes.search(),\n label: '案件總數',\n value: readMetricValue(summary.totalInstanceCount, loading),\n },\n ],\n [loading, routes, summary],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看待處理簽核、近期通知與你發起的案件進度。\"\n title=\"工作台\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <CardGroup>\n {metrics.map((metric) => (\n <BaseCard\n aria-label={`前往${metric.label}`}\n className={styles.metricCard}\n description={metric.value}\n key={metric.label}\n onClick={(): void => router.push(metric.href)}\n onKeyDown={(event: KeyboardEvent<HTMLElement>): void => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n router.push(metric.href);\n }\n }}\n role=\"link\"\n tabIndex={0}\n title={metric.label}\n >\n <Typography color=\"text-neutral\" variant=\"caption\">\n {metric.caption}\n </Typography>\n </BaseCard>\n ))}\n </CardGroup>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readMetricValue(value: number, loading: boolean): string {\n return loading ? '-' : String(value);\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取工作台摘要失敗。';\n}\n"],"mappings":";;;;;;;;;;gDCgCM,IAA0D;CAC9D,qBAAqB;CACrB,wBAAwB;CACxB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,oBAAoB;CACpB,yBAAyB;AAC3B;AAOA,SAAgB,IAA8B;CAC5C,IAAM,IAAS,EAAiB,GAC1B,IAAS,EAAa,GACtB,EAAE,cAAW,EAAQ,GACrB,IAAkB,GAAQ,YAAY,MACtC,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,CAAC,GAAS,KAAc,EAAS,EAAI,GACrC,CAAC,GAAS,KAAc,EAC5B,CACF,GAEM,IAAiB,EAAY,YAA2B;EAC5D,IAAI,CAAC,GAAiB;GACpB,EAAW,EAAK;GAChB;EACF;EAGA,AADA,EAAW,EAAI,GACf,EAAS,IAAI;EAEb,IAAI;GACF,EACE,MAAM,EAA6B;IACjC;IACA,MAAM;IACN,IAAI;GACN,CAAC,CACH;EACF,SAAS,GAAuB;GAC9B,EAAS,EAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAW,EAAK;EAClB;CACF,GAAG,CAAC,CAAe,CAAC;CAEpB,QAAsB;EACpB,EAAoB;CACtB,GAAG,CAAC,CAAc,CAAC;CAEnB,IAAM,IAAU,QACW;EACvB;GACE,SAAS;GACT,MAAM,EAAO,MAAM;GACnB,OAAO;GACP,OAAO,EAAgB,EAAQ,kBAAkB,CAAO;EAC1D;EACA;GAME,SAAS;GACT,MAAM,EAAO,MAAM;GACnB,OAAO;GACP,OAAO,EAAgB,EAAQ,yBAAyB,CAAO;EACjE;EACA;GACE,SAAS;GACT,MAAM,EAAO,OAAO;GACpB,OAAO;GACP,OAAO,EAAgB,EAAQ,qBAAqB,CAAO;EAC7D;EACA;GACE,SAAS;GACT,MAAM,EAAO,MAAM;GACnB,OAAO;GACP,OAAO,EAAgB,EAAQ,kBAAkB,CAAO;EAC1D;EACA;GACE,SAAS;GACT,MAAM,EAAO,OAAO;GACpB,OAAO;GACP,OAAO,EAAgB,EAAQ,oBAAoB,CAAO;EAC5D;CACF,GACA;EAAC;EAAS;EAAQ;CAAO,CAC3B;CAEA,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EACE,aAAY;EACZ,OAAM;YAEN,kBAAC,GAAD;GACE,MAAM;GACN,UAAS;GACT,eAAqB,EAAO,KAAK,EAAO,QAAQ,CAAC;GACjD,SAAQ;aACT;EAEO,CAAA;CACK,CAAA,EACL,CAAA,GAEZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA,CACG,IACC,kBAAC,GAAD;EAAY,OAAM;EAAa,SAAQ;YACpC;CACS,CAAA,IACV,MACJ,kBAAC,GAAD,EAAA,UACG,EAAQ,KAAK,MACZ,kBAAC,GAAD;EACE,cAAY,KAAK,EAAO;EACxB,WAAW,EAAO;EAClB,aAAa,EAAO;EAEpB,eAAqB,EAAO,KAAK,EAAO,IAAI;EAC5C,YAAY,MAA4C;GACtD,CAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,eAAe,GACrB,EAAO,KAAK,EAAO,IAAI;EAE3B;EACA,MAAK;EACL,UAAU;EACV,OAAO,EAAO;YAEd,kBAAC,GAAD;GAAY,OAAM;GAAe,SAAQ;aACtC,EAAO;EACE,CAAA;CACJ,GAfH,EAAO,KAeJ,CACX,EACQ,CAAA,CACJ,EAAA,CAAA,EACG,CAAA,CACd,EAAA,CAAA;AAEN;AAEA,SAAS,EAAgB,GAAe,GAA0B;CAChE,OAAO,IAAU,MAAM,OAAO,CAAK;AACrC;AAEA,SAAS,EAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD"}
@@ -1,2 +1,2 @@
1
- "use client";require('../dashboard-page.css');const e=require("./chunk-CMqjfN_6.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./auth-provider-4BeCw7cI.cjs"),r=require("./routes-config-2aKbWq2H.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("react/jsx-runtime"),s=require("@rytass/bpm-core-client/workflow"),c=require("@mezzanine-ui/react/ContentHeader");c=e.t(c,1);let l=require("@mezzanine-ui/icons");var u={metricCard:`bpm_metricCard_vp2qC`},d={activeInstanceCount:0,completedInstanceCount:0,overdueTaskCount:0,pendingTaskCount:0,rejectedInstanceCount:0,totalInstanceCount:0,unreadNotificationCount:0};function f(){let e=t.r(),f=r.r(),{member:h}=n.n(),g=h?.memberId??null,[_,v]=(0,i.useState)(null),[y,b]=(0,i.useState)(!0),[x,S]=(0,i.useState)(d),C=(0,i.useCallback)(async()=>{if(!g){b(!1);return}b(!0),v(null);try{S(await(0,s.readWorkflowDashboardSummary)({currentMemberId:g,from:null,to:null}))}catch(e){v(m(e))}finally{b(!1)}},[g]);(0,i.useEffect)(()=>{C()},[C]);let w=(0,i.useMemo)(()=>[{caption:`目前需要你處理的任務`,href:f.inbox(),label:`待處理簽核`,value:p(x.pendingTaskCount,y)},{caption:`尚未讀取的站內通知`,href:f.inbox(),label:`未讀通知`,value:p(x.unreadNotificationCount,y)},{caption:`目前仍在流程中的案件`,href:f.search(),label:`進行中案件`,value:p(x.activeInstanceCount,y)},{caption:`已超過 SLA 的待處理任務`,href:f.inbox(),label:`逾時任務`,value:p(x.overdueTaskCount,y)},{caption:`你有權限查看的全部案件`,href:f.search(),label:`案件總數`,value:p(x.totalInstanceCount,y)}],[y,f,x]);return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(a.PageHeader,{children:(0,o.jsx)(c.default,{description:`查看待處理簽核、近期通知與你發起的案件進度。`,title:`工作台`,children:(0,o.jsx)(a.Button,{icon:l.PlusIcon,iconType:`leading`,onClick:()=>e.push(f.caseNew()),variant:`base-primary`,children:`發起簽核`})})}),(0,o.jsx)(a.SectionGroup,{children:(0,o.jsxs)(a.Section,{children:[_?(0,o.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:_}):null,(0,o.jsx)(a.CardGroup,{children:w.map(t=>(0,o.jsx)(a.BaseCard,{"aria-label":`前往${t.label}`,className:u.metricCard,description:t.value,onClick:()=>e.push(t.href),onKeyDown:n=>{(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),e.push(t.href))},role:`link`,tabIndex:0,title:t.label,children:(0,o.jsx)(a.Typography,{color:`text-neutral`,variant:`caption`,children:t.caption})},t.label))})]})})]})}function p(e,t){return t?`-`:String(e)}function m(e){return e instanceof Error?e.message:`讀取工作台摘要失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return f}});
2
- //# sourceMappingURL=dashboard-page-CddG1MnK.cjs.map
1
+ "use client";require('../dashboard-page.css');const e=require("./chunk-CMqjfN_6.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./auth-provider-4BeCw7cI.cjs"),r=require("./routes-config-fDVHmvXi.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("react/jsx-runtime"),s=require("@rytass/bpm-core-client/workflow"),c=require("@mezzanine-ui/react/ContentHeader");c=e.t(c,1);let l=require("@mezzanine-ui/icons");var u={metricCard:`bpm_metricCard_vp2qC`},d={activeInstanceCount:0,completedInstanceCount:0,overdueTaskCount:0,pendingTaskCount:0,rejectedInstanceCount:0,totalInstanceCount:0,unreadNotificationCount:0};function f(){let e=t.r(),f=r.r(),{member:h}=n.n(),g=h?.memberId??null,[_,v]=(0,i.useState)(null),[y,b]=(0,i.useState)(!0),[x,S]=(0,i.useState)(d),C=(0,i.useCallback)(async()=>{if(!g){b(!1);return}b(!0),v(null);try{S(await(0,s.readWorkflowDashboardSummary)({currentMemberId:g,from:null,to:null}))}catch(e){v(m(e))}finally{b(!1)}},[g]);(0,i.useEffect)(()=>{C()},[C]);let w=(0,i.useMemo)(()=>[{caption:`目前需要你處理的任務`,href:f.inbox(),label:`待處理簽核`,value:p(x.pendingTaskCount,y)},{caption:`尚未讀取的站內通知`,href:f.inbox(),label:`未讀通知`,value:p(x.unreadNotificationCount,y)},{caption:`目前仍在流程中的案件`,href:f.search(),label:`進行中案件`,value:p(x.activeInstanceCount,y)},{caption:`已超過 SLA 的待處理任務`,href:f.inbox(),label:`逾時任務`,value:p(x.overdueTaskCount,y)},{caption:`你有權限查看的全部案件`,href:f.search(),label:`案件總數`,value:p(x.totalInstanceCount,y)}],[y,f,x]);return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(a.PageHeader,{children:(0,o.jsx)(c.default,{description:`查看待處理簽核、近期通知與你發起的案件進度。`,title:`工作台`,children:(0,o.jsx)(a.Button,{icon:l.PlusIcon,iconType:`leading`,onClick:()=>e.push(f.caseNew()),variant:`base-primary`,children:`發起簽核`})})}),(0,o.jsx)(a.SectionGroup,{children:(0,o.jsxs)(a.Section,{children:[_?(0,o.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:_}):null,(0,o.jsx)(a.CardGroup,{children:w.map(t=>(0,o.jsx)(a.BaseCard,{"aria-label":`前往${t.label}`,className:u.metricCard,description:t.value,onClick:()=>e.push(t.href),onKeyDown:n=>{(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),e.push(t.href))},role:`link`,tabIndex:0,title:t.label,children:(0,o.jsx)(a.Typography,{color:`text-neutral`,variant:`caption`,children:t.caption})},t.label))})]})})]})}function p(e,t){return t?`-`:String(e)}function m(e){return e instanceof Error?e.message:`讀取工作台摘要失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return f}});
2
+ //# sourceMappingURL=dashboard-page-DwHQY6Ki.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-page-CddG1MnK.cjs","names":[],"sources":["../../src/components/dashboard-page.module.scss","../../src/components/dashboard-page.tsx"],"sourcesContent":[".metricCard {\n color: inherit;\n cursor: pointer;\n text-decoration: none;\n}\n\n.metricCard:hover {\n text-decoration: none;\n}\n","'use client';\n\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n BaseCard,\n Button,\n CardGroup,\n PageHeader,\n Section,\n SectionGroup,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport {\n readWorkflowDashboardSummary,\n type WorkflowDashboardSummaryRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { useAuth } from '../lib/auth-provider';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport styles from './dashboard-page.module.scss';\n\n\ninterface Metric {\n readonly caption: string;\n readonly href: string;\n readonly label: string;\n readonly value: string;\n}\n\nconst EMPTY_DASHBOARD_SUMMARY: WorkflowDashboardSummaryRecord = {\n activeInstanceCount: 0,\n completedInstanceCount: 0,\n overdueTaskCount: 0,\n pendingTaskCount: 0,\n rejectedInstanceCount: 0,\n totalInstanceCount: 0,\n unreadNotificationCount: 0,\n};\n\n/**\n * Operator dashboard — shows pending/unread/active counts for the\n * currently-authenticated member. Reads {@link readWorkflowDashboardSummary}\n * and renders five metric tiles that navigate via {@link useRouterAdapter}.\n */\nexport function DashboardPage(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [summary, setSummary] = useState<WorkflowDashboardSummaryRecord>(\n EMPTY_DASHBOARD_SUMMARY,\n );\n\n const refreshSummary = useCallback(async (): Promise<void> => {\n if (!currentMemberId) {\n setLoading(false);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n setSummary(\n await readWorkflowDashboardSummary({\n currentMemberId,\n from: null,\n to: null,\n }),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [currentMemberId]);\n\n useEffect((): void => {\n void refreshSummary();\n }, [refreshSummary]);\n\n const metrics = useMemo(\n (): readonly Metric[] => [\n {\n caption: '目前需要你處理的任務',\n href: routes.inbox(),\n label: '待處理簽核',\n value: readMetricValue(summary.pendingTaskCount, loading),\n },\n {\n // 未讀通知 — clicking the tile routes to inbox where pending\n // tasks are the most actionable next step. The notification\n // drawer bell stays available globally for in-place review.\n // (Hosts that want a dedicated /notifications page can override\n // `routes.notifications` and swap this href accordingly.)\n caption: '尚未讀取的站內通知',\n href: routes.inbox(),\n label: '未讀通知',\n value: readMetricValue(summary.unreadNotificationCount, loading),\n },\n {\n caption: '目前仍在流程中的案件',\n href: routes.search(),\n label: '進行中案件',\n value: readMetricValue(summary.activeInstanceCount, loading),\n },\n {\n caption: '已超過 SLA 的待處理任務',\n href: routes.inbox(),\n label: '逾時任務',\n value: readMetricValue(summary.overdueTaskCount, loading),\n },\n {\n caption: '你有權限查看的全部案件',\n href: routes.search(),\n label: '案件總數',\n value: readMetricValue(summary.totalInstanceCount, loading),\n },\n ],\n [loading, routes, summary],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看待處理簽核、近期通知與你發起的案件進度。\"\n title=\"工作台\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <CardGroup>\n {metrics.map((metric) => (\n <BaseCard\n aria-label={`前往${metric.label}`}\n className={styles.metricCard}\n description={metric.value}\n key={metric.label}\n onClick={(): void => router.push(metric.href)}\n onKeyDown={(event: KeyboardEvent<HTMLElement>): void => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n router.push(metric.href);\n }\n }}\n role=\"link\"\n tabIndex={0}\n title={metric.label}\n >\n <Typography color=\"text-neutral\" variant=\"caption\">\n {metric.caption}\n </Typography>\n </BaseCard>\n ))}\n </CardGroup>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readMetricValue(value: number, loading: boolean): string {\n return loading ? '-' : String(value);\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取工作台摘要失敗。';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-page-DwHQY6Ki.cjs","names":[],"sources":["../../src/components/dashboard-page.module.scss","../../src/components/dashboard-page.tsx"],"sourcesContent":[".metricCard {\n color: inherit;\n cursor: pointer;\n text-decoration: none;\n}\n\n.metricCard:hover {\n text-decoration: none;\n}\n","'use client';\n\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n BaseCard,\n Button,\n CardGroup,\n PageHeader,\n Section,\n SectionGroup,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport {\n readWorkflowDashboardSummary,\n type WorkflowDashboardSummaryRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { useAuth } from '../lib/auth-provider';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport styles from './dashboard-page.module.scss';\n\n\ninterface Metric {\n readonly caption: string;\n readonly href: string;\n readonly label: string;\n readonly value: string;\n}\n\nconst EMPTY_DASHBOARD_SUMMARY: WorkflowDashboardSummaryRecord = {\n activeInstanceCount: 0,\n completedInstanceCount: 0,\n overdueTaskCount: 0,\n pendingTaskCount: 0,\n rejectedInstanceCount: 0,\n totalInstanceCount: 0,\n unreadNotificationCount: 0,\n};\n\n/**\n * Operator dashboard — shows pending/unread/active counts for the\n * currently-authenticated member. Reads {@link readWorkflowDashboardSummary}\n * and renders five metric tiles that navigate via {@link useRouterAdapter}.\n */\nexport function DashboardPage(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [summary, setSummary] = useState<WorkflowDashboardSummaryRecord>(\n EMPTY_DASHBOARD_SUMMARY,\n );\n\n const refreshSummary = useCallback(async (): Promise<void> => {\n if (!currentMemberId) {\n setLoading(false);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n setSummary(\n await readWorkflowDashboardSummary({\n currentMemberId,\n from: null,\n to: null,\n }),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [currentMemberId]);\n\n useEffect((): void => {\n void refreshSummary();\n }, [refreshSummary]);\n\n const metrics = useMemo(\n (): readonly Metric[] => [\n {\n caption: '目前需要你處理的任務',\n href: routes.inbox(),\n label: '待處理簽核',\n value: readMetricValue(summary.pendingTaskCount, loading),\n },\n {\n // 未讀通知 — clicking the tile routes to inbox where pending\n // tasks are the most actionable next step. The notification\n // drawer bell stays available globally for in-place review.\n // (Hosts that want a dedicated /notifications page can override\n // `routes.notifications` and swap this href accordingly.)\n caption: '尚未讀取的站內通知',\n href: routes.inbox(),\n label: '未讀通知',\n value: readMetricValue(summary.unreadNotificationCount, loading),\n },\n {\n caption: '目前仍在流程中的案件',\n href: routes.search(),\n label: '進行中案件',\n value: readMetricValue(summary.activeInstanceCount, loading),\n },\n {\n caption: '已超過 SLA 的待處理任務',\n href: routes.inbox(),\n label: '逾時任務',\n value: readMetricValue(summary.overdueTaskCount, loading),\n },\n {\n caption: '你有權限查看的全部案件',\n href: routes.search(),\n label: '案件總數',\n value: readMetricValue(summary.totalInstanceCount, loading),\n },\n ],\n [loading, routes, summary],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看待處理簽核、近期通知與你發起的案件進度。\"\n title=\"工作台\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.caseNew())}\n variant=\"base-primary\"\n >\n 發起簽核\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <CardGroup>\n {metrics.map((metric) => (\n <BaseCard\n aria-label={`前往${metric.label}`}\n className={styles.metricCard}\n description={metric.value}\n key={metric.label}\n onClick={(): void => router.push(metric.href)}\n onKeyDown={(event: KeyboardEvent<HTMLElement>): void => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n router.push(metric.href);\n }\n }}\n role=\"link\"\n tabIndex={0}\n title={metric.label}\n >\n <Typography color=\"text-neutral\" variant=\"caption\">\n {metric.caption}\n </Typography>\n </BaseCard>\n ))}\n </CardGroup>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readMetricValue(value: number, loading: boolean): string {\n return loading ? '-' : String(value);\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取工作台摘要失敗。';\n}\n"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ "use client";const e=require("./chunk-CMqjfN_6.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-fDVHmvXi.cjs"),r=require("./admin-pickers-Btvij1at.cjs"),i=require("./bpm-form-field-Bc6k4ZEO.cjs"),a=require("./FormBuilderView-B_KGPjlp.cjs");let o=require("react"),s=require("@mezzanine-ui/react"),c=require("react/jsx-runtime"),l=require("@mezzanine-ui/react/Drawer");l=e.t(l,1);let u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@mezzanine-ui/icons"),f=require("ai"),p=require("@rytass/bpm-core-shared"),m=require("@rytass/bpm-core-client/form"),h=require("@rytass/bpm-core-client/organization"),g=require("@xyflow/react"),_=require("dagre");_=e.t(_,1);let v=require("@rytass/bpm-core-client/template"),y=require("@ai-sdk/react");function ee({directory:e,initialState:t,layout:n,onLayout:r}){let[i,a]=(0,o.useState)(t),s=(0,o.useRef)(t),c=(0,o.useRef)(e);c.current=e;let l=(0,o.useCallback)(e=>{if(!e.changed&&!e.error)return e;let t=e.effects.layout?n(e.state.definition):e.state.definition,i={...e.state,definition:t};return s.current=i,a(i),e.effects.layout&&r?.(t),{...e,state:i}},[n,r]),u=(0,o.useCallback)(e=>l((0,p.applyWorkflowCommand)(s.current,e)),[l]),d=(0,o.useCallback)(e=>l((0,p.applyWorkflowMacroCommand)(s.current,e)),[l]),f=(0,o.useCallback)(async(e,t)=>{let n=await(0,p.executeWorkflowTool)(s.current,e,t,{directory:c.current});if(n.ok&&(n.kind===`mutation`||n.kind===`macro`)){let e=l(n.result);return{...n,result:e,snapshot:(0,p.readWorkflowSnapshot)(e.state)}}return n},[l]),m=(0,o.useCallback)(e=>{let t=typeof e==`function`?e(s.current):e;s.current=t,a(t)},[]),h=(0,o.useCallback)(()=>s.current,[]),g=(0,o.useMemo)(()=>(0,p.readWorkflowSnapshot)(i),[i]);return(0,o.useMemo)(()=>({dispatch:u,dispatchMacro:d,executeTool:f,getState:h,replaceState:m,snapshot:g,state:i,tools:p.WORKFLOW_TOOLSET}),[u,d,f,h,m,g,i])}function te({controller:e,api:t=`/api/chat`}){let n=(0,y.useChat)({transport:(0,o.useMemo)(()=>new f.DefaultChatTransport({api:t}),[t]),sendAutomaticallyWhen:f.lastAssistantMessageIsCompleteWithToolCalls,async onToolCall({toolCall:t}){let r=await e.executeTool(t.toolName,t.input);if(r.ok){n.addToolOutput({output:r.kind===`query`?r.data:r.snapshot,tool:t.toolName,toolCallId:t.toolCallId});return}n.addToolOutput({errorText:r.error,state:`output-error`,tool:t.toolName,toolCallId:t.toolCallId})}});return n}var ne=12;function re(){let e=globalThis.LanguageModel;return e&&typeof e==`object`?e:null}var ie={additionalProperties:!1,properties:{action:{enum:[`tool`,`message`],type:`string`},input:{type:`object`},text:{type:`string`},tool:{type:`string`}},required:[`action`],type:`object`};function ae(){return`你是「簽核流程設計器」頁面的離線 AI 助理。只能透過下列工具操作這個流程畫布,其他請求一律婉拒並引導回流程設計。
2
+
3
+ 每一步只輸出一個 JSON 決策物件:
4
+ - 呼叫工具:{"action":"tool","tool":"<工具名>","input":{...}}
5
+ - 回覆使用者(完成或詢問):{"action":"message","text":"<繁體中文訊息>"}
6
+
7
+ 規則:先用 get_workflow_snapshot 了解現況再規劃;完成後用 validate_workflow 檢查並以 message 說明做了什麼。
8
+
9
+ 可用工具:
10
+ ${p.WORKFLOW_TOOLSET.map(e=>`- ${e.name}(${JSON.stringify(e.inputSchema.properties??{})}): ${e.description}`).join(`
11
+ `)}`}function oe({controller:e}){let[t,n]=(0,o.useState)(!1),[r,i]=(0,o.useState)([]),[a,s]=(0,o.useState)(`ready`),c=(0,o.useRef)(0);(0,o.useEffect)(()=>{let e=re();e&&e.availability().then(e=>{n(e!==`unavailable`)}).catch(()=>n(!1))},[]);let l=(0,o.useCallback)((e,t)=>{c.current+=1,i(n=>[...n,{id:`chrome-${c.current}`,parts:[{text:t,type:`text`}],role:e}])},[]);return{available:t,messages:r,send:(0,o.useCallback)(t=>{let n=re();!n||a!==`ready`||(l(`user`,t),s(`submitted`),se({appendMessage:l,controller:e,model:n,userText:t}).then(()=>s(`ready`)).catch(e=>{l(`assistant`,ce(e)),s(`error`)}))},[l,e,a]),status:a}}async function se({appendMessage:e,controller:t,model:n,userText:r}){let i=await n.create({initialPrompts:[{content:ae(),role:`system`}]});try{let n=`使用者需求:${r}\n目前流程:${JSON.stringify(t.snapshot)}`;for(let r=0;r<ne;r+=1){let r=b(await i.prompt(n,{responseConstraint:ie}));if(!r||r.action===`message`){e(`assistant`,r?.text??`我已完成可處理的部分。`);return}if(!r.tool){e(`assistant`,`我已完成可處理的部分。`);return}let a=await t.executeTool(r.tool,r.input??{});if(a.ok){let t=a.kind===`query`?a.data:a.snapshot;e(`assistant`,`⚙ ${r.tool}`),n=`工具 ${r.tool} 已執行。最新流程:${JSON.stringify(t)}\n請決定下一步。`}else n=`工具 ${r.tool} 失敗:${a.error}\n請改用其他方式或回覆使用者。`}e(`assistant`,`已達到單次操作步數上限,請告訴我下一步。`)}finally{i.destroy()}}function b(e){try{let t=JSON.parse(e);return typeof t==`object`&&t&&t.action!==void 0?t:null}catch{return null}}function ce(e){return e instanceof Error?`離線模式發生錯誤:${e.message}`:`離線模式發生未知錯誤。`}var x={display:`flex`,flexDirection:`column`,gap:12,height:`100%`},le={display:`flex`,flex:1,flexDirection:`column`,gap:12,minHeight:0,overflowY:`auto`},ue={display:`flex`,gap:8,paddingBottom:4},de={borderTop:`1px solid var(--mzn-color-border-neutral, #e5e7eb)`,display:`flex`,flexDirection:`column`,gap:8,paddingTop:12},fe={display:`flex`,justifyContent:`flex-end`},pe={width:`100%`},me=`workflow-chat-input-field`,he=`
12
+ .${me}.mzn-text-field {
13
+ width: 100%;
14
+ }
15
+ `,ge={color:`var(--mzn-color-text-secondary, #6b7280)`,fontSize:12,padding:`2px 0`},_e={"input-available":`執行中…`,"input-streaming":`準備中…`,"output-available":`完成`,"output-error":`失敗`};function ve(e){let t=e===`user`;return{alignSelf:t?`flex-end`:`flex-start`,background:t?`var(--mzn-color-primary, #2563eb)`:`var(--mzn-color-surface, #f3f4f6)`,borderRadius:10,color:t?`#fff`:`var(--mzn-color-text-primary, #111827)`,maxWidth:`85%`,padding:`8px 12px`,whiteSpace:`pre-wrap`,wordBreak:`break-word`}}function ye({api:e,controller:t,onClose:n,open:r}){let i=te({api:e,controller:t}),a=oe({controller:t}),[u,d]=(0,o.useState)(`online`),[f,p]=(0,o.useState)(``),m=u===`offline`?{messages:a.messages,send:a.send,status:a.status}:{messages:i.messages,send:e=>{i.sendMessage({text:e})},status:i.status},{messages:h,send:g}=m,_=m.status===`submitted`||m.status===`streaming`,v=(0,o.useCallback)(()=>{let e=f.trim();!e||_||(p(``),g(e))},[_,f,g]),y=(0,o.useCallback)(e=>{e.nativeEvent.isComposing||e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),v())},[v]);return(0,c.jsxs)(l.default,{headerTitle:`AI 流程助理`,isHeaderDisplay:!0,onClose:n,open:r,size:`medium`,children:[(0,c.jsx)(`style`,{children:he}),(0,c.jsxs)(`div`,{style:x,children:[a.available?(0,c.jsxs)(`div`,{style:ue,children:[(0,c.jsx)(s.Button,{onClick:()=>d(`online`),variant:u===`online`?`base-primary`:`base-tertiary`,children:`線上`}),(0,c.jsx)(s.Button,{onClick:()=>d(`offline`),variant:u===`offline`?`base-primary`:`base-tertiary`,children:`離線(裝置內,實驗)`})]}):null,(0,c.jsxs)(`div`,{role:`log`,style:le,children:[h.length===0?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:`用一句話描述你想要的流程,例如:「建立三關簽核:部門主管 → 經理 → 財務,金額大於十萬走財務複核」。我會直接在畫布上幫你繪製。`}):null,h.map(e=>(0,c.jsx)(o.Fragment,{children:be(e)},e.id)),_?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:`思考中…`}):null]}),(0,c.jsxs)(`div`,{style:de,children:[(0,c.jsx)(s.Textarea,{className:me,disabled:_,maxLength:2e3,onChange:e=>p(e.target.value),onKeyDown:y,placeholder:`描述你想要的流程…(Enter 送出,Shift + Enter 換行)`,rows:3,style:pe,value:f}),(0,c.jsx)(`div`,{style:fe,children:(0,c.jsx)(s.Button,{disabled:_||f.trim().length===0,loading:_,onClick:v,type:`button`,variant:`base-primary`,children:`送出`})})]})]})]})}function be(e){return e.parts.map((t,n)=>t.type===`text`?(0,c.jsx)(`div`,{style:ve(e.role),children:t.text},`${e.id}-${n}`):t.type===`dynamic-tool`||(0,f.isToolUIPart)(t)?(0,c.jsx)(`div`,{style:ge,children:`⚙ ${(0,f.getToolName)(t)} · ${_e[t.state]??t.state}`},`${e.id}-${n}`):null)}var xe={display:`grid`,gap:16},Se={alignItems:`start`,display:`grid`,gap:16,gridTemplateColumns:`minmax(0, 1fr) 420px`},Ce={border:`1px solid var(--mzn-color-border-neutral)`,borderRadius:6,height:620,minWidth:0,overflow:`hidden`},we={alignItems:`center`,boxSizing:`border-box`,color:`var(--mzn-color-text-error)`,display:`flex`,height:26,justifyContent:`center`,lineHeight:0,padding:0,width:26},Te={alignItems:`center`,display:`flex`,height:`100%`,justifyContent:`center`,width:`100%`},Ee=`workflow-designer-side-panel`,De=96,Oe=`
16
+ .${Ee} .mzn-form-field--stretch .mzn-form-field__label-area,
17
+ .${Ee} .mzn-form-field--horizontal .mzn-form-field__label-area {
18
+ flex: 0 0 ${De}px;
19
+ width: ${De}px;
20
+ }
21
+
22
+ .${Ee} .mzn-form-field--stretch .mzn-form-field__data-entry,
23
+ .${Ee} .mzn-form-field--horizontal .mzn-form-field__data-entry {
24
+ min-width: 0;
25
+ }
26
+ `,S=`#2563eb`,C=`#64748b`,ke=`var(--mzn-color-text-error, #dc2626)`,w=`drop-shadow(0 0 3px rgba(0, 87, 255, 0.85)) drop-shadow(0 0 9px rgba(0, 87, 255, 0.36))`,Ae=`
27
+ .workflow-selection-delete-control.react-flow__controls-button {
28
+ align-items: center !important;
29
+ display: flex !important;
30
+ height: 26px !important;
31
+ justify-content: center !important;
32
+ padding: 0 !important;
33
+ width: 26px !important;
34
+ }
35
+
36
+ .workflow-selection-delete-control .mzn-icon {
37
+ align-items: center;
38
+ display: flex;
39
+ justify-content: center;
40
+ }
41
+
42
+ .workflow-selection-delete-control .mzn-icon svg {
43
+ height: 16px !important;
44
+ max-height: none !important;
45
+ max-width: none !important;
46
+ width: 16px !important;
47
+ }
48
+
49
+ .workflow-edge--selected .react-flow__edge-path,
50
+ .react-flow__edge-path.workflow-edge--selected {
51
+ filter: ${w};
52
+ opacity: 1 !important;
53
+ stroke: ${C} !important;
54
+ stroke-opacity: 1 !important;
55
+ stroke-width: 1.5px !important;
56
+ }
57
+
58
+ .workflow-edge--selected {
59
+ --xy-edge-stroke: ${C};
60
+ --xy-edge-stroke-selected: ${C};
61
+ --xy-edge-stroke-width: 1.5px;
62
+ }
63
+
64
+ `,je={display:`grid`,gap:12},T={display:`grid`,gap:12},Me={border:`1px solid var(--mzn-color-border-neutral)`,borderRadius:6,display:`grid`,gap:8,maxHeight:360,overflow:`auto`,padding:12},Ne={borderBottom:`1px solid var(--mzn-color-border-neutral)`,display:`grid`,gap:4,padding:`0 0 8px`},Pe={display:`flex`,flexWrap:`wrap`,gap:8},Fe={alignItems:`center`,display:`flex`,gap:8},Ie={flex:`1 1 auto`,minWidth:0},Le={flex:`0 0 auto`},Re={display:`grid`,gap:8},E={alignContent:`center`,background:`var(--mzn-color-bg-surface)`,border:`1px solid var(--mzn-color-border-neutral)`,borderRadius:6,boxShadow:`0 8px 20px rgba(15, 23, 42, 0.08)`,boxSizing:`border-box`,display:`grid`,gap:4,height:`100%`,minWidth:132,overflow:`visible`,padding:`10px 12px`,textAlign:`center`,width:`100%`},ze=`0 8px 20px rgba(15, 23, 42, 0.08), 0 0 0 1px var(--mzn-color-primary, #0057ff), 0 0 10px rgba(0, 87, 255, 0.3)`,D=64,Be=160,Ve=20,He=64,Ue=180,O={...E,display:`grid`,gap:8,padding:`10px 12px`},We={...O,background:`#eff6ff`,border:`1px solid #2563eb`},Ge={...O,background:`#f0fdfa`,border:`1px solid #0f766e`},Ke={...E,background:`#ffffff`},k={...E,background:`#ecfdf3`,border:`1px solid #2f855a`},qe={...E,background:`#fff4ed`,border:`1px solid #c2410c`},A={display:`block`,maxWidth:`100%`,minWidth:0},Je={display:`grid`,gap:2,minWidth:0},j=`input`,Ye=`output`,Xe={endEvent:`結束`,exclusiveGateway:`條件分流`,parallelGateway:`並行處理`,serviceTask:`系統`,startEvent:`開始`,userTask:`簽核`},Ze=[{icon:d.UserIcon,label:`簽核節點`,type:`userTask`},{icon:d.MailIcon,label:`知會節點`,type:`serviceTask`}],Qe=[{icon:d.FilterIcon,label:`條件分流`,type:`exclusiveGateway`}],$e=[{id:`AND`,name:`全部前置完成`},{id:`OR`,name:`任一前置完成`}],et=[{id:`RESTART`,name:`重新送出後從開始重跑`},{id:`FROM_RETURN_POINT`,name:`重新送出後回到退回節點`}],tt=[{id:`DIRECT`,name:`指定會員`},{id:`ORG_MANAGER`,name:`發起人主管`},{id:`ORG_UNIT_MANAGER`,name:`指定組織主管`},{id:`ORG_UNIT_MEMBER`,name:`組織任一人`},{id:`ORG_UNIT_POSITION`,name:`組織特定職位`},{id:`POSITION`,name:`指定職位`}],M=[{id:`1`,name:`直屬主管`,value:1},{id:`2`,name:`第二層主管`,value:2},{id:`3`,name:`第三層主管`,value:3}],nt=[{id:`NONE`,name:`停止流程並提示`},{id:`DIRECT`,name:`固定改派`}],rt=[{id:`EQUALS`,name:`等於`},{id:`NOT_EQUALS`,name:`不等於`},{id:`GREATER_THAN`,name:`大於`},{id:`GREATER_THAN_OR_EQUALS`,name:`大於等於`},{id:`LESS_THAN`,name:`小於`},{id:`LESS_THAN_OR_EQUALS`,name:`小於等於`},{id:`IS_FILLED`,name:`已填寫`},{id:`IS_EMPTY`,name:`未填寫`}],it=[`EQUALS`,`GREATER_THAN`,`GREATER_THAN_OR_EQUALS`,`LESS_THAN`,`LESS_THAN_OR_EQUALS`,`NOT_EQUALS`],at=[{id:`NONE`,name:`未設定`},{id:`ALL`,name:`所有人`},{id:`ORG_UNIT`,name:`指定組織`},{id:`ORG_UNIT_POSITION`,name:`指定組織職位`}],ot={id:`CUSTOM`,name:`既有自訂規則`},st=`member-001`,ct={display:`flex`,flexDirection:`column`,height:`100%`},lt={flex:1,minHeight:0,overflowY:`auto`},ut={borderTop:`1px solid var(--mzn-color-border-neutral)`,display:`flex`,gap:8,paddingTop:12},dt={fields:[],schemaVersion:1},ft={layout:[],schemaVersion:1},pt={endEvent:P,exclusiveGateway:P,parallelGateway:P,serviceTask:P,startEvent:P,userTask:P};function N(e,t){return typeof e==`function`?e(t):e}function mt({aiAssistantAvailable:e=!0,embedded:f=!1,formSchemaOverride:p,initialInitiatorPolicyCel:_,initialWorkflowDefinition:y,onInitiatorPolicyChange:te,onWorkflowChange:ne,showAiAssistant:re=!1,showDryRun:ie=!0,templateId:ae}){let oe=t.r(),se=n.r(),[b,ce]=(0,o.useState)(null),[x,le]=(0,o.useState)(null),[ue,de]=(0,o.useState)(``),[fe,pe]=(0,o.useState)(null),[me,he]=(0,o.useState)(null),ge=(0,o.useRef)(null),[_e,ve]=(0,o.useState)(void 0),be=(0,o.useRef)([]),De=(0,o.useRef)([]),S=ee({directory:(0,o.useMemo)(()=>({listOrgUnits:async()=>be.current.map(e=>({id:e.id,name:e.name})),listPositions:async()=>De.current.map(e=>({id:e.id,name:e.name})),searchMembers:async e=>an(await(0,v.searchMemberOptions)(e)).map(e=>({email:e.email,id:e.memberId,name:e.name}))}),[]),initialState:{definition:f&&y!=null?y:Tt(),editingEdgeId:null,formDefinitionVersionId:null,formSchema:null,initiatorPolicyCel:f&&_!==void 0?_:null,selectedEdgeIds:[],selectedNodeId:f&&y!=null?y.nodes[0]?.id??`start`:`start`},layout:Dt,onLayout:e=>{let t=Sn(e,ge.current);t&&ve(t)}}),C=S.state.definition,w=S.state.formDefinitionVersionId,E=S.state.initiatorPolicyCel,ze=S.state.selectedNodeId,D=S.state.selectedEdgeIds,Be=S.state.editingEdgeId,Ve=e=>S.replaceState(t=>({...t,definition:N(e,t.definition)})),He=e=>S.replaceState(t=>({...t,formDefinitionVersionId:N(e,t.formDefinitionVersionId)})),Ue=e=>S.replaceState(t=>({...t,initiatorPolicyCel:N(e,t.initiatorPolicyCel)})),O=e=>S.replaceState(t=>({...t,selectedNodeId:N(e,t.selectedNodeId)})),We=e=>S.replaceState(t=>({...t,selectedEdgeIds:N(e,t.selectedEdgeIds)})),Ge=e=>S.replaceState(t=>({...t,editingEdgeId:N(e,t.editingEdgeId)})),[Ke,k]=(0,o.useState)(null),[qe,A]=(0,o.useState)(!0),[Je,j]=(0,o.useState)(!1),[Ye,rt]=(0,o.useState)(!1),[it,mt]=(0,o.useState)([]),P=(0,o.useMemo)(()=>JSON.stringify({formDefinitionVersionId:w,initiatorPolicyCel:E,workflowDefinition:C}),[w,E,C]),F=!!ue&&P!==ue,[gt,_t]=(0,o.useState)(!1),[I,L]=(0,o.useState)([]),[R,yt]=(0,o.useState)([]),[z,xt]=(0,o.useState)([]),[Ct,wt]=(0,o.useState)([]);be.current=R,De.current=z;let[Lt,Bt]=(0,o.useState)(!1),[Ht,qt]=(0,o.useState)(!1),[Jt,Yt]=(0,o.useState)(`{}`),[V,en]=(0,o.useState)(null),[H,U]=(0,o.useState)(null),[fn,pn]=(0,o.useState)(!1),[mn,W]=(0,o.useState)(!1),[G,K]=(0,o.useState)(null),[vn,yn]=(0,o.useState)(!1),[bn,xn]=(0,o.useState)(!1),wn=F||vn?`保存並發布`:x?`發布草稿`:`已發布`;(0,o.useEffect)(()=>{f?Yn():Xn()},[f,ae]),(0,o.useEffect)(()=>{function e(e){F&&(e.preventDefault(),e.returnValue=``)}return window.addEventListener(`beforeunload`,e),()=>{window.removeEventListener(`beforeunload`,e)}},[F]),(0,o.useEffect)(()=>{Qn(C)},[C,I]),(0,o.useEffect)(()=>{Ve(e=>St(e))},[C.edges,C.nodes]);function An(){F&&!window.confirm(`目前有尚未儲存的流程草稿,確定要離開嗎?`)||oe.push(se.templates())}let q=(0,o.useMemo)(()=>C.nodes.find(e=>e.id===ze)??null,[ze,C.nodes]),Pn=q?Kt(q):!1,In=D.length>0||Pn,Ln=(0,o.useCallback)(()=>{S.getState().selectedEdgeIds.forEach(e=>S.dispatch({edgeId:e,type:`deleteEdge`})),q&&Kt(q)&&S.dispatch({nodeId:q.id,type:`deleteNode`})},[S,q]);(0,o.useEffect)(()=>{if(!In)return;function e(e){e.key!==`Delete`&&e.key!==`Backspace`||Xt(e.target)||(e.preventDefault(),Ln())}return window.addEventListener(`keydown`,e),()=>{window.removeEventListener(`keydown`,e)}},[In,Ln]);let Rn=(0,o.useMemo)(()=>C.edges.find(e=>e.id===Be)??null,[Be,C.edges]),zn=(0,o.useMemo)(()=>D.length===1?C.edges.find(e=>e.id===D[0])??null:null,[D,C.edges]),Bn=(0,o.useMemo)(()=>D.map(e=>C.edges.find(t=>t.id===e)??null).filter(e=>!!e),[D,C.edges]),X=(0,o.useMemo)(()=>me??Rt(E,fe),[E,me,fe]),Vn=(0,o.useMemo)(()=>C.nodes.map(e=>vt(e,I,R,z,e.id===ze,X)),[X,I,R,z,ze,C.nodes]),Hn=(0,o.useMemo)(()=>C.edges.map(e=>bt(e,C.nodes,D.includes(e.id))),[D,C.edges,C.nodes]),Z=(0,o.useMemo)(()=>B(it,w)??B(Zt(b?.formVersions??[]),w),[w,it,b?.formVersions]),Un=(0,o.useMemo)(()=>rn(it,Z),[it,Z]),Wn=Z?.schema??null,Gn=f?p??null:Wn;(0,o.useEffect)(()=>{S.getState().formSchema!==Gn&&S.replaceState(e=>({...e,formSchema:Gn}))},[S,Gn]);let Kn=(0,o.useMemo)(()=>Cn(C),[C]),qn=(0,o.useMemo)(()=>Tn(C),[C]),Jn=(0,o.useMemo)(()=>zt(X),[X]);(0,o.useEffect)(()=>{f&&ne?.(C)},[f,C]),(0,o.useEffect)(()=>{f&&te?.(E)},[f,E]);async function Yn(){A(!0),k(null);try{let e=await(0,h.readOrganizationDashboard)();yt(e.orgUnits),xt(e.positions),wt(e.memberships)}catch(e){k(Y(e))}finally{A(!1)}}async function Xn(){A(!0),k(null);try{let[e,t]=await Promise.all([(0,v.readTemplateDesigner)(ae),(0,h.readOrganizationDashboard)()]),n=e.versions.find(e=>e.status===`DRAFT`)??null,r=n??e.versions[0]??null;ce(e),le(n),yt(t.orgUnits),xt(t.positions),wt(t.memberships),mt(Zt(e.formVersions));let i=r?.workflowDefinition??Tt(),a=r?.formDefinitionVersionId??e.formVersions[0]?.id??null,o=r?.initiatorPolicyCel??null;Ve(i),He(a),Ue(o),de(JSON.stringify({formDefinitionVersionId:a,initiatorPolicyCel:o,workflowDefinition:i})),pe(r&&!e.template.currentVersionId&&!r.initiatorPolicyCel&&Et(r.workflowDefinition)?`NONE`:null),he(null),O(r?.workflowDefinition.nodes[0]?.id??`start`),We([]),Ge(null),K(null),yn(!1)}catch(e){k(Y(e))}finally{A(!1)}}async function Zn(e){rt(!0),k(null);try{mt(rn(Zt(await(0,v.searchPublishedFormVersionOptions)(e)),Z))}catch(e){k(Y(e))}finally{rt(!1)}}async function Q(e){_t(!0),k(null);try{let t=await(0,v.searchMemberOptions)(e);L(e=>gn(e,an(t)))}catch(e){k(Y(e))}finally{_t(!1)}}async function Qn(e){let t=_n(e).filter(e=>!I.some(t=>t.memberId===e));if(t.length!==0)try{let e=await(0,v.resolveMemberOptions)(t);L(t=>gn(t,an(e)))}catch{L(e=>gn(e,t.map(on)))}}async function $n(e){j(!0),k(null);try{let t=Cn(C),n=zt(X);if(t||n){let e=t??n??`流程設定未完成`;throw k(e),Error(e)}if(vn&&G!==null)await(0,v.composeApprovalTemplateWithForm)({category:b?.template.category??null,categoryId:b?.template.categoryId??null,formDefinitionId:Z?.formDefinitionId??null,formDescription:null,formName:Z?.formName??b?.template.name??`表單`,initiatorPolicyCel:E,notificationConfig:null,publish:e,schema:G.schema,slaDefaults:null,templateDescription:null,templateId:ae??null,templateName:b?.template.name??`模板`,uiSchema:G.uiSchema,workflowDefinition:C}),yn(!1),K(null),await Xn();else{let t=await(0,v.updateApprovalTemplateDraft)({formDefinitionVersionId:w,initiatorPolicyCel:E,versionId:(x??await(0,v.forkApprovalTemplate)(ae)).id,workflowDefinition:C});le(t),e&&await(0,v.publishApprovalTemplateVersion)(t.id),await Xn()}}catch(e){throw k(Y(e)),e}finally{j(!1)}}async function er(){await $n(!1)}async function tr(){await $n(!0)}function nr(){Yt(JSON.stringify(Qt(Z),null,2)),en(null),U(null),Bt(!0)}function rr(){Ht||Bt(!1)}async function ir(){qt(!0),U(null),en(null);try{en(await(0,v.dryRunApprovalWorkflow)({formData:$t(Jt),initiatorMemberId:st,initiatorMetadataSnapshot:dn(st,Ct),workflowDefinition:C}))}catch(e){U(Y(e))}finally{qt(!1)}}async function ar(){if(W(!0),G!==null)return;let e=Z?.formDefinitionId??null;if(!e){K({schema:dt,uiSchema:ft});return}xn(!0);try{let t=await(0,m.readFormBuilder)(e),n=t.versions.find(e=>e.status===`DRAFT`)??t.versions.find(e=>e.id===t.definition.currentVersionId)??t.versions[0]??null;K({schema:n?.schema??dt,uiSchema:n?.uiSchema??ft})}catch(e){k(Y(e))}finally{xn(!1)}}function or(e){let t=(0,g.applyNodeChanges)(e,Vn);Ve(e=>({...e,nodes:e.nodes.map(e=>{let n=t.find(t=>t.id===e.id);return n?{...e,position:n.position}:e})}))}function sr(e){!Wt(e,C.nodes)||!e.source||!e.target||S.dispatch({source:e.source,target:e.target,type:`connectEdge`})}function cr(e,t){e.stopPropagation(),We(n=>e.shiftKey||e.metaKey||e.ctrlKey?Gt(n,t.id):[t.id]),O(null)}function lr(){Ge(null)}function ur(e){S.dispatch({nodeType:e,type:`addNode`})}function dr(e){q&&S.dispatch({label:e,nodeId:q.id,type:`renameNode`})}function $(e){!q||q.type!==`userTask`||S.dispatch({approverResolver:e,nodeId:q.id,type:`setUserTaskApprover`})}function fr(e){!q||q.type!==`userTask`||S.dispatch({nodeId:q.id,resubmitStrategy:e,type:`setUserTaskReturnResubmitStrategy`})}function pr(e){!q||q.type!==`serviceTask`||S.dispatch({action:e,nodeId:q.id,type:`setServiceAction`})}function mr(e){he(e.mode===`ALL`||e.mode===`CUSTOM`?null:e),pe(e.mode===`ALL`||e.mode===`CUSTOM`?null:e.mode),Ue(Vt(e,R))}function hr(e){!q||q.type===`startEvent`||S.dispatch({nodeId:q.id,triggerMode:e,type:`setNodeTriggerMode`})}function gr(e,t){S.dispatch({edgeId:e,isDefault:t,type:`setEdgeDefault`})}function _r({edgeId:e,fieldKey:t,operator:n,value:r}){S.dispatch({edgeId:e,fieldKey:t,operator:n,type:`setEdgeCondition`,value:r})}function vr(){S.dispatch({type:`autoLayout`})}return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`style`,{children:Oe}),f?null:(0,c.jsx)(s.PageHeader,{children:(0,c.jsxs)(u.default,{description:`${x?`草稿 v${x.version}`:`尚未建立草稿`} ·${b?.template.currentVersionId?` 已發布版本`:` 尚未發布`}`,onBackClick:An,title:b?.template.name??`流程設計器`,children:[re?(0,c.jsx)(s.Button,{disabled:!e,onClick:()=>pn(e=>!e),variant:fn?`base-primary`:`base-secondary`,children:e?`AI 助理`:`AI 助理(未設定)`}):null,(0,c.jsx)(s.Button,{"aria-label":`儲存草稿`,disabled:Je||!!Kn||!!Jn,icon:d.SaveIcon,iconType:`icon-only`,onClick:()=>void er(),variant:`base-secondary`,children:`儲存草稿`}),ie?(0,c.jsx)(s.Button,{disabled:qe||!!Kn||!!Jn,icon:d.EyeIcon,iconType:`leading`,onClick:nr,variant:`base-secondary`,children:`試跑流程`}):null,(0,c.jsx)(s.Button,{disabled:Je||!x&&!F&&!vn||!!Kn||!!Jn,icon:d.CheckedIcon,iconType:`leading`,onClick:()=>void tr(),variant:`base-primary`,children:wn})]})}),(0,c.jsx)(s.SectionGroup,{children:(0,c.jsx)(s.Section,{children:(0,c.jsxs)(`div`,{style:xe,children:[Ke?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:Ke}):null,Kn?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:Kn}):null,Jn?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:Jn}):null,f?null:(0,c.jsx)(`div`,{style:T,children:(0,c.jsx)(i.t,{hintText:qn?`已設定條件分流條件。請先移除所有條件,才能更換綁定表單版本。`:void 0,label:`綁定表單版本`,name:`formDefinitionVersionId`,required:!0,children:(0,c.jsxs)(`div`,{style:Fe,children:[(0,c.jsx)(`div`,{style:Ie,children:(0,c.jsx)(s.AutoComplete,{asyncData:!0,disabled:qe||qn,disabledOptionsFilter:!0,emptyText:`沒有符合的已發布表單版本`,isForceClearable:!!w&&!qn,loading:Ye,loadingText:`搜尋表單版本中...`,mode:`single`,onChange:e=>{qn||He(e?.id??null)},onClear:()=>{qn||He(null)},onSearch:Zn,onVisibilityChange:e=>{e&&!qn&&Zn(``)},options:[...Un],placeholder:`選擇已發布表單版本`,searchDebounceTime:300,value:Z})}),(0,c.jsx)(s.Button,{disabled:qe,onClick:()=>{ar()},style:Le,variant:`base-secondary`,children:`編輯表單`})]})})}),(0,c.jsxs)(`div`,{style:Se,children:[(0,c.jsx)(`div`,{ref:ge,style:Ce,children:(0,c.jsxs)(g.ReactFlow,{connectionMode:g.ConnectionMode.Strict,edges:Hn,fitView:!0,isValidConnection:e=>Wt(e,C.nodes),nodeTypes:pt,nodes:Vn,deleteKeyCode:null,multiSelectionKeyCode:[`Shift`,`Meta`,`Control`],onConnect:sr,onEdgeClick:cr,onNodeClick:(e,t)=>{O(t.id),We([])},onNodesChange:or,onPaneClick:()=>{O(null),We([])},onViewportChange:ve,viewport:_e,children:[(0,c.jsx)(g.Background,{}),(0,c.jsx)(`style`,{children:Ae}),(0,c.jsx)(g.Controls,{children:In?(0,c.jsx)(g.ControlButton,{"aria-label":`刪除選取項目`,className:`workflow-selection-delete-control`,onClick:Ln,style:we,title:`刪除選取項目`,children:(0,c.jsx)(`span`,{style:Te,children:(0,c.jsx)(s.Icon,{color:`error`,icon:d.TrashIcon,size:16})})}):null}),(0,c.jsx)(ht,{onApplyAutoLayout:vr}),(0,c.jsx)(g.MiniMap,{})]})}),(0,c.jsxs)(`div`,{className:Ee,style:je,children:[(0,c.jsx)(s.Typography,{component:`h2`,variant:`h3`,children:`流程工具`}),(0,c.jsxs)(`div`,{style:Re,children:[(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`動作節點`}),(0,c.jsx)(`div`,{style:Pe,children:Ze.map(e=>(0,c.jsx)(s.Button,{icon:e.icon,iconType:`leading`,onClick:()=>ur(e.type),size:`sub`,variant:`base-secondary`,children:e.label},e.type))})]}),(0,c.jsxs)(`div`,{style:Re,children:[(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:`流程控制`}),(0,c.jsx)(`div`,{style:Pe,children:Qe.map(e=>(0,c.jsx)(s.Button,{icon:e.icon,iconType:`leading`,onClick:()=>ur(e.type),size:`sub`,variant:`base-secondary`,children:e.label},e.type))})]}),Bn.length>1?Tr(Bn):null,Bn.length===1&&zn?Er(zn):null,Bn.length===0&&q?br(q):null]})]})]})})}),Dr(Rn),!f&&ie?yr():null,!f&&re&&e?(0,c.jsx)(ye,{controller:S,onClose:()=>pn(!1),open:fn}):null,f?null:(0,c.jsx)(l.default,{headerTitle:`編輯表單`,isHeaderDisplay:!0,onClose:()=>W(!1),open:mn,size:`wide`,children:(0,c.jsxs)(`div`,{style:ct,children:[(0,c.jsx)(`div`,{style:lt,children:bn?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:`載入中…`}):(0,c.jsx)(a.t,{onChange:e=>{K(e)},value:G??{schema:dt,uiSchema:ft}})}),(0,c.jsxs)(`div`,{style:ut,children:[(0,c.jsx)(s.Button,{disabled:bn,onClick:()=>{G!==null&&(yn(!0),S.replaceState(e=>({...e,formSchema:G.schema}))),W(!1)},variant:`base-primary`,children:`套用`}),(0,c.jsx)(s.Button,{onClick:()=>W(!1),variant:`base-secondary`,children:`取消`})]})]})})]});function yr(){return(0,c.jsx)(s.Modal,{cancelText:`關閉`,confirmText:`執行試跑`,loading:Ht,modalType:`standard`,onCancel:rr,onClose:rr,onConfirm:()=>void ir(),open:Lt,showModalFooter:!0,showModalHeader:!0,size:`wide`,supportingText:`使用 ${st} 與範例表單資料模擬目前畫布流程,不會建立案件。`,title:`試跑流程`,children:(0,c.jsxs)(`div`,{style:T,children:[(0,c.jsx)(i.t,{label:`表單資料 JSON`,name:`dryRunFormDataJson`,required:!0,children:(0,c.jsx)(s.Textarea,{onChange:e=>Yt(e.target.value),resize:`vertical`,rows:8,value:Jt})}),H?(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:H}):null,V?(0,c.jsxs)(`div`,{style:Me,children:[(0,c.jsx)(s.Typography,{color:V.valid?`text-success`:`text-error`,variant:`label-primary-highlight`,children:V.valid?`試跑通過`:`試跑失敗`}),V.errors.map(e=>(0,c.jsx)(s.Typography,{color:`text-error`,variant:`body`,children:e},e)),V.steps.map(e=>(0,c.jsxs)(`div`,{style:Ne,children:[(0,c.jsxs)(s.Typography,{variant:`label-primary-highlight`,children:[e.nodeLabel,` · `,tn(e.status)]}),(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`caption`,children:[nn(e.nodeType),e.assigneeMemberId?` · 處理者:${e.assigneeMemberId}`:``,e.edgeLabel?` · 來源線段:${e.edgeLabel}`:``]}),e.edgeReason?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`caption`,children:e.edgeReason}):null,e.entryCondition?(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`caption`,children:[`進入條件:`,e.entryConditionMatched?`符合`:`不符合`,` ·`,` `,e.entryCondition]}):null,(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:e.message})]},e.id))]}):null]})})}function br(e){return(0,c.jsxs)(`div`,{style:T,children:[(0,c.jsx)(s.Typography,{component:`h2`,variant:`h3`,children:`節點屬性`}),(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`body`,children:[Xe[e.type],` · `,e.id]}),(0,c.jsx)(i.t,{label:`顯示名稱`,name:`nodeLabel`,required:!0,children:(0,c.jsx)(s.Input,{onChange:e=>dr(e.target.value),value:e.data.label,variant:`base`})}),e.type===`startEvent`?xr():null,e.type===`startEvent`?null:Sr(e),e.type===`userTask`?Cr(e):null,e.type===`serviceTask`?wr(e):null]})}function xr(){let e=X.mode===`CUSTOM`?[...at,ot]:[...at],t=X.mode===`ORG_UNIT`||X.mode===`ORG_UNIT_POSITION`?ln(R,X.orgUnitId??``):null,n=X.mode===`ORG_UNIT_POSITION`?un(z,X.positionId??``):null,a=X.mode===`ORG_UNIT_POSITION`?hn({includeDescendants:!!X.includeDescendants,memberships:Ct,orgUnitId:X.orgUnitId??``,orgUnits:R,positions:z}):[];return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i.t,{hintText:X.mode===`CUSTOM`?`這是舊版表達式規則;切換成標準選項後會改由 UI 管理。`:void 0,label:`發起權限`,name:`initiatorPolicyMode`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:e=>{if(e?.id===`CUSTOM`){pe(null),he(null);return}let t=It(e?.id??null),n=Ut(t);pe(t===`ALL`?null:t),he(t===`ALL`?null:n),Ue(Vt(n,R))},options:e,placeholder:`選擇誰可以發起`,value:B(e,X.mode)})}),X.mode===`ORG_UNIT`||X.mode===`ORG_UNIT_POSITION`?(0,c.jsx)(i.t,{label:`組織`,name:`initiatorOrgUnitId`,required:!0,children:(0,c.jsx)(r.n,{name:`initiatorOrgUnitId`,onChange:e=>mr({...X,orgUnitId:e?.id??``,positionId:``,value:e?.id??``}),orgUnits:R,placeholder:`選擇組織`,value:t})}):null,X.mode===`ORG_UNIT`||X.mode===`ORG_UNIT_POSITION`?(0,c.jsx)(i.t,{label:`包含下層`,name:`initiatorIncludeDescendants`,children:(0,c.jsx)(s.Toggle,{checked:!!X.includeDescendants,onChange:e=>mr({...X,includeDescendants:e.target.checked,...X.mode===`ORG_UNIT_POSITION`?{positionId:``}:{}})})}):null,X.mode===`ORG_UNIT_POSITION`?(0,c.jsx)(i.t,{label:`職位`,name:`initiatorPositionId`,required:!0,children:(0,c.jsx)(r.r,{disabled:!X.orgUnitId?.trim(),name:`initiatorPositionId`,onChange:e=>mr({...X,positionId:e?.id??``}),placeholder:X.orgUnitId?.trim()?`選擇職位`:`請先選擇組織`,positions:a,value:n})}):null]})}function Sr(e){let t=C.edges.filter(t=>t.target===e.id).length,n=t<2,r=n?`AND`:e.data.triggerMode??`AND`;return(0,c.jsx)(i.t,{hintText:n?`需要至少兩條前置連線,才可切換為任一前置完成。`:t>1?`${t} 條前置連線會依此規則觸發。`:`只有一條前置連線時,兩種設定效果相同。`,label:`前置條件`,name:`triggerMode`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:e=>n?void 0:hr(Ot(e?.id??null)),options:[...$e],readOnly:n,value:B($e,r)})})}function Cr(e){let t=e.data.approverResolver,n=At(t.type),a=t.type===`DIRECT`?cn(t.memberIds,I):null,o=t.type===`ORG_UNIT_MANAGER`||t.type===`ORG_UNIT_MEMBER`||t.type===`ORG_UNIT_POSITION`?ln(R,t.orgUnitId):null,l=t.type===`POSITION`||t.type===`ORG_UNIT_POSITION`?un(z,t.positionId):null,u=t.type===`ORG_UNIT_POSITION`?hn({includeDescendants:!!t.includeDescendants,memberships:Ct,orgUnitId:t.orgUnitId,orgUnits:R,positions:z}):[],d=t.type===`ORG_MANAGER`?Pt(t.levelsUp):M[0],f=t.type===`ORG_MANAGER`||t.type===`ORG_UNIT_MANAGER`?t.fallback??{type:`NONE`}:{type:`NONE`},p=f.type===`DIRECT`?sn(I,f.memberId):null,m=e.data.returnBehavior.resubmitStrategy??`RESTART`;return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i.t,{label:`簽核來源`,name:`approverResolverType`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:e=>$(jt(e?.id??null)),options:[...tt],value:B(tt,n)})}),t.type===`DIRECT`?(0,c.jsx)(i.t,{label:`簽核者`,name:`memberId`,required:!0,children:(0,c.jsx)(s.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`workflow-approver-search`,spellCheck:!1},loading:gt,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>$({memberIds:e?.id?[e.id]:[],type:`DIRECT`}),onSearch:Q,onVisibilityChange:e=>{e&&Q(``)},options:[...I],placeholder:`搜尋姓名或信箱`,searchDebounceTime:300,value:a})}):null,t.type===`ORG_MANAGER`?(0,c.jsx)(i.t,{hintText:`依發起人的有效會員歸屬與主管解析規則決定簽核人。`,label:`主管層級`,name:`managerLevelsUp`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:e=>$({baseFromInitiator:!0,levelsUp:Ft(e?.id??null).value,type:`ORG_MANAGER`}),options:[...M],value:d})}):null,t.type===`ORG_UNIT_MANAGER`||t.type===`ORG_UNIT_MEMBER`||t.type===`ORG_UNIT_POSITION`?(0,c.jsx)(i.t,{hintText:t.type===`ORG_UNIT_MANAGER`?`依指定組織或其上層的主管解析規則決定簽核人。`:`依指定組織目前有效會員歸屬建立候選簽核人。`,label:`組織`,name:`orgUnitId`,required:!0,children:(0,c.jsx)(r.n,{name:`orgUnitId`,onChange:e=>$(t.type===`ORG_UNIT_MEMBER`?{includeDescendants:t.includeDescendants,orgUnitId:e?.id??``,type:`ORG_UNIT_MEMBER`}:t.type===`ORG_UNIT_POSITION`?{includeDescendants:t.includeDescendants,orgUnitId:e?.id??``,positionId:``,type:`ORG_UNIT_POSITION`}:{fallback:t.fallback,orgUnitId:e?.id??``,type:`ORG_UNIT_MANAGER`}),orgUnits:R,placeholder:`選擇組織`,value:o})}):null,t.type===`ORG_MANAGER`||t.type===`ORG_UNIT_MANAGER`?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i.t,{hintText:`預設會停止流程並提示;若設定固定人,找不到主管時會改派給該會員。`,label:`無主管時`,name:`approverFallbackMode`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:e=>$(Nt(t,Mt(e?.id??null)===`DIRECT`?{memberId:``,type:`DIRECT`}:{type:`NONE`})),options:[...nt],value:B(nt,f.type)})}),f.type===`DIRECT`?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i.t,{label:`改派人員`,name:`approverFallbackMemberId`,required:!0,children:(0,c.jsx)(s.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`workflow-approver-fallback-search`,spellCheck:!1},loading:gt,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>$(Nt(t,{allowInitiatorSelfApproval:f.allowInitiatorSelfApproval,memberId:e?.id??``,type:`DIRECT`})),onSearch:Q,onVisibilityChange:e=>{e&&Q(``)},options:[...I],placeholder:`搜尋姓名或信箱`,searchDebounceTime:300,value:p})}),(0,c.jsx)(i.t,{hintText:`預設禁止申請人簽自己的案件;只有此流程允許自簽時才開啟。`,label:`允許自簽`,name:`allowInitiatorSelfApproval`,children:(0,c.jsx)(s.Toggle,{checked:!!f.allowInitiatorSelfApproval,onChange:e=>$(Nt(t,{allowInitiatorSelfApproval:e.target.checked,memberId:f.memberId,type:`DIRECT`}))})})]}):null]}):null,t.type===`ORG_UNIT_MEMBER`||t.type===`ORG_UNIT_POSITION`?(0,c.jsx)(i.t,{label:`包含下層`,name:`includeDescendants`,children:(0,c.jsx)(s.Toggle,{checked:!!t.includeDescendants,onChange:e=>$({...t,includeDescendants:e.target.checked,...t.type===`ORG_UNIT_POSITION`?{positionId:``}:{}})})}):null,t.type===`POSITION`?(0,c.jsx)(i.t,{hintText:`指派給目前有效歸屬中擁有此職位的會員;主要歸屬優先。`,label:`職位`,name:`positionId`,required:!0,children:(0,c.jsx)(r.r,{name:`positionId`,onChange:e=>$({positionId:e?.id??``,type:`POSITION`}),placeholder:`選擇職位`,positions:z,value:l})}):null,t.type===`ORG_UNIT_POSITION`?(0,c.jsx)(i.t,{hintText:`只納入指定組織範圍內擁有此職位的有效會員。`,label:`職位`,name:`orgUnitPositionId`,required:!0,children:(0,c.jsx)(r.r,{disabled:!t.orgUnitId.trim(),name:`orgUnitPositionId`,onChange:e=>$({includeDescendants:t.includeDescendants,orgUnitId:t.orgUnitId,positionId:e?.id??``,type:`ORG_UNIT_POSITION`}),placeholder:t.orgUnitId.trim()?`選擇職位`:`請先選擇組織`,positions:u,value:l})}):null,e.data.returnBehavior.allowReturn?(0,c.jsx)(i.t,{hintText:`退回發起人後,重新送出時要從流程開始重跑,或直接回到退回的簽核節點。`,label:`重送策略`,name:`returnResubmitStrategy`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:e=>fr(kt(e?.id??null)),options:[...et],value:B(et,m)})}):null]})}function wr(e){let t=Fn(e.data.action).map(e=>sn(I,e));return(0,c.jsx)(i.t,{label:`知會對象`,name:`notifyMemberIds`,required:!0,children:(0,c.jsx)(s.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,loading:gt,loadingText:`搜尋成員中...`,mode:`multiple`,onChange:e=>pr({channels:[`IN_APP`],recipients:{memberIds:e.map(e=>e.id),type:`DIRECT`},type:`NOTIFY`}),onSearch:Q,onVisibilityChange:e=>{e&&Q(``)},options:[...I],overflowStrategy:`wrap`,placeholder:`搜尋姓名或信箱`,searchDebounceTime:300,value:[...t]})})}function Tr(e){return(0,c.jsxs)(`div`,{style:T,children:[(0,c.jsx)(s.Typography,{component:`h2`,variant:`h3`,children:`已選取線段`}),(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`body`,children:[`已選取 `,e.length,` 條線段,可使用 Delete 或控制面板刪除。`]})]})}function Er(e){let t=J(e,C.nodes);return(0,c.jsxs)(`div`,{style:T,children:[(0,c.jsx)(s.Typography,{component:`h2`,variant:`h3`,children:t?`條件設定`:`線段屬性`}),(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`body`,children:[e.source,` → `,e.target]}),t?Or(e):(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:`這條線會直接把流程送到下一個節點。`})]})}function Dr(e){return!e||!J(e,C.nodes)?null:(0,c.jsx)(s.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!e.data.isDefault&&!e.data.condition},confirmText:`完成`,modalType:`standard`,onCancel:lr,onClose:lr,onConfirm:lr,open:!!Be,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`條件分流的輸出連線需要指定條件,條件會直接顯示在線上。`,title:`條件設定`,children:Or(e)})}function Or(e){let t=Nn(e,C.nodes),n=En(Z?.schema??null),r=Dn(Z?.schema??null,e.data.conditionFieldKey??null),a=On(r),o=jn(r),l=B(a,e.data.conditionOperator??null);return(0,c.jsxs)(`div`,{style:T,children:[(0,c.jsxs)(s.Typography,{color:`text-neutral`,variant:`body`,children:[`畫布上的這條線目前會顯示「`,(0,c.jsx)(`span`,{style:{color:!e.data.isDefault&&!e.data.condition?ke:void 0},children:t??`請設定條件`}),`」。`]}),(0,c.jsx)(s.Toggle,{checked:!!e.data.isDefault,label:`其他情況走這條`,onChange:t=>gr(e.id,t.target.checked)}),e.data.isDefault?(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:`其他條件都不符合時,流程會走這條線。`}):(0,c.jsxs)(c.Fragment,{children:[Z?null:(0,c.jsx)(s.Typography,{color:`text-neutral`,variant:`body`,children:`請先綁定表單版本,才能選擇條件欄位。`}),(0,c.jsx)(i.t,{label:`條件欄位`,name:`edgeConditionField`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:t=>_r({edgeId:e.id,fieldKey:t?.id??null,operator:null,value:null}),options:[...n],placeholder:`選擇條件欄位`,value:B(n,e.data.conditionFieldKey??null)})}),(0,c.jsx)(i.t,{label:`條件判斷`,name:`edgeConditionOperator`,required:!0,children:(0,c.jsx)(s.Select,{clearable:!1,onChange:t=>_r({edgeId:e.id,operator:kn(t?.id??null),value:null}),options:[...a],placeholder:`選擇判斷方式`,value:l})}),l&&Mn(l.id)?(0,c.jsx)(i.t,{label:`條件值`,name:`edgeConditionValue`,required:!0,children:o.length>0?(0,c.jsx)(s.Select,{clearable:!1,onChange:t=>_r({edgeId:e.id,value:t?.id??null}),options:[...o],placeholder:`選擇條件值`,value:B(o,e.data.conditionValue??null)}):(0,c.jsx)(s.Input,{onChange:t=>_r({edgeId:e.id,value:t.target.value}),placeholder:`輸入要比對的值`,value:e.data.conditionValue??``,variant:`base`})}):null]})]})}}function ht({onApplyAutoLayout:e}){function t(){e()}return(0,c.jsx)(g.Panel,{position:`top-right`,children:(0,c.jsx)(s.Button,{icon:d.DotGridIcon,iconType:`leading`,onClick:t,size:`sub`,variant:`base-secondary`,children:`自動排版`})})}function P({data:e,selected:t,type:n}){let r=e.approverLines??[e.approverSummary??e.label],i=F(e);return(0,c.jsxs)(`div`,{style:gt(n,t),children:[I(e),(0,c.jsx)(`div`,{style:Je,children:r.map((e,t)=>(0,c.jsx)(s.Typography,{component:`span`,ellipsis:!0,style:A,title:e,variant:`label-primary`,children:e},`${e}_${t}`))}),(0,c.jsx)(s.Typography,{color:`text-neutral`,component:`span`,ellipsis:!0,style:A,title:i,variant:`caption`,children:i})]})}function F(e){return e.nodeKind===`startEvent`?e.initiatorPolicySummary??`所有人`:e.approverSummary||e.approverLines?e.label:e.nodeKind===`exclusiveGateway`?`條件在線上`:e.nodeKind===`parallelGateway`?`多條路徑同時進行`:Xe[e.nodeKind]}function gt(e,t){let n=_t(e);return t?{...n,border:`1px solid var(--mzn-color-primary, #0057ff)`,boxShadow:ze}:n}function _t(e){return e===`exclusiveGateway`?We:e===`parallelGateway`?Ge:e===`startEvent`?k:e===`endEvent`?qe:e===`userTask`?Ke:E}function I(e){return!e.hasInput&&e.hasOutput?(0,c.jsx)(g.Handle,{id:Ye,position:g.Position.Right,type:`source`}):e.hasInput&&!e.hasOutput?(0,c.jsx)(g.Handle,{id:j,position:g.Position.Left,type:`target`}):!e.hasInput&&!e.hasOutput?null:[(0,c.jsx)(g.Handle,{id:j,position:g.Position.Left,type:`target`},`target`),(0,c.jsx)(g.Handle,{id:Ye,position:g.Position.Right,type:`source`},`source`)]}function vt(e,t,n,r,i,a){let o=L(e);return{data:{approverLines:yn(e,t),approverSummary:K(e,t,n,r),hasInput:qt(e),hasOutput:Jt(e),initiatorPolicySummary:e.type===`startEvent`?Ht(a,n,r):null,label:e.data.label,nodeKind:e.type},height:o.height,handles:R(e),id:e.id,initialHeight:o.height,initialWidth:o.width,position:e.position,selected:i,sourcePosition:g.Position.Right,targetPosition:g.Position.Left,type:e.type,width:o.width}}function L(e){return e.type===`exclusiveGateway`||e.type===`parallelGateway`?{height:He,width:Ue}:e.type===`serviceTask`?{height:D+(Math.max(1,Fn(e.data.action).length)-1)*Ve,width:Be}:{height:D,width:Be}}function R(e){let t=L(e);return[...qt(e)?[yt(t)]:[],...Jt(e)?[z(t)]:[]]}function yt({height:e}){let t=e/2-9/2;return{height:9,id:j,position:g.Position.Left,type:`target`,width:9,x:-9/2,y:t}}function z({height:e,width:t}){let n=e/2-9/2;return{height:9,id:Ye,position:g.Position.Right,type:`source`,width:9,x:t-9/2,y:n}}function bt(e,t,n){let r=Nn(e,t),i=J(e,t),a=i&&!e.data.isDefault&&!e.data.condition,o=a?ke:i?S:`#475569`,s=a?`#fef2f2`:i?`#eff6ff`:`#ffffff`,c=a?ke:i?S:C;return{className:n?`workflow-edge--selected`:void 0,data:e.data,id:e.id,label:r,labelBgBorderRadius:6,labelBgPadding:[8,4],labelBgStyle:{fill:s,stroke:c,strokeWidth:1},labelShowBg:!!r,labelStyle:{fill:o,fontSize:12,fontWeight:600},selected:n,source:e.source,sourceHandle:e.sourceHandle,style:{filter:n?w:void 0,opacity:1,stroke:C,strokeOpacity:1,strokeWidth:1.5},target:e.target,targetHandle:e.targetHandle,type:e.type??`smoothstep`}}function xt(e,t){return e.type===`startEvent`?e:(e.type===`endEvent`||e.type===`userTask`||e.type===`serviceTask`||e.type,{...e,data:{...e.data,triggerMode:t}})}function St(e){return wt(Ct(e))}function Ct(e){let t=new Set(e.nodes.filter(e=>Yt(e)).map(e=>e.id)),n=e.edges.filter(e=>!t.has(e.source));return n.length===e.edges.length?e:{...e,edges:n}}function wt(e){let t=e.edges.reduce((e,t)=>({...e,[t.target]:(e[t.target]??0)+1}),{}),n=e.nodes.map(e=>e.type===`startEvent`?e:(t[e.id]??0)<2&&e.data.triggerMode!==`AND`?xt(e,`AND`):e);return n.some((t,n)=>t!==e.nodes[n])?{...e,nodes:n}:e}function Tt(){return{edges:[],meta:{schemaVersion:1},nodes:[{data:{label:`開始`},id:`start`,position:{x:80,y:160},type:`startEvent`},{data:{endState:`APPROVED`,label:`完成`,triggerMode:`AND`},id:`end`,position:{x:560,y:160},type:`endEvent`}]}}function Et(e){return e.edges.length===0&&e.nodes.length===2&&e.nodes.some(e=>e.type===`startEvent`)&&e.nodes.some(e=>e.type===`endEvent`)}function Dt(e){let t=new _.graphlib.Graph;return t.setDefaultEdgeLabel(()=>({})),t.setGraph({rankdir:`LR`,ranksep:120}),e.nodes.forEach(e=>{t.setNode(e.id,L(e))}),e.edges.forEach(e=>{t.setEdge(e.source,e.target)}),_.layout(t),{...e,nodes:e.nodes.map(e=>{let n=t.node(e.id);return n?{...e,position:{x:n.x-L(e).width/2,y:n.y-L(e).height/2}}:e})}}function B(e,t){return t?e.find(e=>e.id===t)??null:null}function Ot(e){return e===`OR`?`OR`:`AND`}function kt(e){return e===`FROM_RETURN_POINT`?`FROM_RETURN_POINT`:`RESTART`}function At(e){return e===`ORG_MANAGER`||e===`ORG_UNIT_MANAGER`||e===`ORG_UNIT_MEMBER`||e===`ORG_UNIT_POSITION`||e===`POSITION`?e:`DIRECT`}function jt(e){let t=At(e??`DIRECT`);return t===`ORG_MANAGER`?{baseFromInitiator:!0,levelsUp:1,type:`ORG_MANAGER`}:t===`ORG_UNIT_MANAGER`?{orgUnitId:``,type:`ORG_UNIT_MANAGER`}:t===`ORG_UNIT_MEMBER`?{includeDescendants:!1,orgUnitId:``,type:`ORG_UNIT_MEMBER`}:t===`ORG_UNIT_POSITION`?{includeDescendants:!1,orgUnitId:``,positionId:``,type:`ORG_UNIT_POSITION`}:t===`POSITION`?{positionId:``,type:`POSITION`}:{memberIds:[],type:`DIRECT`}}function Mt(e){return e===`DIRECT`?`DIRECT`:`NONE`}function Nt(e,t){return e.type===`ORG_MANAGER`||e.type===`ORG_UNIT_MANAGER`?{...e,fallback:t}:e}function Pt(e){return M.find(t=>t.value===e)??M[0]}function Ft(e){return M.find(t=>t.id===e)??M[0]}function It(e){return e===`ORG_UNIT`||e===`ORG_UNIT_POSITION`||e===`NONE`?e:`ALL`}function Lt(e){let t=e?.trim();if(!t)return{mode:`ALL`,value:``};let n=Bt(t,/"([^"]+)" in subject\.orgUnitIds/gu),r=Bt(t,/"([^"]+)" in subject\.positionIds/gu);return n.length>0&&r.length>0?{includeDescendants:n.length>1,mode:`ORG_UNIT_POSITION`,orgUnitId:n[0],positionId:r[0],value:n[0]??``}:n.length>0?{includeDescendants:n.length>1,mode:`ORG_UNIT`,orgUnitId:n[0],value:n[0]??``}:{mode:`CUSTOM`,value:t}}function Rt(e,t){let n=Lt(e);return!t||t===`ALL`||t===`NONE`?t===`ALL`||t===`NONE`?{mode:t,value:``}:n:n.mode===t?n:Ut(t)}function zt(e){return e.mode===`NONE`?`發起權限需要選擇誰可以發起。`:(e.mode===`ORG_UNIT`||e.mode===`ORG_UNIT_POSITION`)&&!e.orgUnitId?.trim()?`指定組織發起時,需要選擇組織。`:e.mode===`ORG_UNIT_POSITION`&&!e.positionId?.trim()?`指定組織職位發起時,需要選擇職位。`:null}function Bt(e,t){return[...e.matchAll(t)].map(e=>e[1]).filter(e=>!!e)}function Vt(e,t){if(e.mode===`ALL`||e.mode===`NONE`)return null;let n=e.orgUnitId?.trim()??``;if(!n)return null;let r=G(t,n,!!e.includeDescendants).map(e=>`${JSON.stringify(e)} in subject.orgUnitIds`).join(` || `);if(e.mode===`ORG_UNIT`)return r?`(${r})`:null;let i=e.positionId?.trim()??``;return i&&r?`(${r}) && ${JSON.stringify(i)} in subject.positionIds`:null}function Ht(e,t,n){return e.mode===`NONE`?`未設定`:e.mode===`ORG_UNIT`?e.orgUnitId?`組織:${H(t,e.orgUnitId)}`:`指定組織`:e.mode===`ORG_UNIT_POSITION`?e.orgUnitId&&e.positionId?`組織職位:${H(t,e.orgUnitId)} / ${U(n,e.positionId)}`:`指定組織職位`:e.mode===`CUSTOM`?`既有自訂規則`:`所有人`}function Ut(e){return{includeDescendants:!0,mode:e,orgUnitId:``,positionId:``,value:``}}function Wt(e,t){let n=e.source?t.find(t=>t.id===e.source)??null:null,r=e.target?t.find(t=>t.id===e.target)??null:null;return!!n&&!!r&&e.source!==e.target&&e.sourceHandle===Ye&&e.targetHandle===j&&!!(n&&Jt(n))&&!!(r&&qt(r))}function Gt(e,t){return e.includes(t)?e.filter(e=>e!==t):[...e,t]}function Kt(e){return e.type!==`startEvent`&&e.type!==`endEvent`}function qt(e){return e.type!==`startEvent`}function Jt(e){return e.type!==`endEvent`&&!Yt(e)}function Yt(e){return e.type===`serviceTask`&&e.data.action.type===`NOTIFY`}function Xt(e){return e instanceof HTMLElement?e.isContentEditable||e.tagName===`INPUT`||e.tagName===`TEXTAREA`||e.tagName===`SELECT`||!!e.closest(`[contenteditable="true"]`):!1}function Zt(e){return e.map(e=>({formDefinitionId:e.formDefinitionId,formName:e.formName,id:e.id,name:`${e.formName} | v${e.version}`,schema:e.schema}))}function Qt(e){return(e?.schema.fields??[]).reduce((e,t)=>({...e,[t.fieldKey]:V(t)}),{})}function V(e){return e.type===`number`?1e3:e.type===`boolean`?!0:e.type===`select`?e.options[0]?.value??``:e.type===`checkbox`?e.options[0]?[e.options[0].value]:[]:e.type===`date`?`2026-05-08`:e.type===`datetime`?`2026-05-08T09:00:00+08:00`:e.placeholder??e.label}function $t(e){let t=JSON.parse(e);if(!en(t))throw Error(`表單資料 JSON 必須是物件。`);return t}function en(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function tn(e){return e===`COMPLETED`?`完成`:e===`PASSED`?`通過`:e===`SKIPPED`?`略過`:e===`STOPPED`?`已停止`:e===`WAITING`?`將等待簽核`:e}function nn(e){return e in Xe?Xe[e]:e}function rn(e,t){return t&&!e.some(e=>e.id===t.id)?[t,...e]:e}function an(e){return e.map(e=>({displayName:e.name,email:e.email,id:e.memberId,memberId:e.memberId,name:xn(e.name,e.email)}))}function on(e){return{displayName:`未知會員`,email:``,id:e,memberId:e,name:`未知會員`}}function sn(e,t){return e.find(e=>e.memberId===t)??on(t)}function cn(e,t){let n=e[0];return n?sn(t,n):null}function ln(e,t){let n=e.find(e=>e.id===t);return n?r.a(n):null}function un(e,t){let n=e.find(e=>e.id===t);return n?r.o(n):null}function H(e,t){return ln(e,t)?.name??`未指定組織`}function U(e,t){return un(e,t)?.name??`未指定職位`}function dn(e,t){let n=fn(),r=t.filter(t=>t.memberId===e&&pn(t,n)),i=r.reduce((e,t)=>e&&mn(e,t)<=0?e:t,null);return{customFields:{},managerMemberId:`member-002`,memberId:e,orgCode:`HQ`,orgUnitIds:W(r.map(e=>e.orgUnitId)),positionId:i?.positionId??null,positionIds:W(r.map(e=>e.positionId)),primaryOrgUnitId:i?.orgUnitId??null,roles:[`manager`]}}function fn(){return new Date().toISOString().slice(0,10)}function pn(e,t){return e.effectiveFrom<=t&&(!e.effectiveTo||e.effectiveTo>=t)}function mn(e,t){return e.isPrimary===t.isPrimary?t.effectiveFrom.localeCompare(e.effectiveFrom):e.isPrimary?-1:1}function W(e){return e.reduce((e,t)=>t&&!e.includes(t)?[...e,t]:e,[])}function hn({includeDescendants:e,memberships:t,orgUnitId:n,orgUnits:r,positions:i}){let a=new Set(G(r,n,e)),o=new Set(t.filter(e=>a.has(e.orgUnitId)).map(e=>e.positionId).filter(e=>!!e));return i.filter(e=>o.has(e.id))}function G(e,t,n){let r=e.find(e=>e.id===t);return r?n?e.filter(e=>e.id===r.id||e.path.startsWith(`${r.path}.`)).map(e=>e.id):[r.id]:t.trim()?[t]:[]}function gn(e,t){let n=new Set(e.map(e=>e.memberId)),r=t.filter(e=>!n.has(e.memberId));return[...e,...r]}function _n(e){return[...new Set(e.nodes.flatMap(e=>e.type===`userTask`?e.data.approverResolver.type===`DIRECT`?e.data.approverResolver.memberIds:[]:e.type===`serviceTask`?Fn(e.data.action):[]))]}function K(e,t,n,r){return e.type===`userTask`?vn(e.data.approverResolver,t,n,r):null}function vn(e,t,n,r){return e.type===`DIRECT`?bn(e.memberIds,t,`未指定簽核者`):e.type===`ORG_MANAGER`?Pt(e.levelsUp).name:e.type===`ORG_UNIT_MANAGER`?`組織主管:${H(n,e.orgUnitId)}`:e.type===`ORG_UNIT_MEMBER`?`組織任一人:${H(n,e.orgUnitId)}`:e.type===`ORG_UNIT_POSITION`?`組織職位:${H(n,e.orgUnitId)} / ${U(r,e.positionId)}`:e.type===`POSITION`?`職位:${U(r,e.positionId)}`:e.type===`DYNAMIC_FORM`?`表單欄位:${e.formPath||`未設定`}`:`自訂表達式`}function yn(e,t){if(e.type!==`serviceTask`)return null;let n=Fn(e.data.action);return n.length===0?[`未指定知會對象`]:n.map(e=>sn(t,e).name)}function bn(e,t,n){let r=e.map(e=>sn(t,e).name);return r.length===0?n:r.length<=2?r.join(`、`):`${r.slice(0,2).join(`、`)} 等 ${r.length} 人`}function xn(e,t){return`${e} (${t})`}function Sn(e,t){let n=t?.getBoundingClientRect();if(!n||e.nodes.length===0)return null;let r=e.nodes.reduce((e,t)=>{let n=L(t);return{maxX:Math.max(e.maxX,t.position.x+n.width),maxY:Math.max(e.maxY,t.position.y+n.height),minX:Math.min(e.minX,t.position.x),minY:Math.min(e.minY,t.position.y)}},{maxX:-1/0,maxY:-1/0,minX:1/0,minY:1/0});return(0,g.getViewportForBounds)({height:r.maxY-r.minY,width:r.maxX-r.minX,x:r.minX,y:r.minY},n.width,n.height,.1,1,.2)}function Cn(e){let t=e.nodes.find(e=>e.type===`userTask`&&!!wn(e.data.approverResolver)),n=e.nodes.find(e=>e.type===`serviceTask`&&e.data.action.type===`NOTIFY`&&Fn(e.data.action).length===0),r=e.edges.find(t=>J(t,e.nodes)&&!t.data.isDefault&&!t.data.condition);return t&&t.type===`userTask`?wn(t.data.approverResolver):n?`知會節點需要至少一位知會對象。`:r?`條件分流的每條輸出連線都需要先設定條件。`:null}function wn(e){return e.type===`DIRECT`&&e.memberIds.length===0?`簽核節點需要指定簽核會員。`:e.type===`ORG_MANAGER`&&e.levelsUp<1?`簽核節點需要指定有效的主管層級。`:e.type===`ORG_UNIT_MANAGER`&&!e.orgUnitId.trim()||e.type===`ORG_UNIT_MEMBER`&&!e.orgUnitId.trim()?`簽核節點需要指定組織。`:e.type===`ORG_UNIT_POSITION`&&(!e.orgUnitId.trim()||!e.positionId.trim())?`簽核節點需要指定組織與職位。`:(e.type===`ORG_MANAGER`||e.type===`ORG_UNIT_MANAGER`)&&e.fallback?.type===`DIRECT`&&!e.fallback.memberId.trim()?`簽核節點需要指定改派固定人。`:e.type===`POSITION`&&!e.positionId.trim()?`簽核節點需要指定職位。`:null}function Tn(e){return e.edges.some(t=>J(t,e.nodes)&&!!(t.data.condition||t.data.conditionFieldKey||t.data.conditionOperator||t.data.conditionValue))}function En(e){return e?.fields.map(e=>({fieldType:e.type,id:e.fieldKey,name:`${e.label} (${e.fieldKey})`}))??[]}function Dn(e,t){return t?e?.fields.find(e=>e.fieldKey===t)??null:null}function On(e){if(!e)return[];let t=An(e);return rt.filter(e=>t.includes(e.id))}function kn(e){return rt.some(t=>t.id===e)?e:null}function An(e){return e.type===`file_upload`?[`IS_FILLED`,`IS_EMPTY`]:e.type===`boolean`?[`EQUALS`,`NOT_EQUALS`,`IS_FILLED`,`IS_EMPTY`]:e.type===`date`||e.type===`datetime`||e.type===`money`||e.type===`number`?[`EQUALS`,`NOT_EQUALS`,`GREATER_THAN`,`GREATER_THAN_OR_EQUALS`,`LESS_THAN`,`LESS_THAN_OR_EQUALS`,`IS_FILLED`,`IS_EMPTY`]:[`EQUALS`,`NOT_EQUALS`,`IS_FILLED`,`IS_EMPTY`]}function jn(e){return e?e.type===`boolean`?[{id:`true`,name:`是`},{id:`false`,name:`否`}]:e.type===`checkbox`||e.type===`radio`||e.type===`select`?e.options.map(e=>({id:e.value,name:e.label})):[]:[]}function Mn(e){return it.includes(e)}function Nn(e,t){if(e.data.label)return e.data.label;if(J(e,t))return q(e);if(Pn(e,t))return`同時進行`}function q(e){return e.data.isDefault?`其他情況`:`請設定條件`}function J(e,t){return t.some(t=>t.id===e.source&&t.type===`exclusiveGateway`)}function Pn(e,t){return t.some(t=>t.id===e.source&&t.type===`parallelGateway`)}function Fn(e){return e.type===`NOTIFY`&&e.recipients.type===`DIRECT`?e.recipients.memberIds:[]}function Y(e){return e instanceof Error?e.message:`發生未知錯誤`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return mt}});
65
+ //# sourceMappingURL=designer-DCn6_v4b.cjs.map