@rytass/bpm-core-react 0.22.0 → 0.24.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 (166) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +1 -0
  3. package/dist/chunks/FormBuilderView-Bg9ftYz-.cjs +4 -0
  4. package/dist/chunks/FormBuilderView-Bg9ftYz-.cjs.map +1 -0
  5. package/dist/chunks/{FormBuilderView-DbfbLZCI.js → FormBuilderView-CBvdcg_t.js} +675 -614
  6. package/dist/chunks/FormBuilderView-CBvdcg_t.js.map +1 -0
  7. package/dist/chunks/FormRendererView-D-p6GDQB.cjs +6 -0
  8. package/dist/chunks/FormRendererView-D-p6GDQB.cjs.map +1 -0
  9. package/dist/chunks/FormRendererView-DHXmekC3.js +1319 -0
  10. package/dist/chunks/FormRendererView-DHXmekC3.js.map +1 -0
  11. package/dist/chunks/{approval-instance-list-page-Cv5I1YPX.cjs → approval-instance-list-page-BqkG9jiR.cjs} +2 -2
  12. package/dist/chunks/{approval-instance-list-page-Cv5I1YPX.cjs.map → approval-instance-list-page-BqkG9jiR.cjs.map} +1 -1
  13. package/dist/chunks/{approval-instance-list-page-BI5fIXc-.js → approval-instance-list-page-CsSpIN4C.js} +2 -2
  14. package/dist/chunks/{approval-instance-list-page-BI5fIXc-.js.map → approval-instance-list-page-CsSpIN4C.js.map} +1 -1
  15. package/dist/chunks/compose-B43jtdyL.cjs +2 -0
  16. package/dist/chunks/compose-B43jtdyL.cjs.map +1 -0
  17. package/dist/chunks/{compose-U1zs3Yof.js → compose-C7yS6bJm.js} +162 -148
  18. package/dist/chunks/compose-C7yS6bJm.js.map +1 -0
  19. package/dist/chunks/{dashboard-page-BoqNhjT_.js → dashboard-page-DBJCsPya.js} +2 -2
  20. package/dist/chunks/{dashboard-page-BoqNhjT_.js.map → dashboard-page-DBJCsPya.js.map} +1 -1
  21. package/dist/chunks/{dashboard-page-D7YJ3udk.cjs → dashboard-page-lqlLELKs.cjs} +2 -2
  22. package/dist/chunks/{dashboard-page-D7YJ3udk.cjs.map → dashboard-page-lqlLELKs.cjs.map} +1 -1
  23. package/dist/chunks/{designer-DPG7R_WP.js → designer-B9Ut4xze.js} +1786 -1463
  24. package/dist/chunks/designer-B9Ut4xze.js.map +1 -0
  25. package/dist/chunks/designer-eXw7R9ug.cjs +69 -0
  26. package/dist/chunks/designer-eXw7R9ug.cjs.map +1 -0
  27. package/dist/chunks/{detail-CHZDNNM6.js → detail-BB_uYaoM.js} +904 -896
  28. package/dist/chunks/detail-BB_uYaoM.js.map +1 -0
  29. package/dist/chunks/detail-DN8pEzUJ.cjs +5 -0
  30. package/dist/chunks/detail-DN8pEzUJ.cjs.map +1 -0
  31. package/dist/chunks/instance-error-message-BKt07-Bo.js +270 -0
  32. package/dist/chunks/instance-error-message-BKt07-Bo.js.map +1 -0
  33. package/dist/chunks/instance-error-message-BL_X7Af8.cjs +2 -0
  34. package/dist/chunks/instance-error-message-BL_X7Af8.cjs.map +1 -0
  35. package/dist/chunks/member-profile-resolution-CJlgVdTR.js +44 -0
  36. package/dist/chunks/member-profile-resolution-CJlgVdTR.js.map +1 -0
  37. package/dist/chunks/member-profile-resolution-DiH-P-Vh.cjs +2 -0
  38. package/dist/chunks/member-profile-resolution-DiH-P-Vh.cjs.map +1 -0
  39. package/dist/chunks/{providers-CQWekD7_.js → providers-D35lBOTd.js} +2 -2
  40. package/dist/chunks/{providers-CQWekD7_.js.map → providers-D35lBOTd.js.map} +1 -1
  41. package/dist/chunks/{providers-VUOh6i0i.cjs → providers-Dz4Wqxr6.cjs} +2 -2
  42. package/dist/chunks/{providers-VUOh6i0i.cjs.map → providers-Dz4Wqxr6.cjs.map} +1 -1
  43. package/dist/chunks/{routes-config-C1j_vFKo.cjs → routes-config-BWjZDAU3.cjs} +2 -2
  44. package/dist/chunks/{routes-config-C1j_vFKo.cjs.map → routes-config-BWjZDAU3.cjs.map} +1 -1
  45. package/dist/chunks/{routes-config-BcNaWJWJ.js → routes-config-DjEOE9eP.js} +3 -2
  46. package/dist/chunks/{routes-config-BcNaWJWJ.js.map → routes-config-DjEOE9eP.js.map} +1 -1
  47. package/dist/chunks/users-C_Dtw_sR.cjs +2 -0
  48. package/dist/chunks/users-C_Dtw_sR.cjs.map +1 -0
  49. package/dist/chunks/users-wgM3TqU3.js +513 -0
  50. package/dist/chunks/users-wgM3TqU3.js.map +1 -0
  51. package/dist/index.cjs +1 -1
  52. package/dist/index.js +4 -4
  53. package/dist/lib/routes-config.d.cts +2 -0
  54. package/dist/lib/routes-config.d.ts +2 -0
  55. package/dist/next/index.cjs +1 -1
  56. package/dist/next/index.js +2 -2
  57. package/dist/pages/admin/stuck-instances/index.cjs +2 -0
  58. package/dist/pages/admin/stuck-instances/index.cjs.map +1 -0
  59. package/dist/pages/admin/stuck-instances/index.d.cts +4 -0
  60. package/dist/pages/admin/stuck-instances/index.d.ts +4 -0
  61. package/dist/pages/admin/stuck-instances/index.js +13 -0
  62. package/dist/pages/admin/stuck-instances/index.js.map +1 -0
  63. package/dist/pages/admin/users/index.cjs +1 -1
  64. package/dist/pages/admin/users/index.js +1 -1
  65. package/dist/pages/instances/detail/index.cjs +1 -1
  66. package/dist/pages/instances/detail/index.js +1 -1
  67. package/dist/pages/templates/compose/index.cjs +1 -1
  68. package/dist/pages/templates/compose/index.js +1 -1
  69. package/dist/pages/templates/designer/index.cjs +1 -1
  70. package/dist/pages/templates/designer/index.js +1 -1
  71. package/dist/views/admin/index.cjs +1 -1
  72. package/dist/views/admin/index.d.cts +1 -0
  73. package/dist/views/admin/index.d.ts +1 -0
  74. package/dist/views/admin/index.js +3 -2
  75. package/dist/views/admin/stuck-instances/AdminStuckInstancesView.d.cts +10 -0
  76. package/dist/views/admin/stuck-instances/AdminStuckInstancesView.d.ts +10 -0
  77. package/dist/views/admin/stuck-instances/StuckInstanceCancelModal.d.cts +14 -0
  78. package/dist/views/admin/stuck-instances/StuckInstanceCancelModal.d.ts +14 -0
  79. package/dist/views/admin/stuck-instances/index.cjs +2 -0
  80. package/dist/views/admin/stuck-instances/index.cjs.map +1 -0
  81. package/dist/views/admin/stuck-instances/index.d.cts +2 -0
  82. package/dist/views/admin/stuck-instances/index.d.ts +2 -0
  83. package/dist/views/admin/stuck-instances/index.js +237 -0
  84. package/dist/views/admin/stuck-instances/index.js.map +1 -0
  85. package/dist/views/admin/users/index.cjs +1 -1
  86. package/dist/views/admin/users/index.js +1 -1
  87. package/dist/views/cc/index.cjs +1 -1
  88. package/dist/views/cc/index.js +1 -1
  89. package/dist/views/dashboard/index.cjs +1 -1
  90. package/dist/views/dashboard/index.js +1 -1
  91. package/dist/views/forms/builder/index.cjs +1 -1
  92. package/dist/views/forms/builder/index.js +1 -1
  93. package/dist/views/forms/renderer/FormRendererView.d.cts +26 -1
  94. package/dist/views/forms/renderer/FormRendererView.d.ts +26 -1
  95. package/dist/views/forms/renderer/index.cjs +1 -1
  96. package/dist/views/forms/renderer/index.js +1 -1
  97. package/dist/views/inbox/index.cjs +1 -1
  98. package/dist/views/inbox/index.js +1 -1
  99. package/dist/views/instances/approver-filled-form.d.cts +56 -20
  100. package/dist/views/instances/approver-filled-form.d.ts +56 -20
  101. package/dist/views/instances/detail/index.cjs +1 -1
  102. package/dist/views/instances/detail/index.js +1 -1
  103. package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +7 -0
  104. package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +7 -0
  105. package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +1 -1
  106. package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +1 -1
  107. package/dist/views/instances/new/index.cjs +1 -1
  108. package/dist/views/instances/new/index.js +5 -5
  109. package/dist/views/instances/new/index.js.map +1 -1
  110. package/dist/views/search/index.cjs +1 -1
  111. package/dist/views/search/index.js +1 -1
  112. package/dist/views/sent/index.cjs +1 -1
  113. package/dist/views/sent/index.js +1 -1
  114. package/dist/views/templates/compose/index.cjs +1 -1
  115. package/dist/views/templates/compose/index.js +1 -1
  116. package/dist/views/templates/compose/steps/ComposeReviewStep.d.cts +3 -1
  117. package/dist/views/templates/compose/steps/ComposeReviewStep.d.ts +3 -1
  118. package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.cts +4 -1
  119. package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.ts +4 -1
  120. package/dist/views/templates/compose/use-template-compose-wizard.d.cts +3 -1
  121. package/dist/views/templates/compose/use-template-compose-wizard.d.ts +3 -1
  122. package/dist/views/templates/designer/TemplateDesignerView.d.cts +10 -1
  123. package/dist/views/templates/designer/TemplateDesignerView.d.ts +10 -1
  124. package/dist/views/templates/designer/approver-resolver-model.d.cts +31 -0
  125. package/dist/views/templates/designer/approver-resolver-model.d.ts +31 -0
  126. package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.cts +3 -1
  127. package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.ts +3 -1
  128. package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.cts +3 -2
  129. package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.ts +3 -2
  130. package/dist/views/templates/designer/index.cjs +1 -1
  131. package/dist/views/templates/designer/index.js +1 -1
  132. package/dist/views/templates/designer/launch-mode.d.cts +19 -0
  133. package/dist/views/templates/designer/launch-mode.d.ts +19 -0
  134. package/dist/views/templates/designer/node-actor-resolver-options.d.cts +30 -3
  135. package/dist/views/templates/designer/node-actor-resolver-options.d.ts +30 -3
  136. package/dist/views/templates/designer/publish-default-value-check.d.cts +36 -0
  137. package/dist/views/templates/designer/publish-default-value-check.d.ts +36 -0
  138. package/dist/views/templates/index.cjs +1 -1
  139. package/dist/views/templates/index.js +1 -1
  140. package/dist/views/templates/versions/index.cjs +1 -1
  141. package/dist/views/templates/versions/index.js +1 -1
  142. package/package.json +23 -3
  143. package/dist/chunks/FormBuilderView-Bok4Y59D.cjs +0 -4
  144. package/dist/chunks/FormBuilderView-Bok4Y59D.cjs.map +0 -1
  145. package/dist/chunks/FormBuilderView-DbfbLZCI.js.map +0 -1
  146. package/dist/chunks/FormRendererView-CAyPXhPq.js +0 -1351
  147. package/dist/chunks/FormRendererView-CAyPXhPq.js.map +0 -1
  148. package/dist/chunks/FormRendererView-iLlHFIUR.cjs +0 -6
  149. package/dist/chunks/FormRendererView-iLlHFIUR.cjs.map +0 -1
  150. package/dist/chunks/compose-DP1N4twA.cjs +0 -2
  151. package/dist/chunks/compose-DP1N4twA.cjs.map +0 -1
  152. package/dist/chunks/compose-U1zs3Yof.js.map +0 -1
  153. package/dist/chunks/designer-CWL-dCQ_.cjs +0 -69
  154. package/dist/chunks/designer-CWL-dCQ_.cjs.map +0 -1
  155. package/dist/chunks/designer-DPG7R_WP.js.map +0 -1
  156. package/dist/chunks/detail-BUfsSal0.cjs +0 -5
  157. package/dist/chunks/detail-BUfsSal0.cjs.map +0 -1
  158. package/dist/chunks/detail-CHZDNNM6.js.map +0 -1
  159. package/dist/chunks/instance-error-message-BEM4O_Kj.js +0 -208
  160. package/dist/chunks/instance-error-message-BEM4O_Kj.js.map +0 -1
  161. package/dist/chunks/instance-error-message-BpCLCOjp.cjs +0 -2
  162. package/dist/chunks/instance-error-message-BpCLCOjp.cjs.map +0 -1
  163. package/dist/chunks/users-BBtiZ9QQ.js +0 -486
  164. package/dist/chunks/users-BBtiZ9QQ.js.map +0 -1
  165. package/dist/chunks/users-EqSzDhuj.cjs +0 -2
  166. package/dist/chunks/users-EqSzDhuj.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { n as e } from "./auth-provider-C2b-5mGt.js";
3
3
  import { r as t } from "./router-adapter-CkxCyzf5.js";
4
- import { r as n } from "./routes-config-BcNaWJWJ.js";
4
+ import { r as n } from "./routes-config-DjEOE9eP.js";
5
5
  import { useCallback as r, useEffect as i, useMemo as a, useState as o } from "react";
6
6
  import { BaseCard as s, Button as c, CardGroup as l, PageHeader as u, Section as d, SectionGroup as f, Typography as p } from "@mezzanine-ui/react";
7
7
  import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
@@ -114,4 +114,4 @@ function w(e) {
114
114
  }
115
115
  export { S as t };
116
116
 
117
- //# sourceMappingURL=dashboard-page-BoqNhjT_.js.map
117
+ //# sourceMappingURL=dashboard-page-DBJCsPya.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-page-BoqNhjT_.js","names":["_Fragment","styles","useAuth","useRouterAdapter","useBPMRoutes","Fragment$1","ContentHeader","dashboard_page_module_default","EMPTY_DASHBOARD_SUMMARY","DashboardPage","router","routes","currentMemberId","member","error","setError","useState","loading","setLoading","summary","setSummary","refreshSummary","useCallback","readWorkflowDashboardSummary","requestError","readErrorMessage","metrics","useMemo","readMetricValue","PageHeader","Button","PlusIcon","SectionGroup","Section","Typography","CardGroup","BaseCard","metric","event","value"],"sources":["../../src/components/dashboard-page.tsx"],"sourcesContent":["'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-DBJCsPya.js","names":["_Fragment","styles","useAuth","useRouterAdapter","useBPMRoutes","Fragment$1","ContentHeader","dashboard_page_module_default","EMPTY_DASHBOARD_SUMMARY","DashboardPage","router","routes","currentMemberId","member","error","setError","useState","loading","setLoading","summary","setSummary","refreshSummary","useCallback","readWorkflowDashboardSummary","requestError","readErrorMessage","metrics","useMemo","readMetricValue","PageHeader","Button","PlusIcon","SectionGroup","Section","Typography","CardGroup","BaseCard","metric","event","value"],"sources":["../../src/components/dashboard-page.tsx"],"sourcesContent":["'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,2 +1,2 @@
1
- "use client";require('../dashboard-page.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./auth-provider-4BeCw7cI.cjs"),n=require("./router-adapter--gYs13E8.cjs"),r=require("./routes-config-C1j_vFKo.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=n.r(),f=r.r(),{member:h}=t.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);else{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-D7YJ3udk.cjs.map
1
+ "use client";require('../dashboard-page.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./auth-provider-4BeCw7cI.cjs"),n=require("./router-adapter--gYs13E8.cjs"),r=require("./routes-config-BWjZDAU3.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=n.r(),f=r.r(),{member:h}=t.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);else{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-lqlLELKs.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-page-D7YJ3udk.cjs","names":["useRouterAdapter","useBPMRoutes","useAuth","useState","useCallback","readWorkflowDashboardSummary","useMemo","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","Typography","CardGroup","BaseCard","styles","require_rolldown_runtime","require_auth_provider","require_router_adapter","require_routes_config","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","dashboard_page_module_default","EMPTY_DASHBOARD_SUMMARY","DashboardPage","router","routes","currentMemberId","member","error","setError","loading","setLoading","summary","setSummary","refreshSummary","requestError","readErrorMessage","metrics","readMetricValue","metric","event","value"],"sources":["../../src/components/dashboard-page.tsx"],"sourcesContent":["'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-lqlLELKs.cjs","names":["useRouterAdapter","useBPMRoutes","useAuth","useState","useCallback","readWorkflowDashboardSummary","useMemo","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","Typography","CardGroup","BaseCard","styles","require_rolldown_runtime","require_auth_provider","require_router_adapter","require_routes_config","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","dashboard_page_module_default","EMPTY_DASHBOARD_SUMMARY","DashboardPage","router","routes","currentMemberId","member","error","setError","loading","setLoading","summary","setSummary","refreshSummary","requestError","readErrorMessage","metrics","readMetricValue","metric","event","value"],"sources":["../../src/components/dashboard-page.tsx"],"sourcesContent":["'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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"}