@rytass/bpm-core-react 0.3.8 → 0.4.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 (227) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +69 -4
  3. package/dist/chunks/approval-instance-list-page-BtEc8Cs3.js +278 -0
  4. package/dist/chunks/approval-instance-list-page-BtEc8Cs3.js.map +1 -0
  5. package/dist/chunks/approval-instance-list-page-UNIIgUZy.cjs +2 -0
  6. package/dist/chunks/approval-instance-list-page-UNIIgUZy.cjs.map +1 -0
  7. package/dist/chunks/auth-provider-D2P-qWmY.cjs +2 -0
  8. package/dist/chunks/auth-provider-D2P-qWmY.cjs.map +1 -0
  9. package/dist/chunks/auth-provider-TTO9eNZV.js +83 -0
  10. package/dist/chunks/auth-provider-TTO9eNZV.js.map +1 -0
  11. package/dist/chunks/{builder-D950gct_.js → builder-C3E-8OJu.js} +474 -478
  12. package/dist/chunks/builder-C3E-8OJu.js.map +1 -0
  13. package/dist/chunks/builder-f-Q_0NUs.cjs +3 -0
  14. package/dist/chunks/builder-f-Q_0NUs.cjs.map +1 -0
  15. package/dist/chunks/categories-B6QZKZRt.cjs +2 -0
  16. package/dist/chunks/categories-B6QZKZRt.cjs.map +1 -0
  17. package/dist/chunks/categories-DBPoSrsi.js +382 -0
  18. package/dist/chunks/categories-DBPoSrsi.js.map +1 -0
  19. package/dist/chunks/chunk-CMqjfN_6.cjs +1 -0
  20. package/dist/chunks/dashboard-page-CQRBJxze.js +119 -0
  21. package/dist/chunks/dashboard-page-CQRBJxze.js.map +1 -0
  22. package/dist/chunks/dashboard-page-DrDChhg1.cjs +2 -0
  23. package/dist/chunks/dashboard-page-DrDChhg1.cjs.map +1 -0
  24. package/dist/chunks/delegations-CFXaJrdX.cjs +2 -0
  25. package/dist/chunks/delegations-CFXaJrdX.cjs.map +1 -0
  26. package/dist/chunks/delegations-D5pPEWsP.js +641 -0
  27. package/dist/chunks/delegations-D5pPEWsP.js.map +1 -0
  28. package/dist/chunks/delegations-DwbYkNUg.cjs +2 -0
  29. package/dist/chunks/delegations-DwbYkNUg.cjs.map +1 -0
  30. package/dist/chunks/delegations-FTLaWo1Y.js +568 -0
  31. package/dist/chunks/delegations-FTLaWo1Y.js.map +1 -0
  32. package/dist/chunks/detail-B9JkYNHc.cjs +2 -0
  33. package/dist/chunks/detail-B9JkYNHc.cjs.map +1 -0
  34. package/dist/chunks/detail-CSxI04gB.js +1518 -0
  35. package/dist/chunks/detail-CSxI04gB.js.map +1 -0
  36. package/dist/chunks/format-date-time-XxBzF0F5.cjs +2 -0
  37. package/dist/chunks/{format-date-time-26_pFvv4.cjs.map → format-date-time-XxBzF0F5.cjs.map} +1 -1
  38. package/dist/chunks/login-BfmfCclF.cjs +2 -0
  39. package/dist/chunks/{login-CQ9MfwcC.cjs.map → login-BfmfCclF.cjs.map} +1 -1
  40. package/dist/chunks/{login-C20yVxbc.js → login-xgI4wLHe.js} +3 -2
  41. package/dist/chunks/{login-C20yVxbc.js.map → login-xgI4wLHe.js.map} +1 -1
  42. package/dist/chunks/notifications-BoNa1BXD.js +193 -0
  43. package/dist/chunks/notifications-BoNa1BXD.js.map +1 -0
  44. package/dist/chunks/notifications-a-FCxV02.cjs +2 -0
  45. package/dist/chunks/notifications-a-FCxV02.cjs.map +1 -0
  46. package/dist/chunks/orgs-BIiqzHvb.cjs +2 -0
  47. package/dist/chunks/orgs-BIiqzHvb.cjs.map +1 -0
  48. package/dist/chunks/orgs-Cc18umVt.js +1944 -0
  49. package/dist/chunks/orgs-Cc18umVt.js.map +1 -0
  50. package/dist/chunks/router-adapter-BdHZXLS3.js +23 -0
  51. package/dist/chunks/router-adapter-BdHZXLS3.js.map +1 -0
  52. package/dist/chunks/router-adapter-BybHrCNP.cjs +2 -0
  53. package/dist/chunks/router-adapter-BybHrCNP.cjs.map +1 -0
  54. package/dist/chunks/templates-CL8bPvgn.cjs +2 -0
  55. package/dist/chunks/templates-CL8bPvgn.cjs.map +1 -0
  56. package/dist/chunks/templates-DNfDOPGm.js +380 -0
  57. package/dist/chunks/templates-DNfDOPGm.js.map +1 -0
  58. package/dist/chunks/users-CUY139DF.js +214 -0
  59. package/dist/chunks/users-CUY139DF.js.map +1 -0
  60. package/dist/chunks/users-qghSMtLn.cjs +2 -0
  61. package/dist/chunks/users-qghSMtLn.cjs.map +1 -0
  62. package/dist/components/approval-instance-list-page.d.ts +1 -2
  63. package/dist/components/bpm-notification-bell-button.d.ts +22 -0
  64. package/dist/components/dashboard-page.d.ts +1 -4
  65. package/dist/index.cjs +1 -1
  66. package/dist/index.cjs.map +1 -1
  67. package/dist/index.css +1 -0
  68. package/dist/index.d.ts +3 -1
  69. package/dist/index.js +206 -97
  70. package/dist/index.js.map +1 -1
  71. package/dist/lib/notification-drawer-provider.d.ts +3 -2
  72. package/dist/lib/notification-unread-provider.d.ts +6 -5
  73. package/dist/lib/providers.d.ts +3 -2
  74. package/dist/lib/use-bpm-logout.d.ts +12 -0
  75. package/dist/lib/use-bpm-member.d.ts +11 -0
  76. package/dist/pages/admin/delegations/index.cjs +1 -1
  77. package/dist/pages/admin/delegations/index.js +1 -1
  78. package/dist/pages/admin/orgs/index.cjs +1 -1
  79. package/dist/pages/admin/orgs/index.js +1 -1
  80. package/dist/pages/admin/users/index.cjs +1 -1
  81. package/dist/pages/admin/users/index.js +1 -1
  82. package/dist/pages/delegations/index.cjs +1 -1
  83. package/dist/pages/delegations/index.js +1 -1
  84. package/dist/pages/forms/builder/index.cjs +1 -1
  85. package/dist/pages/forms/builder/index.js +1 -1
  86. package/dist/pages/instances/detail/index.cjs +1 -1
  87. package/dist/pages/instances/detail/index.js +1 -1
  88. package/dist/pages/login/index.cjs +1 -1
  89. package/dist/pages/login/index.js +1 -1
  90. package/dist/pages/settings/notifications/index.cjs +1 -1
  91. package/dist/pages/settings/notifications/index.js +1 -1
  92. package/dist/pages/templates/categories/index.cjs +1 -1
  93. package/dist/pages/templates/categories/index.js +1 -1
  94. package/dist/pages/templates/index.cjs +1 -1
  95. package/dist/pages/templates/index.js +1 -1
  96. package/dist/views/admin/delegations/AdminDelegationsView.d.ts +1 -4
  97. package/dist/views/admin/delegations/index.cjs +1 -1
  98. package/dist/views/admin/delegations/index.js +1 -1
  99. package/dist/views/admin/index.cjs +1 -1
  100. package/dist/views/admin/index.js +3 -3
  101. package/dist/views/admin/orgs/AdminOrgsView.d.ts +1 -4
  102. package/dist/views/admin/orgs/index.cjs +1 -1
  103. package/dist/views/admin/orgs/index.js +1 -1
  104. package/dist/views/admin/users/AdminUsersView.d.ts +1 -4
  105. package/dist/views/admin/users/index.cjs +1 -1
  106. package/dist/views/admin/users/index.js +1 -1
  107. package/dist/views/cc/CcView.d.ts +1 -3
  108. package/dist/views/cc/index.cjs +1 -1
  109. package/dist/views/cc/index.cjs.map +1 -1
  110. package/dist/views/cc/index.js +2 -3
  111. package/dist/views/cc/index.js.map +1 -1
  112. package/dist/views/dashboard/DashboardView.d.ts +1 -3
  113. package/dist/views/dashboard/index.cjs +1 -1
  114. package/dist/views/dashboard/index.cjs.map +1 -1
  115. package/dist/views/dashboard/index.js +3 -3
  116. package/dist/views/dashboard/index.js.map +1 -1
  117. package/dist/views/delegations/DelegationsView.d.ts +1 -4
  118. package/dist/views/delegations/index.cjs +1 -1
  119. package/dist/views/delegations/index.js +1 -1
  120. package/dist/views/forms/FormsView.d.ts +1 -3
  121. package/dist/views/forms/builder/index.cjs +1 -1
  122. package/dist/views/forms/builder/index.js +1 -1
  123. package/dist/views/forms/index.cjs +1 -1
  124. package/dist/views/forms/index.cjs.map +1 -1
  125. package/dist/views/forms/index.js +95 -99
  126. package/dist/views/forms/index.js.map +1 -1
  127. package/dist/views/inbox/InboxView.d.ts +1 -3
  128. package/dist/views/inbox/index.cjs +1 -1
  129. package/dist/views/inbox/index.cjs.map +1 -1
  130. package/dist/views/inbox/index.js +91 -94
  131. package/dist/views/inbox/index.js.map +1 -1
  132. package/dist/views/instances/detail/index.cjs +1 -1
  133. package/dist/views/instances/detail/index.js +1 -1
  134. package/dist/views/instances/new/index.cjs +1 -1
  135. package/dist/views/instances/new/index.cjs.map +1 -1
  136. package/dist/views/instances/new/index.js +71 -77
  137. package/dist/views/instances/new/index.js.map +1 -1
  138. package/dist/views/login/index.cjs +1 -1
  139. package/dist/views/login/index.js +1 -1
  140. package/dist/views/root/RootView.d.ts +1 -3
  141. package/dist/views/search/SearchView.d.ts +1 -3
  142. package/dist/views/search/index.cjs +1 -1
  143. package/dist/views/search/index.cjs.map +1 -1
  144. package/dist/views/search/index.js +2 -3
  145. package/dist/views/search/index.js.map +1 -1
  146. package/dist/views/sent/SentView.d.ts +1 -3
  147. package/dist/views/sent/index.cjs +1 -1
  148. package/dist/views/sent/index.cjs.map +1 -1
  149. package/dist/views/sent/index.js +2 -3
  150. package/dist/views/sent/index.js.map +1 -1
  151. package/dist/views/settings/index.cjs +1 -1
  152. package/dist/views/settings/index.js +1 -1
  153. package/dist/views/settings/notifications/SettingsNotificationsView.d.ts +1 -4
  154. package/dist/views/settings/notifications/index.cjs +1 -1
  155. package/dist/views/settings/notifications/index.js +1 -1
  156. package/dist/views/templates/TemplatesView.d.ts +1 -4
  157. package/dist/views/templates/categories/TemplateCategoriesView.d.ts +1 -4
  158. package/dist/views/templates/categories/index.cjs +1 -1
  159. package/dist/views/templates/categories/index.js +1 -1
  160. package/dist/views/templates/designer/TemplateDesignerView.d.ts +1 -2
  161. package/dist/views/templates/designer/index.cjs +7 -7
  162. package/dist/views/templates/designer/index.cjs.map +1 -1
  163. package/dist/views/templates/designer/index.js +707 -711
  164. package/dist/views/templates/designer/index.js.map +1 -1
  165. package/dist/views/templates/index.cjs +1 -1
  166. package/dist/views/templates/index.js +2 -2
  167. package/dist/views/templates/versions/TemplateVersionsView.d.ts +1 -2
  168. package/dist/views/templates/versions/index.cjs +1 -1
  169. package/dist/views/templates/versions/index.cjs.map +1 -1
  170. package/dist/views/templates/versions/index.js +45 -49
  171. package/dist/views/templates/versions/index.js.map +1 -1
  172. package/package.json +2 -2
  173. package/dist/app-navigation.css +0 -1
  174. package/dist/chunks/app-navigation-BSkMsEhy.js +0 -268
  175. package/dist/chunks/app-navigation-BSkMsEhy.js.map +0 -1
  176. package/dist/chunks/app-navigation-KnlJCUp1.cjs +0 -2
  177. package/dist/chunks/app-navigation-KnlJCUp1.cjs.map +0 -1
  178. package/dist/chunks/approval-instance-list-page-CVXgE2K3.cjs +0 -2
  179. package/dist/chunks/approval-instance-list-page-CVXgE2K3.cjs.map +0 -1
  180. package/dist/chunks/approval-instance-list-page-CqNdoZqx.js +0 -282
  181. package/dist/chunks/approval-instance-list-page-CqNdoZqx.js.map +0 -1
  182. package/dist/chunks/auth-provider-BV8Iiwfb.cjs +0 -2
  183. package/dist/chunks/auth-provider-BV8Iiwfb.cjs.map +0 -1
  184. package/dist/chunks/auth-provider-Bnox5gsx.js +0 -98
  185. package/dist/chunks/auth-provider-Bnox5gsx.js.map +0 -1
  186. package/dist/chunks/builder-CMlJfQHE.cjs +0 -3
  187. package/dist/chunks/builder-CMlJfQHE.cjs.map +0 -1
  188. package/dist/chunks/builder-D950gct_.js.map +0 -1
  189. package/dist/chunks/categories-5yEM3p3N.cjs +0 -2
  190. package/dist/chunks/categories-5yEM3p3N.cjs.map +0 -1
  191. package/dist/chunks/categories-BIpOG451.js +0 -387
  192. package/dist/chunks/categories-BIpOG451.js.map +0 -1
  193. package/dist/chunks/dashboard-page-Bx1-Ys3e.js +0 -122
  194. package/dist/chunks/dashboard-page-Bx1-Ys3e.js.map +0 -1
  195. package/dist/chunks/dashboard-page-CQNRbMkJ.cjs +0 -2
  196. package/dist/chunks/dashboard-page-CQNRbMkJ.cjs.map +0 -1
  197. package/dist/chunks/delegations-B2j-wNEO.js +0 -646
  198. package/dist/chunks/delegations-B2j-wNEO.js.map +0 -1
  199. package/dist/chunks/delegations-CsB9ozLu.cjs +0 -2
  200. package/dist/chunks/delegations-CsB9ozLu.cjs.map +0 -1
  201. package/dist/chunks/delegations-CvtwTXNP.cjs +0 -2
  202. package/dist/chunks/delegations-CvtwTXNP.cjs.map +0 -1
  203. package/dist/chunks/delegations-dKodb0WW.js +0 -573
  204. package/dist/chunks/delegations-dKodb0WW.js.map +0 -1
  205. package/dist/chunks/detail-BcGAqJ_R.js +0 -1523
  206. package/dist/chunks/detail-BcGAqJ_R.js.map +0 -1
  207. package/dist/chunks/detail-CqjqLd65.cjs +0 -2
  208. package/dist/chunks/detail-CqjqLd65.cjs.map +0 -1
  209. package/dist/chunks/format-date-time-26_pFvv4.cjs +0 -2
  210. package/dist/chunks/login-CQ9MfwcC.cjs +0 -2
  211. package/dist/chunks/notifications-2swRqDPF.js +0 -198
  212. package/dist/chunks/notifications-2swRqDPF.js.map +0 -1
  213. package/dist/chunks/notifications-BaYDebFt.cjs +0 -2
  214. package/dist/chunks/notifications-BaYDebFt.cjs.map +0 -1
  215. package/dist/chunks/orgs-CuHxxd_n.js +0 -1949
  216. package/dist/chunks/orgs-CuHxxd_n.js.map +0 -1
  217. package/dist/chunks/orgs-YMiVLNvL.cjs +0 -2
  218. package/dist/chunks/orgs-YMiVLNvL.cjs.map +0 -1
  219. package/dist/chunks/templates-DTkbSgFY.cjs +0 -2
  220. package/dist/chunks/templates-DTkbSgFY.cjs.map +0 -1
  221. package/dist/chunks/templates-DoDWM68t.js +0 -384
  222. package/dist/chunks/templates-DoDWM68t.js.map +0 -1
  223. package/dist/chunks/users-3ySyUW4u.cjs +0 -2
  224. package/dist/chunks/users-3ySyUW4u.cjs.map +0 -1
  225. package/dist/chunks/users-sMfrSjRQ.js +0 -219
  226. package/dist/chunks/users-sMfrSjRQ.js.map +0 -1
  227. package/dist/components/app-navigation.d.ts +0 -41
@@ -0,0 +1,2 @@
1
+ "use client";require('../detail.css');const e=require("./chunk-CMqjfN_6.cjs"),t=require("./auth-provider-D2P-qWmY.cjs"),n=require("./format-date-time-XxBzF0F5.cjs"),r=require("./bpm-form-field-Bc6k4ZEO.cjs"),i=require("./FormRendererView-BwVsH2eX.cjs");let a=require("react"),o=require("@mezzanine-ui/react"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/react/ContentHeader");l=e.t(l,1);let u=require("@mezzanine-ui/icons"),d=require("@rytass/bpm-core-client/form"),f=require("@xyflow/react"),p=require("dagre");p=e.t(p,1);let m=require("@mezzanine-ui/core/stepper"),h=require("react-pdf");var g={root:`bpm_root_ehm7w`,toolbar:`bpm_toolbar_R-tis`,pageControls:`bpm_pageControls_jM-rC`,zoomControls:`bpm_zoomControls_7RAbJ`,counter:`bpm_counter_ILUsD`,viewport:`bpm_viewport_DQXms`,page:`bpm_page_Cv5Rg`,state:`bpm_state_bpgp3`},_=760,ee=920,te=320,ne=32,re=.75,ie=1.75,v=.25;function ae({filename:e,fileUrl:t,onDownload:n}){let r=(0,a.useRef)(null),[i,c]=(0,a.useState)(null),[l,d]=(0,a.useState)(1),[f,p]=(0,a.useState)(1),[m,ae]=(0,a.useState)(_);(0,a.useEffect)(()=>{let e=r.current;if(!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(e=>{let t=e[0]?.contentRect.width;t&&ae(t)});return t.observe(e),()=>t.disconnect()},[]),(0,a.useEffect)(()=>{c(null),d(1),p(1)},[t]);let b=(0,a.useMemo)(()=>{let e=Math.max(te,m-ne);return Math.round(Math.min(ee,e)*f)},[f,m]),oe=(0,a.useCallback)(e=>{c(e.numPages),d(1)},[]),x=l>1,se=i!==null&&l<i,ce=f>re,le=f<ie,ue=i===null?`第 ${l} 頁`:`第 ${l} / ${i} 頁`,de=`${Math.round(f*100)}%`;return(0,s.jsxs)(`section`,{"aria-label":`${e} PDF 預覽`,className:g.root,children:[(0,s.jsxs)(`div`,{className:g.toolbar,children:[(0,s.jsxs)(`div`,{className:g.pageControls,"aria-label":`頁面切換`,children:[(0,s.jsx)(o.Button,{"aria-label":`上一頁`,disabled:!x,icon:u.ChevronLeftIcon,onClick:()=>{d(e=>Math.max(1,e-1))},size:`minor`,variant:`base-secondary`}),(0,s.jsx)(o.Typography,{className:g.counter,component:`span`,variant:`body`,children:ue}),(0,s.jsx)(o.Button,{"aria-label":`下一頁`,disabled:!se,icon:u.ChevronRightIcon,onClick:()=>{d(e=>i===null?e:Math.min(i,e+1))},size:`minor`,variant:`base-secondary`})]}),(0,s.jsxs)(`div`,{className:g.zoomControls,"aria-label":`縮放`,children:[(0,s.jsx)(o.Button,{"aria-label":`縮小`,disabled:!ce,icon:u.ZoomOutIcon,onClick:()=>{p(e=>Math.max(re,e-v))},size:`minor`,variant:`base-secondary`}),(0,s.jsx)(o.Typography,{className:g.counter,component:`span`,variant:`body`,children:de}),(0,s.jsx)(o.Button,{"aria-label":`放大`,disabled:!le,icon:u.ZoomInIcon,onClick:()=>{p(e=>Math.min(ie,e+v))},size:`minor`,variant:`base-secondary`})]}),n?(0,s.jsx)(o.Button,{icon:u.DownloadIcon,iconType:`leading`,onClick:n,size:`minor`,variant:`base-primary`,children:`下載`}):null]}),(0,s.jsx)(`div`,{className:g.viewport,ref:r,children:(0,s.jsx)(h.Document,{error:(0,s.jsx)(y,{message:`PDF 無法載入。`}),file:t,loading:(0,s.jsx)(y,{message:`正在載入 PDF...`}),noData:(0,s.jsx)(y,{message:`沒有可預覽的 PDF。`}),onLoadSuccess:oe,children:(0,s.jsx)(h.Page,{className:g.page,loading:(0,s.jsx)(y,{message:`正在載入頁面...`}),pageNumber:l,renderAnnotationLayer:!0,renderTextLayer:!0,width:b})})})]})}function y({message:e}){return(0,s.jsx)(`div`,{className:g.state,children:(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:e})})}var b={display:`grid`,gap:16},oe={display:`flex`,flexWrap:`wrap`,gap:8},x=184,se=96,ce={display:`grid`,gap:16},le={display:`grid`,gap:12,width:`100%`},ue={minWidth:`100%`,width:`100%`},de={display:`grid`,gap:12,width:`100%`},fe={background:`#f8fafc`,border:`1px solid #e2e8f0`,borderRadius:8,height:`min(64vh, 620px)`,minHeight:440,overflow:`hidden`,width:`min(80vw, 1040px)`},S={background:`#ffffff`,border:`1px solid #cbd5e1`,borderRadius:8,boxShadow:`0 8px 18px rgba(15, 23, 42, 0.08)`,display:`grid`,gap:6,minHeight:82,padding:12,width:184},pe={borderRadius:999,fontSize:12,fontWeight:600,justifySelf:`start`,lineHeight:`18px`,padding:`0 8px`},C={color:`#64748b`,fontSize:12,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},me={opacity:0},he={display:`flex`,flexWrap:`wrap`,gap:8},ge={alignItems:`center`,background:`#ffffff`,border:`1px solid #cbd5e1`,borderRadius:8,color:`#334155`,display:`inline-flex`,fontSize:12,fontWeight:600,gap:6,lineHeight:`20px`,padding:`4px 8px`},_e={cursor:`help`,textDecoration:`underline dotted`,textUnderlineOffset:3},ve={color:`var(--mzn-color-text-error)`};function ye(e){e&&(e.style.width=`100%`)}var be={workflowRuntime:Xe};function xe({instanceId:e}){let{member:p}=t.n(),m=p?.memberId??null,[h,g]=(0,a.useState)([]),[_,ee]=(0,a.useState)(null),[te,ne]=(0,a.useState)([]),[re,ie]=(0,a.useState)([]),[v,y]=(0,a.useState)([]),[x,se]=(0,a.useState)(null),[S,pe]=(0,a.useState)([]),[C,me]=(0,a.useState)([]),[_e,ve]=(0,a.useState)([]),[xe,T]=(0,a.useState)(null),[Te,E]=(0,a.useState)(!0),[D,O]=(0,a.useState)(!1),[k,A]=(0,a.useState)(!1),[je,Me]=(0,a.useState)(``),[Ne,j]=(0,a.useState)(!1),[Pe,M]=(0,a.useState)(``),[N,P]=(0,a.useState)(null),[Fe,Ie]=(0,a.useState)(!1),[Le,F]=(0,a.useState)(``),[Re,I]=(0,a.useState)(!1),[ze,R]=(0,a.useState)(null),[We,B]=(0,a.useState)(``),[V,H]=(0,a.useState)(null),[Je,Ye]=(0,a.useState)(!1),[U,W]=(0,a.useState)([]),[G,K]=(0,a.useState)(!1),[Xe,q]=(0,a.useState)({}),[J,et]=(0,a.useState)({}),[Y,tt]=(0,a.useState)(null),[rt,it]=(0,a.useState)(null),at=Pe.trim(),ot=je.trim(),st=Le.trim(),ct=We.trim();(0,a.useEffect)(()=>{Ot()},[m,e]),(0,a.useEffect)(()=>{et(_?.formData??{})},[_]);let X=(0,a.useMemo)(()=>S.find(e=>He(e,m)&&(e.status===`PENDING`||e.status===`IN_PROGRESS`))??null,[m,S]),Z=(0,a.useMemo)(()=>X&&_?_.workflowSnapshot.nodes.find(e=>e.id===X.nodeId)??null:null,[X,_]),lt=(0,a.useMemo)(()=>Z&&_?Be(_.workflowSnapshot,Z):[],[Z,_]),ut=Z?.type===`userTask`&&Z.data.returnBehavior.allowReturn,dt=lt.find(e=>e.id===ze)??lt[0]??null,ft=!!(_&&_.initiatorMemberId===m&&(_.state===`RUNNING`||_.state===`RETURNED`)),Q=!!(_&&_.initiatorMemberId===m&&_.state===`RETURNED`),pt=(0,a.useMemo)(()=>new Map(_e.map(e=>[e.memberId,e])),[_e]),mt=(0,a.useMemo)(()=>S.map(e=>({...e,assigneeLabel:z(e,pt),key:e.id,nodeLabel:L(e.nodeId,_?.workflowSnapshot??null),statusLabel:Ve(e.status)})),[_,pt,S]),ht=(0,a.useMemo)(()=>Oe(te),[te]),gt=(0,a.useMemo)(()=>new Map(v.map(e=>[e.id,e])),[v]),_t=(0,a.useMemo)(()=>ke(h,S,C,_?.workflowSnapshot??null,_?.state??`RUNNING`,pt,ht,gt,x),[h,_,pt,x,gt,ht,S,C]),vt=(0,a.useMemo)(()=>Ae(_t),[_t]),$=(0,a.useMemo)(()=>_?Qe(_.workflowSnapshot):null,[_]),yt=(0,a.useMemo)(()=>_&&$?Ze($,S,C,_.state):[],[_,$,S,C]),bt=(0,a.useMemo)(()=>$?$e($):[],[$]),xt=(0,a.useMemo)(()=>_?nt(_.workflowSnapshot):[],[_]),St=(0,a.useMemo)(()=>[{dataIndex:`nodeLabel`,key:`nodeLabel`,title:`節點`,width:180},{key:`assigneeMemberId`,title:`處理者`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:e.assigneeLabel}),width:180},{dataIndex:`statusLabel`,key:`statusLabel`,title:`狀態`,width:120},{key:`createdAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.createdAt)}),title:`建立時間`,width:220}],[]),Ct=(0,a.useMemo)(()=>re.map(e=>({attachment:e,createdAt:e.createdAt,filename:e.filename,id:e.id,key:e.id,mimeType:e.mimeType,sizeLabel:Se(Number(e.sizeBytes))})),[re]),wt=(0,a.useMemo)(()=>[{dataIndex:`filename`,key:`filename`,title:`檔名`,width:260},{dataIndex:`mimeType`,key:`mimeType`,title:`類型`,width:180},{dataIndex:`sizeLabel`,key:`sizeLabel`,title:`大小`,width:120},{key:`createdAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.createdAt)}),title:`上傳時間`,width:220}],[]),Tt=(0,a.useMemo)(()=>({render:e=>[...e.mimeType===`application/pdf`?[{icon:u.FileSearchIcon,iconType:`leading`,name:`預覽`,onClick:()=>{jt(e.attachment)}}]:[],{icon:u.DownloadIcon,iconType:`leading`,name:`下載`,onClick:()=>{At(e.attachment)}}],variant:`base-secondary`,width:160}),[]),Et=(0,a.useMemo)(()=>v.map(e=>({algorithm:e.algorithm,hashLabel:Ce(e.signedPayloadHash),key:e.id,keyVersion:e.keyVersion,signedAtLabel:n.t(e.signedAt),signerMemberId:e.signerMemberId})),[v]),Dt=(0,a.useMemo)(()=>[{dataIndex:`signerMemberId`,key:`signerMemberId`,title:`簽章者`,width:160},{dataIndex:`algorithm`,key:`algorithm`,title:`演算法`,width:150},{dataIndex:`keyVersion`,key:`keyVersion`,title:`Key 版本`,width:100},{dataIndex:`hashLabel`,key:`hashLabel`,title:`Payload Hash`,width:180},{dataIndex:`signedAtLabel`,key:`signedAtLabel`,title:`簽章時間`,width:220}],[]);async function Ot(){E(!0),T(null);try{let t=await(0,c.readApprovalInstance)(e);g(t.activityLogs),ee(t.instance),pe(t.tasks),me(t.workflowTokens);let[n,r,i,a]=await Promise.all([De(t.tasks),Ee(t),(0,c.listAttachments)(t.instance.id),(0,c.readInstanceSignatures)(t.instance.id)]);ne(n),ve(r),ie(i),y(a.signatures),se(a.verification)}catch(e){T(w(e))}finally{E(!1)}}async function kt(e,t){if(!m)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,c.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}async function At(e){if(!m)return;let t=await(0,c.readAttachmentDownloadUrl)({id:e.id});window.open(t,`_blank`,`noopener,noreferrer`)}async function jt(e){if(!m)return;let t=await(0,c.readAttachmentPreviewUrl)({id:e.id});tt(e),it(t)}async function Mt({action:e,comment:t,returnToNodeId:n=null,transferToMemberId:r=null}){if(!(!m||!X)){O(!0),T(null);try{await(0,c.decideTask)({action:e,comment:t,decidedByMemberId:m,returnToNodeId:n,taskId:X.id,transferToMemberId:r}),Ie(!1),I(!1),K(!1),M(``),F(``),B(``),H(null),R(null),P(null),await Ot()}catch(e){T(w(e))}finally{O(!1)}}}function Nt(){M(``),P(null),Ie(!0)}function Pt(){D||(Ie(!1),M(``),P(null))}function Ft(){F(``),R(lt[0]?.id??null),I(!0)}function It(){D||(I(!1),F(``),R(null))}function Lt(){B(``),H(null),K(!0),zt(``)}function Rt(){D||(K(!1),B(``),H(null))}async function zt(e){Ye(!0);try{W((await(0,c.searchMembers)(e)).filter(e=>e.memberId!==m).map(Ge))}catch(e){T(w(e))}finally{Ye(!1)}}async function Bt(){if(!at){P(`請輸入拒絕原因`);return}await Mt({action:`REJECTED`,comment:at})}async function Vt(){if(!V){T(`請選擇轉派對象`);return}await Mt({action:`TRANSFERRED`,comment:ct||null,transferToMemberId:V.id})}async function Ht(){await Mt({action:`RETURNED`,comment:st||null,returnToNodeId:dt?.id??null})}async function Ut(){if(!(!m||!_||!ft)){if(O(!0),T(null),q({}),_.formDefinitionSnapshot.schema&&_.formDefinitionSnapshot.uiSchema){let e=(0,d.validateFormRendererValues)({schema:_.formDefinitionSnapshot.schema,uiSchema:_.formDefinitionSnapshot.uiSchema,values:J});if(!e.valid){q(e.errors),T(`請先補齊必填欄位。`),e.firstInvalidFieldKey&&(0,d.focusFormRendererField)(e.firstInvalidFieldKey),O(!1);return}}try{await(0,c.cancelApprovalInstance)({cancelledByMemberId:m,comment:ot||null,instanceId:_.id}),Me(``),j(!1),await Ot()}catch(e){T(w(e))}finally{O(!1)}}}async function Wt(){if(!(!m||!_||!Q)){O(!0),T(null);try{await(0,c.resubmitApprovalInstance)({formData:J,initiatorMemberId:m,instanceId:_.id,title:_.title}),await Ot()}catch(e){T(w(e))}finally{O(!1)}}}return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.PageHeader,{children:(0,s.jsxs)(l.default,{description:_?`${Ue(_.state)} · ${n.t(_.startedAt)}`:`載入案件內容。`,title:_?.title??`簽核案件`,children:[_?(0,s.jsx)(o.Button,{"aria-label":`查看流程圖`,icon:u.ShareIcon,iconType:`icon-only`,onClick:()=>A(!0),title:`查看流程圖`,variant:`base-secondary`,children:`流程圖`}):null,ft?(0,s.jsx)(o.Button,{disabled:D,icon:u.DangerousOutlineIcon,iconType:`leading`,onClick:()=>j(!0),variant:`destructive-secondary`,children:`取消案件`}):null,X?(0,s.jsxs)(s.Fragment,{children:[ut?(0,s.jsx)(o.Button,{disabled:D,icon:u.RefreshCcwIcon,iconType:`leading`,onClick:Ft,variant:`base-secondary`,children:`退回`}):null,(0,s.jsx)(o.Button,{disabled:D,icon:u.UserIcon,iconType:`leading`,onClick:Lt,variant:`base-secondary`,children:`轉派`}),(0,s.jsx)(o.Button,{disabled:D,icon:u.DangerousOutlineIcon,iconType:`leading`,onClick:Nt,variant:`destructive-secondary`,children:`拒絕`}),(0,s.jsx)(o.Button,{disabled:D,icon:u.CheckedIcon,iconType:`leading`,onClick:()=>void Mt({action:`APPROVED`,comment:null}),variant:`base-primary`,children:`同意`})]}):null]})}),(0,s.jsxs)(o.SectionGroup,{children:[(0,s.jsx)(o.Section,{children:(0,s.jsxs)(`div`,{style:b,children:[xe?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:xe}):null,Te?(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,_?.formDefinitionSnapshot.schema&&_.formDefinitionSnapshot.uiSchema?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.t,{errors:Xe,onChange:e=>{et(e),q({})},onUploadAttachment:Q?kt:void 0,readonly:!Q,schema:_.formDefinitionSnapshot.schema,uiSchema:_.formDefinitionSnapshot.uiSchema,value:Q?J:_.formData}),Q?(0,s.jsx)(`div`,{style:oe,children:(0,s.jsx)(o.Button,{disabled:D,icon:u.RefreshCcwIcon,iconType:`leading`,onClick:()=>void Wt(),variant:`base-primary`,children:`重新送出`})}):null]}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`此案件沒有可顯示的表單快照。`})]})}),(0,s.jsx)(o.Section,{children:(0,s.jsxs)(`div`,{style:b,children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`附件`}),Ct.length>0?(0,s.jsx)(o.Table,{actions:Tt,columns:wt,dataSource:Ct,fullWidth:!0}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`此案件沒有附件。`})]})}),(0,s.jsxs)(o.Section,{children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`任務`}),(0,s.jsx)(o.Table,{columns:St,dataSource:mt,fullWidth:!0})]}),(0,s.jsx)(o.Section,{children:(0,s.jsxs)(`div`,{style:b,children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`簽章`}),(0,s.jsx)(o.Typography,{color:x?.valid?`text-success`:`text-error`,variant:`body`,children:x?x.valid?`簽章鏈已驗證,共 ${x.checkedCount} 筆。`:`簽章鏈驗證失敗:${x.errors.join(`、`)}`:`尚無簽章紀錄。`}),Et.length>0?(0,s.jsx)(o.Table,{columns:Dt,dataSource:Et,fullWidth:!0}):null]})}),(0,s.jsx)(o.Section,{children:(0,s.jsxs)(`div`,{style:b,children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`歷程`}),_t.length>0?(0,s.jsx)(o.Stepper,{currentStep:vt,orientation:`vertical`,type:`dot`,children:_t.map(e=>(0,s.jsx)(we,{descriptionParts:e.descriptionParts,error:e.error,forcePending:e.forcePending,title:e.title},e.id))}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`尚無歷程紀錄。`})]})})]}),_?(0,s.jsx)(o.Modal,{modalType:`standard`,onClose:()=>A(!1),open:k,showModalHeader:!0,size:`wide`,supportingText:`${Ue(_.state)} · ${n.t(_.startedAt)}`,title:`流程圖`,children:(0,s.jsxs)(`div`,{style:ce,children:[(0,s.jsx)(`div`,{style:fe,children:(0,s.jsxs)(f.ReactFlow,{edges:bt,fitView:!0,fitViewOptions:{padding:.18},maxZoom:1.2,minZoom:.2,nodes:yt,nodesDraggable:!1,nodesFocusable:!1,nodeTypes:be,panOnDrag:!0,proOptions:{hideAttribution:!0},children:[(0,s.jsx)(f.Background,{}),(0,s.jsx)(f.Controls,{showInteractive:!1})]})}),xt.length>0?(0,s.jsx)(`div`,{style:he,children:xt.map(e=>(0,s.jsx)(`span`,{style:ge,children:e},e))}):null]})}):null,(0,s.jsx)(o.Modal,{modalType:`standard`,onClose:()=>{tt(null),it(null)},open:!!(Y&&rt),showModalHeader:!0,size:`wide`,supportingText:Y?.filename??void 0,title:`PDF 預覽`,children:rt?(0,s.jsx)(ae,{filename:Y?.filename??`PDF 預覽`,fileUrl:rt,onDownload:Y?()=>void At(Y):void 0}):null}),(0,s.jsx)(o.Modal,{cancelText:`保留案件`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`確認取消`,loading:D,modalStatusType:`error`,modalType:`standard`,onCancel:()=>j(!1),onClose:()=>j(!1),onConfirm:()=>void Ut(),open:Ne,showModalFooter:!0,showModalHeader:!0,supportingText:`取消後會關閉目前待簽任務與候選簽核人。`,title:`取消案件`,children:(0,s.jsxs)(`div`,{style:b,children:[(0,s.jsxs)(o.Typography,{variant:`body`,children:[`確定要取消「`,_?.title??``,`」嗎?`]}),(0,s.jsx)(r.t,{label:`取消原因`,name:`cancelComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>Me(e.target.value),placeholder:`可填寫取消原因`,resize:`vertical`,rows:3,value:je})})]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!at,variant:`destructive-primary`},confirmText:`送出拒絕`,loading:D,modalStatusType:`error`,modalType:`standard`,onCancel:Pt,onClose:Pt,onConfirm:()=>void Bt(),open:Fe,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`拒絕案件時必須留下原因,供發起人與後續追蹤查看。`,title:`拒絕原因`,children:(0,s.jsxs)(`div`,{style:le,children:[(0,s.jsx)(r.t,{label:`拒絕原因`,name:`rejectReason`,required:!0,children:(0,s.jsx)(o.Textarea,{autoFocus:!0,onChange:e=>{M(e.target.value),P(null)},placeholder:`請說明拒絕原因`,ref:ye,resize:`vertical`,rows:4,style:ue,type:N?`error`:`default`,value:Pe})}),N?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:N}):null]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!V},confirmText:`送出轉派`,loading:D,modalType:`standard`,onCancel:Rt,onClose:Rt,onConfirm:()=>void Vt(),open:G,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`轉派後,原任務會保留轉派紀錄,新的待簽任務會指派給指定成員。`,title:`轉派簽核`,children:(0,s.jsxs)(`div`,{style:de,children:[(0,s.jsx)(r.t,{label:`轉派對象`,name:`transferToMemberId`,required:!0,children:(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`transfer-member-search`,spellCheck:!1},loading:Je,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>H(Ke(e)),onSearch:zt,onSearchTextChange:e=>H(qe(e,U)),onVisibilityChange:e=>{e&&zt(``)},options:[...U],placeholder:`搜尋姓名或信箱`,searchDebounceTime:300,value:V})}),(0,s.jsx)(r.t,{label:`轉派說明`,name:`transferComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>B(e.target.value),placeholder:`可補充轉派原因`,ref:ye,resize:`vertical`,rows:4,style:ue,value:We})})]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!dt},confirmText:`送出退回`,loading:D,modalType:`standard`,onCancel:It,onClose:It,onConfirm:()=>void Ht(),open:Re,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`退回後,流程會回到指定節點並等待重新處理。`,title:`退回簽核`,children:(0,s.jsxs)(`div`,{style:de,children:[(0,s.jsx)(r.t,{label:`退回節點`,name:`returnTargetNodeId`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>R(e?.id??null),options:[...lt],placeholder:`選擇退回節點`,value:dt})}),(0,s.jsx)(r.t,{label:`退回說明`,name:`returnComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>F(e.target.value),placeholder:`可補充需要修改的內容`,ref:ye,resize:`vertical`,rows:4,style:ue,value:Le})})]})})]})}function w(e){return e instanceof Error?e.message:`發生未知錯誤`}function Se(e){return!Number.isFinite(e)||e<=0?`-`:e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function Ce(e){return e.length>16?`${e.slice(0,12)}...`:e}function T(...e){return e.filter(e=>W(e??null)).join(` `)}var we=(0,a.forwardRef)(function({className:e,descriptionParts:t,error:n,forcePending:r=!1,index:i=0,orientation:c,status:l=`pending`,title:u,type:d=`number`,...f},p){let h=r?`pending`:l;return(0,s.jsxs)(`div`,{...f,className:T(m.stepClasses.host,d===`dot`?m.stepClasses.dot:null,n&&h!==`processing`?m.stepClasses.error:null,c===`horizontal`?m.stepClasses.horizontal:null,d===`number`?m.stepClasses.number:null,h===`pending`?m.stepClasses.pending:null,h===`processing`?m.stepClasses.processing:null,n&&h===`processing`?m.stepClasses.processingError:null,!n&&h===`succeeded`?m.stepClasses.succeeded:null,c===`vertical`?m.stepClasses.vertical:null,e),ref:p,children:[d===`dot`?(0,s.jsx)(`span`,{className:T(m.stepClasses.statusIndicator,m.stepClasses.statusIndicatorDot)}):(0,s.jsx)(`span`,{className:m.stepClasses.statusIndicator,children:i+1}),(0,s.jsxs)(`div`,{className:m.stepClasses.textContainer,children:[(0,s.jsxs)(o.Typography,{className:m.stepClasses.title,variant:`label-primary-highlight`,children:[u,(0,s.jsx)(`span`,{className:m.stepClasses.titleConnectLine})]}),t.length>0?(0,s.jsx)(o.Typography,{className:m.stepClasses.description,variant:`caption`,children:t.map((e,t)=>(0,s.jsxs)(a.Fragment,{children:[t>0?` · `:null,Te(e)]},`${e.type}-${t}`))}):null]})]})});function Te(e){return e.type===`text`?e.text:e.type===`dangerText`?(0,s.jsx)(`span`,{style:ve,children:e.text}):e.email?(0,s.jsxs)(s.Fragment,{children:[e.prefix,`:`,(0,s.jsx)(o.Tooltip,{title:e.email,children:({onMouseEnter:t,onMouseLeave:n,ref:r})=>(0,s.jsx)(`span`,{"data-testid":e.memberId?`member-tooltip-${e.memberId}`:void 0,onMouseEnter:t,onMouseLeave:n,ref:r,style:_e,children:e.label})})]}):`${e.prefix}:${e.label}`}async function Ee({activityLogs:e,tasks:t}){let n=[...new Set([...e.map(e=>e.actorMemberId),...t.map(e=>e.assigneeMemberId),...t.map(e=>e.originalAssigneeMemberId),...t.flatMap(e=>e.candidateMemberIds),...t.flatMap(e=>Je(e.delegationChainJson).flatMap(e=>[e.from,e.to]))].filter(W))];try{return await(0,c.resolveMemberProfiles)(n)}catch{return[]}}async function De(e){return(await Promise.all(e.map(e=>(0,c.listTaskDecisions)(e.id)))).flat()}function Oe(e){return e.reduce((e,t)=>{let n=e.get(t.taskId),r=!n||new Date(t.decidedAt).getTime()>new Date(n.decidedAt).getTime()?t:n;return new Map(e).set(t.taskId,r)},new Map)}function ke(e,t,n,r,i,a,o,s,c){let l=e.filter(je).map(e=>{let t=Ie(e),n=ze(e.nodeId,r);return{descriptionParts:[E(n?`節點:${n}`:`節點:全流程`),O(`操作者`,e.actorMemberId,a,`系統`),E(`時間:${B(e.createdAt)}`),...I(e,t,r,o,s,c,a)].filter(A),error:We(e,t),id:e.id,title:Le(e.eventType,t)}}),u=t.filter(K).map(e=>({descriptionParts:[E(`節點:${L(e.nodeId,r)}`),O(`處理者`,e.assigneeMemberId,a,`未指定`),E(`建立時間:${B(e.createdAt)}`)].filter(A),error:!1,id:`pending-task-${e.id}`,title:e.status===`IN_PROGRESS`?`簽核處理中`:`等待簽核處理`})),d=new Set([...e.filter(je).map(e=>e.nodeId),...t.map(e=>e.nodeId)].filter(W)),f=r?Ne(r,t,n,i,d).map(e=>({descriptionParts:[E(`${J(e.type)} · 尚未抵達`)].filter(A),error:!1,forcePending:!0,id:`future-node-${e.id}`,title:Fe(e)})):[];return[...l,...u,...f]}function E(e){return W(e)?{text:e,type:`text`}:null}function D(e){return W(e)?{text:e,type:`dangerText`}:null}function O(e,t,n,r){let i=t?n.get(t):null;return{email:i?.email??null,label:i?.name??r,memberId:t,prefix:e,type:`member`}}function k(e,t){if(!e)return`-`;let n=t.get(e);return n?`${n.name}(${n.email})`:e}function A(e){return!!e}function Ae(e){let t=e.findIndex(e=>e.id.startsWith(`pending-task-`)||e.id.startsWith(`future-node-`));return t===-1?e.length:t}function je(e){return e.eventType===`INSTANCE_STARTED`||e.eventType===`TASK_DECIDED`||e.eventType===`SLA_TRIGGERED`}function Me(e,t,n,r,i){if(e.type===`startEvent`||i.has(e.id))return!1;if(r===`REJECTED`)return!0;let a=q(e,t,n,r);return a.tone===`neutral`||a.tone===`waiting`}function Ne(e,t,n,r,i){if(r!==`RUNNING`&&r!==`REJECTED`)return[];let a=e.nodes.filter(e=>Me(e,t,n,r,i)),o=j(e,a,t,n,i),s=new Map(e.nodes.map((e,t)=>[e.id,t]));return a.filter(e=>o.has(e.id)).sort((e,t)=>{let n=o.get(e.id)??0,r=o.get(t.id)??0;return n===r?e.position.x===t.position.x?e.position.y===t.position.y?(s.get(e.id)??0)-(s.get(t.id)??0):e.position.y-t.position.y:e.position.x-t.position.x:n-r})}function j(e,t,n,r,i){let a=new Set(t.map(e=>e.id)),o=e.edges.reduce((e,t)=>{let n=[...e.get(t.source)??[],t.target];return new Map(e).set(t.source,n)},new Map);return Pe(e,n,r,i).reduce((e,t)=>P(e,M(t,o,a)),new Map)}function Pe(e,t,n,r){let i=n.filter(e=>e.status===`ACTIVE`||e.status===`WAITING`).map(e=>e.currentNodeId),a=t.filter(K).map(e=>e.nodeId),o=e.nodes.filter(e=>r.has(e.id)).map(e=>e.id),s=[...new Set([...i,...a,...o])],c=e.nodes.filter(e=>e.type===`startEvent`).map(e=>e.id);return s.length>0?s:c}function M(e,t,n){return N([{distance:0,nodeId:e}],t,n)}function N(e,t,n,r=new Set,i=new Map){let[a,...o]=e;if(!a)return i;if(r.has(a.nodeId))return N(o,t,n,r,i);let s=new Set(r).add(a.nodeId),c=n.has(a.nodeId)?new Map(i).set(a.nodeId,Math.min(i.get(a.nodeId)??a.distance,a.distance)):i;return N([...o,...(t.get(a.nodeId)??[]).map(e=>({distance:a.distance+1,nodeId:e}))],t,n,s,c)}function P(e,t){return[...t.entries()].reduce((e,[t,n])=>new Map(e).set(t,Math.min(e.get(t)??n,n)),e)}function Fe(e){return e.type===`userTask`?`未來簽核:${e.data.label}`:e.type===`serviceTask`?`未來知會:${e.data.label}`:e.type===`exclusiveGateway`?`未來分流:${e.data.label}`:e.type===`parallelGateway`?`未來匯合:${e.data.label}`:e.type===`endEvent`?`流程完成:${e.data.label}`:`未來節點:${e.data.label}`}function Ie(e){try{let t=JSON.parse(e.payloadJson);return G(t)?t:{}}catch{return{}}}function Le(e,t){return e===`INSTANCE_STARTED`?`案件已發起`:e===`TOKEN_CREATED`?`流程路徑已建立`:e===`ENGINE_PROCESS_REQUESTED`?`流程引擎已處理`:e===`TOKEN_ADVANCED`?`流程已前進`:e===`TASK_CREATED`?`待簽任務已建立`:e===`TASK_DECIDED`?F(V(t,`action`)):e===`SLA_TRIGGERED`?`時限提醒已觸發`:e}function F(e){return e===`APPROVED`?`已同意`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`TRANSFERRED`?`已轉派`:`簽核已決議`}function Re(e,t,n,r){if(e.eventType===`TASK_CREATED`){let e=V(t,`assigneeMemberId`),n=V(t,`originalAssigneeMemberId`);if(!e){let e=H(t,`candidateMemberIds`);return e.length?`候選簽核人:${e.map(e=>k(e,r)).join(`、`)}`:null}let i=k(e,r),a=k(n,r);return n&&n!==e?`待簽人:${i}(原簽核人:${a})`:`待簽人:${i}`}if(e.eventType===`TASK_DECIDED`){let e=V(t,`action`),n=V(t,`comment`),i=e?`決議:${R(e)}`:null,a=V(t,`transferToMemberId`);return e===`REJECTED`&&n?[i,`拒絕原因:${n}`].filter(W).join(` · `):e===`TRANSFERRED`?[i,`轉派給:${k(a,r)}`].filter(W).join(` · `):i}if(e.eventType===`TOKEN_ADVANCED`){let e=V(t,`action`);if(e)return`流程結果:${R(e)}`;let r=U(t,`arrivedCount`),i=U(t,`requiredCount`);if(r!==null&&i!==null)return`等待匯合:${r}/${i}`;let a=V(t,`fromNodeId`),o=V(t,`toNodeId`);if(a&&o)return`由 ${L(a,n)} 前進至 ${L(o,n)}`}if(e.eventType===`ENGINE_PROCESS_REQUESTED`){let e=V(t,`state`);return e?`案件狀態:${Ue(e)}`:null}return null}function I(e,t,n,r,i,a,o){if(e.eventType!==`TASK_DECIDED`)return[E(Re(e,t,n,o))].filter(A);let s=e.taskId?r.get(e.taskId):null,c=V(t,`action`)??s?.action??null,l=V(t,`comment`)??s?.comment??null,u=V(t,`transferToMemberId`)??s?.transferToMemberId??null,d=V(t,`signatureId`)??s?.signatureId??null,f=d?i.get(d):null;return[E(c?`決議:${R(c)}`:null),c===`REJECTED`?D(`拒絕原因:${l??`-`}`):null,c===`RETURNED`?E(`退回說明:${l??`-`}`):null,c===`TRANSFERRED`?E(`轉派給:${k(u,o)}`):null,c===`TRANSFERRED`?E(`轉派說明:${l??`-`}`):null,f?E(a?.valid?`簽章:已驗證(${Ce(f.signedPayloadHash)})`:`簽章:待檢查(${Ce(f.signedPayloadHash)})`):null].filter(A)}function ze(e,t){return e?L(e,t):null}function L(e,t){return t?.nodes.find(t=>t.id===e)?.data.label??e}function Be(e,t){if(t.type!==`userTask`||!t.data.returnBehavior.allowReturn)return[];if(t.data.returnBehavior.allowedTargets===`ANY`)return e.nodes.filter(e=>e.id!==t.id).map(e=>({id:e.id,name:`${e.data.label}(${J(e.type)})`}));let n=t.data.returnBehavior.allowedTargets===`INITIATOR`?e.nodes.find(e=>e.type===`startEvent`)?.id:e.edges.find(e=>e.target===t.id)?.source,r=e.nodes.find(e=>e.id===n);return r?[{id:r.id,name:`${r.data.label}(${J(r.type)})`}]:[]}function R(e){return e===`APPROVED`?`同意`:e===`REJECTED`?`拒絕`:e===`RETURNED`?`退回`:e===`TRANSFERRED`?`轉派`:e}function Ve(e){return e===`PENDING`?`待處理`:e===`IN_PROGRESS`?`處理中`:e===`COMPLETED`?`已完成`:e===`CANCELLED`?`已取消`:e===`TRANSFERRED`?`已轉派`:e}function z(e,t=new Map){let n=Je(e.delegationChainJson);if(!e.assigneeMemberId)return e.candidateMemberIds.length?`候選 ${e.candidateMemberIds.map(e=>k(e,t)).join(`、`)}`:`未指定`;let r=k(e.assigneeMemberId,t),i=k(e.originalAssigneeMemberId,t);return n.length===0||e.originalAssigneeMemberId===e.assigneeMemberId?r:`${r}(原:${i})`}function He(e,t){return t?e.assigneeMemberId===t||e.candidateMemberIds.includes(t):!1}function Ue(e){return e===`APPROVED`?`已同意`:e===`CANCELLED`?`已取消`:e===`DRAFT`?`草稿`:e===`EXPIRED`?`已逾期`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`RUNNING`?`進行中`:e}function We(e,t){return e.eventType===`SLA_TRIGGERED`||V(t,`action`)===`REJECTED`||V(t,`instanceState`)===`REJECTED`}function B(e){return n.t(e)}function V(e,t){let n=e[t];return typeof n==`string`?n:null}function H(e,t){let n=e[t];return Array.isArray(n)?n.filter(e=>typeof e==`string`):[]}function Ge(e){return{email:e.email,id:e.memberId,name:`${e.name} · ${e.email}`}}function Ke(e){if(!G(e))return null;let t=e.email,n=e.id,r=e.name;return typeof n==`string`&&typeof r==`string`?{email:typeof t==`string`?t:null,id:n,name:r}:null}function qe(e,t){let n=e.trim().toLocaleLowerCase();if(!n)return null;let r=t.filter(e=>[e.id,e.name,e.email??``].some(e=>e.toLocaleLowerCase().includes(n)));return r.length===1?r[0]??null:null}function Je(e){try{let t=JSON.parse(e);return Array.isArray(t)?t.map(e=>G(e)?Ye(e):null).filter(e=>e!==null):[]}catch{return[]}}function Ye(e){let t=V(e,`from`),n=V(e,`to`),r=V(e,`reason`);return!t||!n||!r?null:{from:t,reason:r,ruleId:V(e,`ruleId`),to:n}}function U(e,t){let n=e[t];return typeof n==`number`?n:null}function W(e){return typeof e==`string`&&e.trim().length>0}function G(e){return typeof e==`object`&&!!e}function K(e){return e.status===`PENDING`||e.status===`IN_PROGRESS`}function Xe({data:e}){return(0,s.jsxs)(`div`,{style:et(e.tone),children:[(0,s.jsx)(f.Handle,{isConnectable:!1,position:f.Position.Left,style:me,type:`target`}),(0,s.jsx)(o.Typography,{component:`span`,ellipsis:!0,title:e.label,variant:`label-primary`,children:e.label}),(0,s.jsx)(`span`,{style:Y(e.tone),children:e.statusLabel}),(0,s.jsx)(`span`,{title:e.secondaryLabel,style:C,children:e.secondaryLabel||e.kindLabel}),(0,s.jsx)(f.Handle,{isConnectable:!1,position:f.Position.Right,style:me,type:`source`})]})}function Ze(e,t,n,r){return e.nodes.map(e=>{let i=q(e,t,n,r);return{data:{kindLabel:J(e.type),label:e.data.label,secondaryLabel:i.secondaryLabel,statusLabel:i.statusLabel,tone:i.tone},id:e.id,position:e.position,sourcePosition:f.Position.Right,targetPosition:f.Position.Left,type:`workflowRuntime`}})}function Qe(e){let t=new p.graphlib.Graph;return t.setDefaultEdgeLabel(()=>({})),t.setGraph({nodesep:56,rankdir:`LR`,ranksep:120}),e.nodes.forEach(e=>{t.setNode(e.id,{height:se,width:x})}),e.edges.forEach(e=>{t.setEdge(e.source,e.target)}),p.layout(t),{...e,nodes:e.nodes.map(e=>{let n=t.node(e.id);return n?{...e,position:{x:n.x-x/2,y:n.y-se/2}}:e})}}function $e(e){return e.edges.map(e=>{let t=tt(e);return{animated:!1,id:e.id,label:t,labelBgBorderRadius:6,labelBgPadding:[8,4],labelBgStyle:{fill:e.data.isDefault?`#f8fafc`:`#eff6ff`,stroke:e.data.isDefault?`#64748b`:`#2563eb`,strokeWidth:1},labelShowBg:!!t,labelStyle:{fill:e.data.isDefault?`#475569`:`#2563eb`,fontSize:12,fontWeight:600},source:e.source,style:{stroke:`#475569`,strokeWidth:1.5},target:e.target,type:e.type??`smoothstep`}})}function q(e,t,n,r){let i=t.filter(t=>t.nodeId===e.id),a=i.find(e=>e.status===`PENDING`||e.status===`IN_PROGRESS`),o=i.find(e=>e.status===`CANCELLED`),s=i.find(e=>e.status===`COMPLETED`),c=n.filter(t=>t.currentNodeId===e.id),l=c.find(e=>e.status===`ACTIVE`),u=c.find(e=>e.status===`WAITING`);return a?{secondaryLabel:`處理者 ${z(a)}`,statusLabel:`待處理`,tone:`current`}:o?{secondaryLabel:`已取消 ${z(o)}`,statusLabel:`已取消`,tone:`cancelled`}:s?{secondaryLabel:`已完成 ${z(s)}`,statusLabel:`已完成`,tone:`completed`}:l?{secondaryLabel:`token ${l.id}`,statusLabel:`執行中`,tone:`current`}:u?{secondaryLabel:`token ${u.id}`,statusLabel:`等待前置`,tone:`waiting`}:e.type===`startEvent`?{secondaryLabel:`流程已發起`,statusLabel:`已發起`,tone:`completed`}:e.type===`endEvent`&&r!==`RUNNING`?{secondaryLabel:r,statusLabel:r===`REJECTED`?`已拒絕`:`已完成`,tone:r===`REJECTED`?`cancelled`:`completed`}:{secondaryLabel:J(e.type),statusLabel:`未抵達`,tone:`neutral`}}function J(e){return e===`startEvent`?`開始`:e===`endEvent`?`完成`:e===`userTask`?`簽核節點`:e===`serviceTask`?`知會節點`:e===`exclusiveGateway`?`條件分流`:`平行處理`}function et(e){return e===`current`?{...S,border:`1px solid var(--mzn-color-primary, #0057ff)`,boxShadow:`0 0 0 3px rgba(0, 87, 255, 0.14)`}:e===`completed`?{...S,border:`1px solid #16a34a`}:e===`cancelled`?{...S,border:`1px solid #dc2626`,opacity:.72}:e===`waiting`?{...S,border:`1px dashed #64748b`}:S}function Y(e){let t=pe;return e===`current`?{...t,background:`#eff6ff`,color:`#2563eb`}:e===`completed`?{...t,background:`#f0fdf4`,color:`#15803d`}:e===`cancelled`?{...t,background:`#fef2f2`,color:`#dc2626`}:e===`waiting`?{...t,background:`#f8fafc`,color:`#475569`}:{...t,background:`#f1f5f9`,color:`#64748b`}}function tt(e){return e.data.label?e.data.label:e.data.isDefault?`其他情況`:e.data.condition??``}function nt(e){return e.edges.map(tt).filter(e=>e.trim().length>0)}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return xe}});
2
+ //# sourceMappingURL=detail-B9JkYNHc.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detail-B9JkYNHc.cjs","names":[],"sources":["../../src/components/pdf-preview.module.scss","../../src/components/pdf-preview.tsx","../../src/views/instances/detail/InstanceDetailView.tsx"],"sourcesContent":[".root {\n display: grid;\n gap: 12px;\n width: min(86vw, 1080px);\n}\n\n.toolbar {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: space-between;\n}\n\n.pageControls,\n.zoomControls {\n align-items: center;\n display: flex;\n gap: 8px;\n}\n\n.counter {\n min-width: 92px;\n text-align: center;\n white-space: nowrap;\n}\n\n.viewport {\n align-items: flex-start;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n display: flex;\n height: min(72vh, 760px);\n justify-content: center;\n min-height: 420px;\n overflow: auto;\n padding: 16px;\n}\n\n.page {\n background: #ffffff;\n box-shadow: 0 12px 32px rgb(15 23 42 / 14%);\n color: #111827;\n}\n\n.state {\n align-items: center;\n display: flex;\n justify-content: center;\n min-height: 320px;\n width: 100%;\n}\n\n@media (max-width: 720px) {\n .root {\n width: 92vw;\n }\n\n .toolbar {\n align-items: stretch;\n display: grid;\n }\n\n .pageControls,\n .zoomControls {\n justify-content: space-between;\n }\n\n .counter {\n min-width: 84px;\n }\n\n .viewport {\n height: 68vh;\n min-height: 360px;\n padding: 12px;\n }\n}\n","'use client';\n\nimport {\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Button, Typography } from '@mezzanine-ui/react';\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n DownloadIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@mezzanine-ui/icons';\nimport { Document, Page, pdfjs } from 'react-pdf';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport styles from './pdf-preview.module.scss';\n\n// pdfjs ships its worker as a separate chunk. Consumers should call\n// `configurePdfWorker(url)` (or set `pdfjs.GlobalWorkerOptions.workerSrc`\n// directly) before the first `<PDFPreview>` mounts. The library does not\n// hard-bundle a worker path because consumer bundlers may need to resolve\n// it through CDN, public/ asset pipeline, or pinned version.\nexport function configurePdfWorker(workerSrc: string): void {\n pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;\n}\n\nconst DEFAULT_VIEWPORT_WIDTH = 760;\nconst MAX_PAGE_WIDTH = 920;\nconst MIN_PAGE_WIDTH = 320;\nconst PAGE_HORIZONTAL_PADDING = 32;\nconst MIN_SCALE = 0.75;\nconst MAX_SCALE = 1.75;\nconst SCALE_STEP = 0.25;\n\nexport interface PDFPreviewProps {\n readonly filename: string;\n readonly fileUrl: string;\n readonly onDownload?: () => void;\n}\n\n/**\n * Mezzanine-styled PDF preview powered by `react-pdf`. Used by the instance\n * detail view to preview PDF attachments inline.\n */\nexport function PDFPreview({\n filename,\n fileUrl,\n onDownload,\n}: PDFPreviewProps): ReactElement {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const [numPages, setNumPages] = useState<number | null>(null);\n const [pageNumber, setPageNumber] = useState(1);\n const [scale, setScale] = useState(1);\n const [viewportWidth, setViewportWidth] = useState(DEFAULT_VIEWPORT_WIDTH);\n\n useEffect((): (() => void) | undefined => {\n const viewport = viewportRef.current;\n\n if (!viewport || typeof ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const observer = new ResizeObserver((entries): void => {\n const nextWidth = entries[0]?.contentRect.width;\n\n if (nextWidth) {\n setViewportWidth(nextWidth);\n }\n });\n\n observer.observe(viewport);\n\n return (): void => observer.disconnect();\n }, []);\n\n useEffect((): void => {\n setNumPages(null);\n setPageNumber(1);\n setScale(1);\n }, [fileUrl]);\n\n const pageWidth = useMemo((): number => {\n const availableWidth = Math.max(\n MIN_PAGE_WIDTH,\n viewportWidth - PAGE_HORIZONTAL_PADDING,\n );\n const baseWidth = Math.min(MAX_PAGE_WIDTH, availableWidth);\n\n return Math.round(baseWidth * scale);\n }, [scale, viewportWidth]);\n\n const loadDocument = useCallback((document: PDFDocumentProxy): void => {\n setNumPages(document.numPages);\n setPageNumber(1);\n }, []);\n\n const hasPreviousPage = pageNumber > 1;\n const hasNextPage = numPages !== null && pageNumber < numPages;\n const canZoomOut = scale > MIN_SCALE;\n const canZoomIn = scale < MAX_SCALE;\n const pageLabel =\n numPages === null\n ? `第 ${pageNumber} 頁`\n : `第 ${pageNumber} / ${numPages} 頁`;\n const zoomLabel = `${Math.round(scale * 100)}%`;\n\n return (\n <section aria-label={`${filename} PDF 預覽`} className={styles.root}>\n <div className={styles.toolbar}>\n <div className={styles.pageControls} aria-label=\"頁面切換\">\n <Button\n aria-label=\"上一頁\"\n disabled={!hasPreviousPage}\n icon={ChevronLeftIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n Math.max(1, currentPageNumber - 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {pageLabel}\n </Typography>\n <Button\n aria-label=\"下一頁\"\n disabled={!hasNextPage}\n icon={ChevronRightIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n numPages === null\n ? currentPageNumber\n : Math.min(numPages, currentPageNumber + 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n <div className={styles.zoomControls} aria-label=\"縮放\">\n <Button\n aria-label=\"縮小\"\n disabled={!canZoomOut}\n icon={ZoomOutIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.max(MIN_SCALE, currentScale - SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {zoomLabel}\n </Typography>\n <Button\n aria-label=\"放大\"\n disabled={!canZoomIn}\n icon={ZoomInIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.min(MAX_SCALE, currentScale + SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n {onDownload ? (\n <Button\n icon={DownloadIcon}\n iconType=\"leading\"\n onClick={onDownload}\n size=\"minor\"\n variant=\"base-primary\"\n >\n 下載\n </Button>\n ) : null}\n </div>\n <div className={styles.viewport} ref={viewportRef}>\n <Document\n error={<PDFPreviewState message=\"PDF 無法載入。\" />}\n file={fileUrl}\n loading={<PDFPreviewState message=\"正在載入 PDF...\" />}\n noData={<PDFPreviewState message=\"沒有可預覽的 PDF。\" />}\n onLoadSuccess={loadDocument}\n >\n <Page\n className={styles.page}\n loading={<PDFPreviewState message=\"正在載入頁面...\" />}\n pageNumber={pageNumber}\n renderAnnotationLayer\n renderTextLayer\n width={pageWidth}\n />\n </Document>\n </div>\n </section>\n );\n}\n\nfunction PDFPreviewState({\n message,\n}: {\n readonly message: string;\n}): ReactElement {\n return (\n <div className={styles.state}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {message}\n </Typography>\n </div>\n );\n}\n","'use client';\n\nimport {\n ChangeEvent,\n CSSProperties,\n Fragment,\n RefCallback,\n ReactElement,\n forwardRef,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Background,\n Controls,\n Handle,\n Position,\n ReactFlow,\n type Edge as FlowEdge,\n type Node as FlowNode,\n type NodeProps,\n} from '@xyflow/react';\nimport * as dagre from 'dagre';\nimport {\n AutoComplete,\n Button,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Stepper,\n Table,\n Textarea,\n Tooltip,\n Typography,\n type StepProps,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { stepClasses } from '@mezzanine-ui/core/stepper';\nimport {\n CheckedIcon,\n DangerousOutlineIcon,\n DownloadIcon,\n FileSearchIcon,\n RefreshCcwIcon,\n ShareIcon,\n UserIcon,\n} from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport {\n focusFormRendererField,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n ActivityLogRecord,\n AttachmentRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n cancelApprovalInstance,\n decideTask,\n listAttachments,\n listTaskDecisions,\n readApprovalInstance,\n readAttachmentDownloadUrl,\n readAttachmentPreviewUrl,\n readInstanceSignatures,\n resubmitApprovalInstance,\n resolveMemberProfiles,\n searchMembers,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowFormData,\n WorkflowTokenRecord,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport { PDFPreview } from '../../../components/pdf-preview';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst BUTTON_ROW_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nconst FLOW_NODE_LAYOUT_WIDTH = 184;\nconst FLOW_NODE_LAYOUT_HEIGHT = 96;\n\nconst FLOW_MODAL_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst REJECT_REASON_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst REJECT_REASON_TEXTAREA_STYLE: CSSProperties = {\n minWidth: '100%',\n width: '100%',\n};\n\nconst MODAL_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst FLOW_CANVAS_STYLE: CSSProperties = {\n background: '#f8fafc',\n border: '1px solid #e2e8f0',\n borderRadius: 8,\n height: 'min(64vh, 620px)',\n minHeight: 440,\n overflow: 'hidden',\n width: 'min(80vw, 1040px)',\n};\n\nconst NODE_STYLE: CSSProperties = {\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n boxShadow: '0 8px 18px rgba(15, 23, 42, 0.08)',\n display: 'grid',\n gap: 6,\n minHeight: 82,\n padding: 12,\n width: 184,\n};\n\nconst NODE_STATUS_STYLE: CSSProperties = {\n borderRadius: 999,\n fontSize: 12,\n fontWeight: 600,\n justifySelf: 'start',\n lineHeight: '18px',\n padding: '0 8px',\n};\n\nconst NODE_SECONDARY_STYLE: CSSProperties = {\n color: '#64748b',\n fontSize: 12,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nconst NODE_HANDLE_STYLE: CSSProperties = {\n opacity: 0,\n};\n\nconst EDGE_SUMMARY_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nconst EDGE_SUMMARY_ITEM_STYLE: CSSProperties = {\n alignItems: 'center',\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n color: '#334155',\n display: 'inline-flex',\n fontSize: 12,\n fontWeight: 600,\n gap: 6,\n lineHeight: '20px',\n padding: '4px 8px',\n};\n\nconst HISTORY_MEMBER_NAME_STYLE: CSSProperties = {\n cursor: 'help',\n textDecoration: 'underline dotted',\n textUnderlineOffset: 3,\n};\n\nconst HISTORY_DANGER_TEXT_STYLE: CSSProperties = {\n color: 'var(--mzn-color-text-error)',\n};\n\nfunction applyFullWidthTextareaHost(element: HTMLDivElement | null): void {\n if (!element) {\n return;\n }\n\n element.style.width = '100%';\n}\n\nconst READONLY_FLOW_NODE_TYPES = {\n workflowRuntime: WorkflowRuntimeNodeCard,\n};\n\ntype RuntimeTone =\n | 'cancelled'\n | 'completed'\n | 'current'\n | 'neutral'\n | 'waiting';\n\ninterface RuntimeNodeData extends Record<string, unknown> {\n readonly kindLabel: string;\n readonly label: string;\n readonly secondaryLabel: string;\n readonly statusLabel: string;\n readonly tone: RuntimeTone;\n}\n\ntype RuntimeFlowNode = FlowNode<RuntimeNodeData, 'workflowRuntime'>;\ntype RuntimeFlowEdge = FlowEdge<\n Readonly<Record<string, unknown>>,\n 'smoothstep'\n>;\n\ntype TaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n assigneeLabel: string;\n key: string;\n nodeLabel: string;\n statusLabel: string;\n }\n>;\n\ntype AttachmentRow = Readonly<\n Record<string, unknown> & {\n attachment: AttachmentRecord;\n createdAt: string;\n filename: string;\n id: string;\n key: string;\n mimeType: string;\n sizeLabel: string;\n }\n>;\n\ntype SignatureRow = Readonly<\n Record<string, unknown> & {\n algorithm: string;\n hashLabel: string;\n key: string;\n keyVersion: number;\n signedAtLabel: string;\n signerMemberId: string;\n }\n>;\n\ntype MemberOption = Readonly<{\n email: string | null;\n id: string;\n name: string;\n}>;\n\ninterface ActivityStepRecord {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly error: boolean;\n readonly forcePending?: boolean;\n readonly id: string;\n readonly title: string;\n}\n\ntype ActivityStepDescriptionPart =\n | Readonly<{ text: string; type: 'text' }>\n | Readonly<{ text: string; type: 'dangerText' }>\n | Readonly<{\n email: string | null;\n label: string;\n memberId: string | null;\n prefix: string;\n type: 'member';\n }>;\n\nexport interface InstanceDetailViewProps {\n /** Approval instance id (Next.js `params.id` resolved by the page shim). */\n readonly instanceId: string;\n}\n\n/**\n * Framework-agnostic view for the BPM approval instance detail page.\n * Mechanical port of `apps/client/src/app/instances/[id]/page.tsx`. The\n * `instanceId` is provided by the host page wrapper (typically resolved\n * from `params.id` in the Next.js Server Component shim).\n */\nexport function InstanceDetailView({\n instanceId,\n}: InstanceDetailViewProps): ReactElement {\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activityLogs, setActivityLogs] = useState<\n readonly ActivityLogRecord[]\n >([]);\n const [instance, setInstance] = useState<ApprovalInstanceRecord | null>(null);\n const [taskDecisions, setTaskDecisions] = useState<\n readonly TaskDecisionRecord[]\n >([]);\n const [attachments, setAttachments] = useState<readonly AttachmentRecord[]>(\n [],\n );\n const [signatures, setSignatures] = useState<readonly SignatureRecord[]>([]);\n const [signatureVerification, setSignatureVerification] =\n useState<SignatureVerificationRecord | null>(null);\n const [tasks, setTasks] = useState<readonly TaskRecord[]>([]);\n const [workflowTokens, setWorkflowTokens] = useState<\n readonly WorkflowTokenRecord[]\n >([]);\n const [memberProfiles, setMemberProfiles] = useState<\n readonly MemberProfileRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [deciding, setDeciding] = useState(false);\n const [workflowModalOpen, setWorkflowModalOpen] = useState(false);\n const [cancelComment, setCancelComment] = useState('');\n const [cancelModalOpen, setCancelModalOpen] = useState(false);\n const [rejectReason, setRejectReason] = useState('');\n const [rejectReasonError, setRejectReasonError] = useState<string | null>(\n null,\n );\n const [rejectReasonModalOpen, setRejectReasonModalOpen] = useState(false);\n const [returnComment, setReturnComment] = useState('');\n const [returnModalOpen, setReturnModalOpen] = useState(false);\n const [returnTargetNodeId, setReturnTargetNodeId] = useState<string | null>(\n null,\n );\n const [transferComment, setTransferComment] = useState('');\n const [transferMember, setTransferMember] = useState<MemberOption | null>(\n null,\n );\n const [transferMemberLoading, setTransferMemberLoading] = useState(false);\n const [transferMemberOptions, setTransferMemberOptions] = useState<\n readonly MemberOption[]\n >([]);\n const [transferModalOpen, setTransferModalOpen] = useState(false);\n const [resubmitFormErrors, setResubmitFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [resubmitFormData, setResubmitFormData] = useState<WorkflowFormData>(\n {},\n );\n const [previewAttachment, setPreviewAttachment] =\n useState<AttachmentRecord | null>(null);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const trimmedRejectReason = rejectReason.trim();\n const trimmedCancelComment = cancelComment.trim();\n const trimmedReturnComment = returnComment.trim();\n const trimmedTransferComment = transferComment.trim();\n\n useEffect((): void => {\n void refreshInstance();\n }, [currentMemberId, instanceId]);\n\n useEffect((): void => {\n setResubmitFormData(instance?.formData ?? {});\n }, [instance]);\n\n const currentTask = useMemo(\n (): TaskRecord | null =>\n tasks.find(\n (task) =>\n canMemberActOnTask(task, currentMemberId) &&\n (task.status === 'PENDING' || task.status === 'IN_PROGRESS'),\n ) ?? null,\n [currentMemberId, tasks],\n );\n const currentTaskNode = useMemo(\n (): WorkflowNode | null =>\n currentTask && instance\n ? (instance.workflowSnapshot.nodes.find(\n (node) => node.id === currentTask.nodeId,\n ) ?? null)\n : null,\n [currentTask, instance],\n );\n const returnTargetOptions = useMemo(\n (): readonly { readonly id: string; readonly name: string }[] =>\n currentTaskNode && instance\n ? readReturnTargetOptions(instance.workflowSnapshot, currentTaskNode)\n : [],\n [currentTaskNode, instance],\n );\n const canReturnCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.allowReturn;\n const selectedReturnTargetOption =\n returnTargetOptions.find((option) => option.id === returnTargetNodeId) ??\n returnTargetOptions[0] ??\n null;\n const canCancelInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n (instance.state === 'RUNNING' || instance.state === 'RETURNED'),\n );\n const canResubmitInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n instance.state === 'RETURNED',\n );\n const memberProfilesById = useMemo(\n (): ReadonlyMap<string, MemberProfileRecord> =>\n new Map(memberProfiles.map((profile) => [profile.memberId, profile])),\n [memberProfiles],\n );\n const taskRows = useMemo(\n (): TaskRow[] =>\n tasks.map((task) => ({\n ...task,\n assigneeLabel: readTaskAssigneeLabel(task, memberProfilesById),\n key: task.id,\n nodeLabel: readNodeDisplayLabel(\n task.nodeId,\n instance?.workflowSnapshot ?? null,\n ),\n statusLabel: readTaskStatusLabel(task.status),\n })),\n [instance, memberProfilesById, tasks],\n );\n const taskDecisionsByTaskId = useMemo(\n (): ReadonlyMap<string, TaskDecisionRecord> =>\n readLatestTaskDecisionsByTaskId(taskDecisions),\n [taskDecisions],\n );\n const signaturesById = useMemo(\n (): ReadonlyMap<string, SignatureRecord> =>\n new Map(signatures.map((signature) => [signature.id, signature])),\n [signatures],\n );\n const activitySteps = useMemo(\n (): ActivityStepRecord[] =>\n readActivityStepRecords(\n activityLogs,\n tasks,\n workflowTokens,\n instance?.workflowSnapshot ?? null,\n instance?.state ?? 'RUNNING',\n memberProfilesById,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n ),\n [\n activityLogs,\n instance,\n memberProfilesById,\n signatureVerification,\n signaturesById,\n taskDecisionsByTaskId,\n tasks,\n workflowTokens,\n ],\n );\n const currentActivityStep = useMemo(\n (): number => readCurrentActivityStep(activitySteps),\n [activitySteps],\n );\n const layoutedWorkflowSnapshot = useMemo(\n (): WorkflowDefinition | null =>\n instance\n ? layoutRuntimeWorkflowDefinition(instance.workflowSnapshot)\n : null,\n [instance],\n );\n const flowNodes = useMemo(\n (): RuntimeFlowNode[] =>\n instance && layoutedWorkflowSnapshot\n ? readRuntimeFlowNodes(\n layoutedWorkflowSnapshot,\n tasks,\n workflowTokens,\n instance.state,\n )\n : [],\n [instance, layoutedWorkflowSnapshot, tasks, workflowTokens],\n );\n const flowEdges = useMemo(\n (): RuntimeFlowEdge[] =>\n layoutedWorkflowSnapshot\n ? readRuntimeFlowEdges(layoutedWorkflowSnapshot)\n : [],\n [layoutedWorkflowSnapshot],\n );\n const edgeSummaries = useMemo(\n (): readonly string[] =>\n instance ? readEdgeSummaries(instance.workflowSnapshot) : [],\n [instance],\n );\n const taskColumns = useMemo(\n (): TableColumn<TaskRow>[] => [\n { dataIndex: 'nodeLabel', key: 'nodeLabel', title: '節點', width: 180 },\n {\n key: 'assigneeMemberId',\n title: '處理者',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.assigneeLabel}\n </Typography>\n ),\n width: 180,\n },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'createdAt',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n const attachmentRows = useMemo(\n (): AttachmentRow[] =>\n attachments.map((attachment) => ({\n attachment,\n createdAt: attachment.createdAt,\n filename: attachment.filename,\n id: attachment.id,\n key: attachment.id,\n mimeType: attachment.mimeType,\n sizeLabel: formatFileSize(Number(attachment.sizeBytes)),\n })),\n [attachments],\n );\n const attachmentColumns = useMemo(\n (): TableColumn<AttachmentRow>[] => [\n { dataIndex: 'filename', key: 'filename', title: '檔名', width: 260 },\n { dataIndex: 'mimeType', key: 'mimeType', title: '類型', width: 180 },\n { dataIndex: 'sizeLabel', key: 'sizeLabel', title: '大小', width: 120 },\n {\n key: 'createdAt',\n render: (record: AttachmentRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '上傳時間',\n width: 220,\n },\n ],\n [],\n );\n const attachmentActions = useMemo(\n (): TableActions<AttachmentRow> => ({\n render: (record): ReturnType<TableActions<AttachmentRow>['render']> => [\n ...(record.mimeType === 'application/pdf'\n ? [\n {\n icon: FileSearchIcon,\n iconType: 'leading' as const,\n name: '預覽',\n onClick: (): void => {\n void handlePreviewAttachment(record.attachment);\n },\n },\n ]\n : []),\n {\n icon: DownloadIcon,\n iconType: 'leading',\n name: '下載',\n onClick: (): void => {\n void handleDownloadAttachment(record.attachment);\n },\n },\n ],\n variant: 'base-secondary',\n width: 160,\n }),\n [],\n );\n const signatureRows = useMemo(\n (): SignatureRow[] =>\n signatures.map((signature) => ({\n algorithm: signature.algorithm,\n hashLabel: readShortHash(signature.signedPayloadHash),\n key: signature.id,\n keyVersion: signature.keyVersion,\n signedAtLabel: formatDateTime(signature.signedAt),\n signerMemberId: signature.signerMemberId,\n })),\n [signatures],\n );\n const signatureColumns = useMemo(\n (): TableColumn<SignatureRow>[] => [\n {\n dataIndex: 'signerMemberId',\n key: 'signerMemberId',\n title: '簽章者',\n width: 160,\n },\n { dataIndex: 'algorithm', key: 'algorithm', title: '演算法', width: 150 },\n {\n dataIndex: 'keyVersion',\n key: 'keyVersion',\n title: 'Key 版本',\n width: 100,\n },\n {\n dataIndex: 'hashLabel',\n key: 'hashLabel',\n title: 'Payload Hash',\n width: 180,\n },\n {\n dataIndex: 'signedAtLabel',\n key: 'signedAtLabel',\n title: '簽章時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function refreshInstance(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n const nextRecord = await readApprovalInstance(instanceId);\n setActivityLogs(nextRecord.activityLogs);\n setInstance(nextRecord.instance);\n setTasks(nextRecord.tasks);\n setWorkflowTokens(nextRecord.workflowTokens);\n const [\n nextTaskDecisions,\n nextMemberProfiles,\n nextAttachments,\n nextSignatures,\n ] = await Promise.all([\n readTaskDecisionsForTasks(nextRecord.tasks),\n readMemberProfilesForTimeline(nextRecord),\n listAttachments(nextRecord.instance.id),\n readInstanceSignatures(nextRecord.instance.id),\n ]);\n setTaskDecisions(nextTaskDecisions);\n setMemberProfiles(nextMemberProfiles);\n setAttachments(nextAttachments);\n setSignatures(nextSignatures.signatures);\n setSignatureVerification(nextSignatures.verification);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n async function handleDownloadAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentDownloadUrl({\n id: attachment.id,\n });\n\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n\n async function handlePreviewAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentPreviewUrl({\n id: attachment.id,\n });\n\n setPreviewAttachment(attachment);\n setPreviewUrl(url);\n }\n\n async function handleDecision({\n action,\n comment,\n returnToNodeId = null,\n transferToMemberId = null,\n }: Readonly<{\n action: 'APPROVED' | 'REJECTED' | 'RETURNED' | 'TRANSFERRED';\n comment: string | null;\n returnToNodeId?: string | null;\n transferToMemberId?: string | null;\n }>): Promise<void> {\n if (!currentMemberId || !currentTask) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await decideTask({\n action,\n comment,\n decidedByMemberId: currentMemberId,\n returnToNodeId,\n taskId: currentTask.id,\n transferToMemberId,\n });\n setRejectReasonModalOpen(false);\n setReturnModalOpen(false);\n setTransferModalOpen(false);\n setRejectReason('');\n setReturnComment('');\n setTransferComment('');\n setTransferMember(null);\n setReturnTargetNodeId(null);\n setRejectReasonError(null);\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n function openRejectReasonModal(): void {\n setRejectReason('');\n setRejectReasonError(null);\n setRejectReasonModalOpen(true);\n }\n\n function closeRejectReasonModal(): void {\n if (deciding) {\n return;\n }\n\n setRejectReasonModalOpen(false);\n setRejectReason('');\n setRejectReasonError(null);\n }\n\n function openReturnModal(): void {\n setReturnComment('');\n setReturnTargetNodeId(returnTargetOptions[0]?.id ?? null);\n setReturnModalOpen(true);\n }\n\n function closeReturnModal(): void {\n if (deciding) {\n return;\n }\n\n setReturnModalOpen(false);\n setReturnComment('');\n setReturnTargetNodeId(null);\n }\n\n function openTransferModal(): void {\n setTransferComment('');\n setTransferMember(null);\n setTransferModalOpen(true);\n void handleSearchTransferMembers('');\n }\n\n function closeTransferModal(): void {\n if (deciding) {\n return;\n }\n\n setTransferModalOpen(false);\n setTransferComment('');\n setTransferMember(null);\n }\n\n async function handleSearchTransferMembers(\n searchText: string,\n ): Promise<void> {\n setTransferMemberLoading(true);\n\n try {\n setTransferMemberOptions(\n (await searchMembers(searchText))\n .filter((searchedMember) => searchedMember.memberId !== currentMemberId)\n .map(readMemberOption),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setTransferMemberLoading(false);\n }\n }\n\n async function handleRejectConfirm(): Promise<void> {\n if (!trimmedRejectReason) {\n setRejectReasonError('請輸入拒絕原因');\n return;\n }\n\n await handleDecision({\n action: 'REJECTED',\n comment: trimmedRejectReason,\n });\n }\n\n async function handleTransferConfirm(): Promise<void> {\n if (!transferMember) {\n setError('請選擇轉派對象');\n return;\n }\n\n await handleDecision({\n action: 'TRANSFERRED',\n comment: trimmedTransferComment || null,\n transferToMemberId: transferMember.id,\n });\n }\n\n async function handleReturnConfirm(): Promise<void> {\n await handleDecision({\n action: 'RETURNED',\n comment: trimmedReturnComment || null,\n returnToNodeId: selectedReturnTargetOption?.id ?? null,\n });\n }\n\n async function handleCancelInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canCancelInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n setResubmitFormErrors({});\n\n if (\n instance.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema\n ) {\n const validation = validateFormRendererValues({\n schema: instance.formDefinitionSnapshot.schema,\n uiSchema: instance.formDefinitionSnapshot.uiSchema,\n values: resubmitFormData,\n });\n\n if (!validation.valid) {\n setResubmitFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setDeciding(false);\n\n return;\n }\n }\n\n try {\n await cancelApprovalInstance({\n cancelledByMemberId: currentMemberId,\n comment: trimmedCancelComment || null,\n instanceId: instance.id,\n });\n setCancelComment('');\n setCancelModalOpen(false);\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n async function handleResubmitInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canResubmitInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await resubmitApprovalInstance({\n formData: resubmitFormData,\n initiatorMemberId: currentMemberId,\n instanceId: instance.id,\n title: instance.title,\n });\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n instance\n ? `${readInstanceStateLabel(instance.state)} · ${formatDateTime(\n instance.startedAt,\n )}`\n : '載入案件內容。'\n }\n title={instance?.title ?? '簽核案件'}\n >\n {instance ? (\n <Button\n aria-label=\"查看流程圖\"\n icon={ShareIcon}\n iconType=\"icon-only\"\n onClick={(): void => setWorkflowModalOpen(true)}\n title=\"查看流程圖\"\n variant=\"base-secondary\"\n >\n 流程圖\n </Button>\n ) : null}\n {canCancelInstance ? (\n <Button\n disabled={deciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n onClick={(): void => setCancelModalOpen(true)}\n variant=\"destructive-secondary\"\n >\n 取消案件\n </Button>\n ) : null}\n {currentTask ? (\n <>\n {canReturnCurrentTask ? (\n <Button\n disabled={deciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n onClick={openReturnModal}\n variant=\"base-secondary\"\n >\n 退回\n </Button>\n ) : null}\n <Button\n disabled={deciding}\n icon={UserIcon}\n iconType=\"leading\"\n onClick={openTransferModal}\n variant=\"base-secondary\"\n >\n 轉派\n </Button>\n <Button\n disabled={deciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n onClick={openRejectReasonModal}\n variant=\"destructive-secondary\"\n >\n 拒絕\n </Button>\n <Button\n disabled={deciding}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={(): void =>\n void handleDecision({ action: 'APPROVED', comment: null })\n }\n variant=\"base-primary\"\n >\n 同意\n </Button>\n </>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={SECTION_BODY_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n {instance?.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema ? (\n <>\n <FormRenderer\n errors={resubmitFormErrors}\n onChange={(values): void => {\n setResubmitFormData(values);\n setResubmitFormErrors({});\n }}\n onUploadAttachment={\n canResubmitInstance ? handleUploadAttachment : undefined\n }\n readonly={!canResubmitInstance}\n schema={instance.formDefinitionSnapshot.schema}\n uiSchema={instance.formDefinitionSnapshot.uiSchema}\n value={\n canResubmitInstance ? resubmitFormData : instance.formData\n }\n />\n {canResubmitInstance ? (\n <div style={BUTTON_ROW_STYLE}>\n <Button\n disabled={deciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n onClick={(): void => void handleResubmitInstance()}\n variant=\"base-primary\"\n >\n 重新送出\n </Button>\n </div>\n ) : null}\n </>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有可顯示的表單快照。\n </Typography>\n )}\n </div>\n </Section>\n\n <Section>\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 附件\n </Typography>\n {attachmentRows.length > 0 ? (\n <Table\n actions={attachmentActions}\n columns={attachmentColumns}\n dataSource={attachmentRows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有附件。\n </Typography>\n )}\n </div>\n </Section>\n\n <Section>\n <Typography component=\"h2\" variant=\"h3\">\n 任務\n </Typography>\n <Table columns={taskColumns} dataSource={taskRows} fullWidth />\n </Section>\n\n <Section>\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 簽章\n </Typography>\n <Typography\n color={\n signatureVerification?.valid ? 'text-success' : 'text-error'\n }\n variant=\"body\"\n >\n {signatureVerification\n ? signatureVerification.valid\n ? `簽章鏈已驗證,共 ${signatureVerification.checkedCount} 筆。`\n : `簽章鏈驗證失敗:${signatureVerification.errors.join('、')}`\n : '尚無簽章紀錄。'}\n </Typography>\n {signatureRows.length > 0 ? (\n <Table\n columns={signatureColumns}\n dataSource={signatureRows}\n fullWidth\n />\n ) : null}\n </div>\n </Section>\n\n <Section>\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 歷程\n </Typography>\n {activitySteps.length > 0 ? (\n <Stepper\n currentStep={currentActivityStep}\n orientation=\"vertical\"\n type=\"dot\"\n >\n {activitySteps.map((activityStep) => (\n <ActivityHistoryStep\n descriptionParts={activityStep.descriptionParts}\n error={activityStep.error}\n forcePending={activityStep.forcePending}\n key={activityStep.id}\n title={activityStep.title}\n />\n ))}\n </Stepper>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 尚無歷程紀錄。\n </Typography>\n )}\n </div>\n </Section>\n </SectionGroup>\n\n {instance ? (\n <Modal\n modalType=\"standard\"\n onClose={(): void => setWorkflowModalOpen(false)}\n open={workflowModalOpen}\n showModalHeader\n size=\"wide\"\n supportingText={`${readInstanceStateLabel(\n instance.state,\n )} · ${formatDateTime(instance.startedAt)}`}\n title=\"流程圖\"\n >\n <div style={FLOW_MODAL_BODY_STYLE}>\n <div style={FLOW_CANVAS_STYLE}>\n <ReactFlow\n edges={flowEdges}\n fitView\n fitViewOptions={{ padding: 0.18 }}\n maxZoom={1.2}\n minZoom={0.2}\n nodes={flowNodes}\n nodesDraggable={false}\n nodesFocusable={false}\n nodeTypes={READONLY_FLOW_NODE_TYPES}\n panOnDrag\n proOptions={{ hideAttribution: true }}\n >\n <Background />\n <Controls showInteractive={false} />\n </ReactFlow>\n </div>\n {edgeSummaries.length > 0 ? (\n <div style={EDGE_SUMMARY_STYLE}>\n {edgeSummaries.map((summary) => (\n <span key={summary} style={EDGE_SUMMARY_ITEM_STYLE}>\n {summary}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n </Modal>\n ) : null}\n <Modal\n modalType=\"standard\"\n onClose={(): void => {\n setPreviewAttachment(null);\n setPreviewUrl(null);\n }}\n open={Boolean(previewAttachment && previewUrl)}\n showModalHeader\n size=\"wide\"\n supportingText={previewAttachment?.filename ?? undefined}\n title=\"PDF 預覽\"\n >\n {previewUrl ? (\n <PDFPreview\n filename={previewAttachment?.filename ?? 'PDF 預覽'}\n fileUrl={previewUrl}\n onDownload={\n previewAttachment\n ? (): void => void handleDownloadAttachment(previewAttachment)\n : undefined\n }\n />\n ) : null}\n </Modal>\n <Modal\n cancelText=\"保留案件\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"確認取消\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setCancelModalOpen(false)}\n onClose={(): void => setCancelModalOpen(false)}\n onConfirm={(): void => void handleCancelInstance()}\n open={cancelModalOpen}\n showModalFooter\n showModalHeader\n supportingText=\"取消後會關閉目前待簽任務與候選簽核人。\"\n title=\"取消案件\"\n >\n <div style={SECTION_BODY_STYLE}>\n <Typography variant=\"body\">\n 確定要取消「{instance?.title ?? ''}」嗎?\n </Typography>\n <BPMFormField label=\"取消原因\" name=\"cancelComment\">\n <Textarea\n onChange={(event): void =>\n setCancelComment(event.target.value)\n }\n placeholder=\"可填寫取消原因\"\n resize=\"vertical\"\n rows={3}\n value={cancelComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !trimmedRejectReason,\n variant: 'destructive-primary',\n }}\n confirmText=\"送出拒絕\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={closeRejectReasonModal}\n onClose={closeRejectReasonModal}\n onConfirm={(): void => void handleRejectConfirm()}\n open={rejectReasonModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"拒絕案件時必須留下原因,供發起人與後續追蹤查看。\"\n title=\"拒絕原因\"\n >\n <div style={REJECT_REASON_FORM_STYLE}>\n <BPMFormField label=\"拒絕原因\" name=\"rejectReason\" required>\n <Textarea\n autoFocus\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setRejectReason(event.target.value);\n setRejectReasonError(null);\n }}\n placeholder=\"請說明拒絕原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n type={rejectReasonError ? 'error' : 'default'}\n value={rejectReason}\n />\n </BPMFormField>\n {rejectReasonError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {rejectReasonError}\n </Typography>\n ) : null}\n </div>\n </Modal>\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !transferMember,\n }}\n confirmText=\"送出轉派\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeTransferModal}\n onClose={closeTransferModal}\n onConfirm={(): void => void handleTransferConfirm()}\n open={transferModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"轉派後,原任務會保留轉派紀錄,新的待簽任務會指派給指定成員。\"\n title=\"轉派簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"轉派對象\" name=\"transferToMemberId\" required>\n <AutoComplete\n asyncData\n disabledOptionsFilter\n emptyText=\"沒有符合的成員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name: 'transfer-member-search',\n spellCheck: false,\n }}\n loading={transferMemberLoading}\n loadingText=\"搜尋成員中...\"\n mode=\"single\"\n onChange={(option): void =>\n setTransferMember(readMemberOptionFromValue(option))\n }\n onSearch={handleSearchTransferMembers}\n onSearchTextChange={(searchText): void =>\n setTransferMember(\n readUniqueMemberOption(searchText, transferMemberOptions),\n )\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearchTransferMembers('');\n }\n }}\n options={[...transferMemberOptions]}\n placeholder=\"搜尋姓名或信箱\"\n searchDebounceTime={300}\n value={transferMember}\n />\n </BPMFormField>\n <BPMFormField label=\"轉派說明\" name=\"transferComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setTransferComment(event.target.value)\n }\n placeholder=\"可補充轉派原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={transferComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !selectedReturnTargetOption,\n }}\n confirmText=\"送出退回\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeReturnModal}\n onClose={closeReturnModal}\n onConfirm={(): void => void handleReturnConfirm()}\n open={returnModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"退回後,流程會回到指定節點並等待重新處理。\"\n title=\"退回簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"退回節點\" name=\"returnTargetNodeId\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setReturnTargetNodeId(option?.id ?? null)\n }\n options={[...returnTargetOptions]}\n placeholder=\"選擇退回節點\"\n value={selectedReturnTargetOption}\n />\n </BPMFormField>\n <BPMFormField label=\"退回說明\" name=\"returnComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setReturnComment(event.target.value)\n }\n placeholder=\"可補充需要修改的內容\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={returnComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nfunction formatFileSize(sizeBytes: number): string {\n if (!Number.isFinite(sizeBytes) || sizeBytes <= 0) {\n return '-';\n }\n\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n if (sizeBytes < 1024 * 1024) {\n return `${(sizeBytes / 1024).toFixed(1)} KB`;\n }\n\n return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\nfunction readShortHash(hash: string): string {\n return hash.length > 16 ? `${hash.slice(0, 12)}...` : hash;\n}\n\nfunction joinClassNames(\n ...classNames: readonly (string | null | undefined)[]\n): string {\n return classNames\n .filter((className): className is string =>\n isPresentText(className ?? null),\n )\n .join(' ');\n}\n\ninterface ActivityHistoryStepProps extends StepProps {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly forcePending?: boolean;\n}\n\nconst ActivityHistoryStep = forwardRef<\n HTMLDivElement,\n ActivityHistoryStepProps\n>(function ActivityHistoryStep(\n {\n className,\n descriptionParts,\n error,\n forcePending = false,\n index = 0,\n orientation,\n status = 'pending',\n title,\n type = 'number',\n ...rest\n },\n ref,\n): ReactElement {\n const displayStatus = forcePending ? 'pending' : status;\n\n return (\n <div\n {...rest}\n className={joinClassNames(\n stepClasses.host,\n type === 'dot' ? stepClasses.dot : null,\n error && displayStatus !== 'processing' ? stepClasses.error : null,\n orientation === 'horizontal' ? stepClasses.horizontal : null,\n type === 'number' ? stepClasses.number : null,\n displayStatus === 'pending' ? stepClasses.pending : null,\n displayStatus === 'processing' ? stepClasses.processing : null,\n error && displayStatus === 'processing'\n ? stepClasses.processingError\n : null,\n !error && displayStatus === 'succeeded' ? stepClasses.succeeded : null,\n orientation === 'vertical' ? stepClasses.vertical : null,\n className,\n )}\n ref={ref}\n >\n {type === 'dot' ? (\n <span\n className={joinClassNames(\n stepClasses.statusIndicator,\n stepClasses.statusIndicatorDot,\n )}\n />\n ) : (\n <span className={stepClasses.statusIndicator}>{index + 1}</span>\n )}\n <div className={stepClasses.textContainer}>\n <Typography\n className={stepClasses.title}\n variant=\"label-primary-highlight\"\n >\n {title}\n <span className={stepClasses.titleConnectLine} />\n </Typography>\n {descriptionParts.length > 0 ? (\n <Typography className={stepClasses.description} variant=\"caption\">\n {descriptionParts.map((part, partIndex) => (\n <Fragment key={`${part.type}-${partIndex}`}>\n {partIndex > 0 ? ' · ' : null}\n {renderActivityDescriptionPart(part)}\n </Fragment>\n ))}\n </Typography>\n ) : null}\n </div>\n </div>\n );\n});\n\nfunction renderActivityDescriptionPart(\n part: ActivityStepDescriptionPart,\n): ReactElement | string {\n if (part.type === 'text') {\n return part.text;\n }\n\n if (part.type === 'dangerText') {\n return <span style={HISTORY_DANGER_TEXT_STYLE}>{part.text}</span>;\n }\n\n if (!part.email) {\n return `${part.prefix}:${part.label}`;\n }\n\n return (\n <>\n {part.prefix}:\n <Tooltip title={part.email}>\n {({ onMouseEnter, onMouseLeave, ref }): ReactElement => (\n <span\n data-testid={\n part.memberId ? `member-tooltip-${part.memberId}` : undefined\n }\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n ref={ref as RefCallback<HTMLSpanElement>}\n style={HISTORY_MEMBER_NAME_STYLE}\n >\n {part.label}\n </span>\n )}\n </Tooltip>\n </>\n );\n}\n\nasync function readMemberProfilesForTimeline({\n activityLogs,\n tasks,\n}: {\n readonly activityLogs: readonly ActivityLogRecord[];\n readonly tasks: readonly TaskRecord[];\n}): Promise<readonly MemberProfileRecord[]> {\n const memberIds = [\n ...new Set(\n [\n ...activityLogs.map((activityLog) => activityLog.actorMemberId),\n ...tasks.map((task) => task.assigneeMemberId),\n ...tasks.map((task) => task.originalAssigneeMemberId),\n ...tasks.flatMap((task) => task.candidateMemberIds),\n ...tasks.flatMap((task) =>\n readDelegationChain(task.delegationChainJson).flatMap((step) => [\n step.from,\n step.to,\n ]),\n ),\n ].filter(isPresentText),\n ),\n ];\n\n try {\n return await resolveMemberProfiles(memberIds);\n } catch {\n return [];\n }\n}\n\nasync function readTaskDecisionsForTasks(\n tasks: readonly TaskRecord[],\n): Promise<readonly TaskDecisionRecord[]> {\n const decisionLists = await Promise.all(\n tasks.map((task) => listTaskDecisions(task.id)),\n );\n\n return decisionLists.flat();\n}\n\nfunction readLatestTaskDecisionsByTaskId(\n taskDecisions: readonly TaskDecisionRecord[],\n): ReadonlyMap<string, TaskDecisionRecord> {\n return taskDecisions.reduce<ReadonlyMap<string, TaskDecisionRecord>>(\n (decisionsByTaskId, decision) => {\n const currentDecision = decisionsByTaskId.get(decision.taskId);\n const nextDecision =\n !currentDecision ||\n new Date(decision.decidedAt).getTime() >\n new Date(currentDecision.decidedAt).getTime()\n ? decision\n : currentDecision;\n\n return new Map(decisionsByTaskId).set(decision.taskId, nextDecision);\n },\n new Map(),\n );\n}\n\nfunction readActivityStepRecords(\n activityLogs: readonly ActivityLogRecord[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n workflow: WorkflowDefinition | null,\n instanceState: ApprovalInstanceRecord['state'],\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n): ActivityStepRecord[] {\n const historySteps = activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog): ActivityStepRecord => {\n const payload = readActivityPayload(activityLog);\n const nodeLabel = readActivityNodeLabel(activityLog.nodeId, workflow);\n const descriptionParts = [\n readTextDescriptionPart(\n nodeLabel ? `節點:${nodeLabel}` : '節點:全流程',\n ),\n readMemberDescriptionPart(\n '操作者',\n activityLog.actorMemberId,\n memberProfilesById,\n '系統',\n ),\n readTextDescriptionPart(\n `時間:${formatActivityDateTime(activityLog.createdAt)}`,\n ),\n ...readActivityDetailParts(\n activityLog,\n payload,\n workflow,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n memberProfilesById,\n ),\n ].filter(isActivityDescriptionPart);\n\n return {\n descriptionParts,\n error: isActivityError(activityLog, payload),\n id: activityLog.id,\n title: readActivityEventLabel(activityLog.eventType, payload),\n };\n });\n const pendingTaskSteps = tasks.filter(isPendingTask).map(\n (task): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `節點:${readNodeDisplayLabel(task.nodeId, workflow)}`,\n ),\n readMemberDescriptionPart(\n '處理者',\n task.assigneeMemberId,\n memberProfilesById,\n '未指定',\n ),\n readTextDescriptionPart(\n `建立時間:${formatActivityDateTime(task.createdAt)}`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n id: `pending-task-${task.id}`,\n title: task.status === 'IN_PROGRESS' ? '簽核處理中' : '等待簽核處理',\n }),\n );\n const representedNodeIds = new Set(\n [\n ...activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog) => activityLog.nodeId),\n ...tasks.map((task) => task.nodeId),\n ].filter(isPresentText),\n );\n const futureNodeSteps = workflow\n ? readFutureTimelineNodes(\n workflow,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ).map(\n (node): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `${readNodeKindLabel(node.type)} · 尚未抵達`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n forcePending: true,\n id: `future-node-${node.id}`,\n title: readFutureNodeStepTitle(node),\n }),\n )\n : [];\n\n return [...historySteps, ...pendingTaskSteps, ...futureNodeSteps];\n}\n\nfunction readTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'text' } : null;\n}\n\nfunction readDangerTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'dangerText' } : null;\n}\n\nfunction readMemberDescriptionPart(\n prefix: string,\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n fallbackLabel: string,\n): ActivityStepDescriptionPart {\n const profile = memberId ? memberProfilesById.get(memberId) : null;\n\n return {\n email: profile?.email ?? null,\n label: profile?.name ?? fallbackLabel,\n memberId,\n prefix,\n type: 'member',\n };\n}\n\nfunction readMemberDisplayText(\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n if (!memberId) {\n return '-';\n }\n\n const profile = memberProfilesById.get(memberId);\n\n return profile ? `${profile.name}(${profile.email})` : memberId;\n}\n\nfunction isActivityDescriptionPart(\n part: ActivityStepDescriptionPart | null,\n): part is ActivityStepDescriptionPart {\n return Boolean(part);\n}\n\nfunction readCurrentActivityStep(\n activitySteps: readonly ActivityStepRecord[],\n): number {\n const firstPendingStepIndex = activitySteps.findIndex(\n (activityStep) =>\n activityStep.id.startsWith('pending-task-') ||\n activityStep.id.startsWith('future-node-'),\n );\n\n return firstPendingStepIndex === -1\n ? activitySteps.length\n : firstPendingStepIndex;\n}\n\nfunction isUserMeaningfulActivity(activityLog: ActivityLogRecord): boolean {\n return (\n activityLog.eventType === 'INSTANCE_STARTED' ||\n activityLog.eventType === 'TASK_DECIDED' ||\n activityLog.eventType === 'SLA_TRIGGERED'\n );\n}\n\nfunction isFutureTimelineNode(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): boolean {\n if (node.type === 'startEvent' || representedNodeIds.has(node.id)) {\n return false;\n }\n\n if (instanceState === 'REJECTED') {\n return true;\n }\n\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return state.tone === 'neutral' || state.tone === 'waiting';\n}\n\nfunction readFutureTimelineNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): readonly WorkflowNode[] {\n if (instanceState !== 'RUNNING' && instanceState !== 'REJECTED') {\n return [];\n }\n\n const futureNodes = workflow.nodes.filter((node) =>\n isFutureTimelineNode(\n node,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ),\n );\n const reachableDistances = readReachableFutureNodeDistances(\n workflow,\n futureNodes,\n tasks,\n tokens,\n representedNodeIds,\n );\n const originalNodeIndexes = new Map(\n workflow.nodes.map((node, index) => [node.id, index]),\n );\n\n return futureNodes\n .filter((node) => reachableDistances.has(node.id))\n .sort((left, right) => {\n const leftDistance = reachableDistances.get(left.id) ?? 0;\n const rightDistance = reachableDistances.get(right.id) ?? 0;\n\n if (leftDistance !== rightDistance) {\n return leftDistance - rightDistance;\n }\n\n if (left.position.x !== right.position.x) {\n return left.position.x - right.position.x;\n }\n\n if (left.position.y !== right.position.y) {\n return left.position.y - right.position.y;\n }\n\n return (\n (originalNodeIndexes.get(left.id) ?? 0) -\n (originalNodeIndexes.get(right.id) ?? 0)\n );\n });\n}\n\nfunction readReachableFutureNodeDistances(\n workflow: WorkflowDefinition,\n futureNodes: readonly WorkflowNode[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const futureNodeIds = new Set(futureNodes.map((node) => node.id));\n const outgoingNodeIds = workflow.edges.reduce<\n ReadonlyMap<string, readonly string[]>\n >((groups, edge) => {\n const nextTargets = [...(groups.get(edge.source) ?? []), edge.target];\n\n return new Map(groups).set(edge.source, nextTargets);\n }, new Map());\n const frontierNodeIds = readFutureTimelineFrontierNodeIds(\n workflow,\n tasks,\n tokens,\n representedNodeIds,\n );\n\n return frontierNodeIds.reduce<ReadonlyMap<string, number>>(\n (distances, nodeId) =>\n mergeFutureNodeDistances(\n distances,\n readFutureNodeDistancesFrom(nodeId, outgoingNodeIds, futureNodeIds),\n ),\n new Map(),\n );\n}\n\nfunction readFutureTimelineFrontierNodeIds(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): readonly string[] {\n const tokenNodeIds = tokens\n .filter((token) => token.status === 'ACTIVE' || token.status === 'WAITING')\n .map((token) => token.currentNodeId);\n const pendingTaskNodeIds = tasks\n .filter(isPendingTask)\n .map((task) => task.nodeId);\n const representedFrontierNodeIds = workflow.nodes\n .filter((node) => representedNodeIds.has(node.id))\n .map((node) => node.id);\n const activeFrontierNodeIds = [\n ...new Set([\n ...tokenNodeIds,\n ...pendingTaskNodeIds,\n ...representedFrontierNodeIds,\n ]),\n ];\n const startNodeIds = workflow.nodes\n .filter((node) => node.type === 'startEvent')\n .map((node) => node.id);\n\n return activeFrontierNodeIds.length > 0\n ? activeFrontierNodeIds\n : startNodeIds;\n}\n\nfunction readFutureNodeDistancesFrom(\n startNodeId: string,\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const initialQueue: readonly {\n readonly distance: number;\n readonly nodeId: string;\n }[] = [{ distance: 0, nodeId: startNodeId }];\n\n return walkFutureNodeDistances(initialQueue, outgoingNodeIds, futureNodeIds);\n}\n\nfunction walkFutureNodeDistances(\n queue: readonly { readonly distance: number; readonly nodeId: string }[],\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n visitedNodeIds: ReadonlySet<string> = new Set(),\n distances: ReadonlyMap<string, number> = new Map(),\n): ReadonlyMap<string, number> {\n const [current, ...restQueue] = queue;\n\n if (!current) {\n return distances;\n }\n\n if (visitedNodeIds.has(current.nodeId)) {\n return walkFutureNodeDistances(\n restQueue,\n outgoingNodeIds,\n futureNodeIds,\n visitedNodeIds,\n distances,\n );\n }\n\n const nextVisitedNodeIds = new Set(visitedNodeIds).add(current.nodeId);\n const nextDistances = futureNodeIds.has(current.nodeId)\n ? new Map(distances).set(\n current.nodeId,\n Math.min(\n distances.get(current.nodeId) ?? current.distance,\n current.distance,\n ),\n )\n : distances;\n const nextQueue = [\n ...restQueue,\n ...(outgoingNodeIds.get(current.nodeId) ?? []).map((nodeId) => ({\n distance: current.distance + 1,\n nodeId,\n })),\n ];\n\n return walkFutureNodeDistances(\n nextQueue,\n outgoingNodeIds,\n futureNodeIds,\n nextVisitedNodeIds,\n nextDistances,\n );\n}\n\nfunction mergeFutureNodeDistances(\n currentDistances: ReadonlyMap<string, number>,\n nextDistances: ReadonlyMap<string, number>,\n): ReadonlyMap<string, number> {\n return [...nextDistances.entries()].reduce<ReadonlyMap<string, number>>(\n (mergedDistances, [nodeId, distance]) =>\n new Map(mergedDistances).set(\n nodeId,\n Math.min(mergedDistances.get(nodeId) ?? distance, distance),\n ),\n currentDistances,\n );\n}\n\nfunction readFutureNodeStepTitle(node: WorkflowNode): string {\n if (node.type === 'userTask') {\n return `未來簽核:${node.data.label}`;\n }\n\n if (node.type === 'serviceTask') {\n return `未來知會:${node.data.label}`;\n }\n\n if (node.type === 'exclusiveGateway') {\n return `未來分流:${node.data.label}`;\n }\n\n if (node.type === 'parallelGateway') {\n return `未來匯合:${node.data.label}`;\n }\n\n if (node.type === 'endEvent') {\n return `流程完成:${node.data.label}`;\n }\n\n return `未來節點:${node.data.label}`;\n}\n\nfunction readActivityPayload(\n activityLog: ActivityLogRecord,\n): Readonly<Record<string, unknown>> {\n try {\n const payload = JSON.parse(activityLog.payloadJson) as unknown;\n\n return isRecord(payload) ? payload : {};\n } catch {\n return {};\n }\n}\n\nfunction readActivityEventLabel(\n eventType: string,\n payload: Readonly<Record<string, unknown>>,\n): string {\n if (eventType === 'INSTANCE_STARTED') {\n return '案件已發起';\n }\n\n if (eventType === 'TOKEN_CREATED') {\n return '流程路徑已建立';\n }\n\n if (eventType === 'ENGINE_PROCESS_REQUESTED') {\n return '流程引擎已處理';\n }\n\n if (eventType === 'TOKEN_ADVANCED') {\n return '流程已前進';\n }\n\n if (eventType === 'TASK_CREATED') {\n return '待簽任務已建立';\n }\n\n if (eventType === 'TASK_DECIDED') {\n return readTaskDecisionEventLabel(readStringField(payload, 'action'));\n }\n\n if (eventType === 'SLA_TRIGGERED') {\n return '時限提醒已觸發';\n }\n\n return eventType;\n}\n\nfunction readTaskDecisionEventLabel(action: string | null): string {\n if (action === 'APPROVED') {\n return '已同意';\n }\n\n if (action === 'REJECTED') {\n return '已拒絕';\n }\n\n if (action === 'RETURNED') {\n return '已退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '已轉派';\n }\n\n return '簽核已決議';\n}\n\nfunction readActivityDetail(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string | null {\n if (activityLog.eventType === 'TASK_CREATED') {\n const assigneeMemberId = readStringField(payload, 'assigneeMemberId');\n const originalAssigneeMemberId = readStringField(\n payload,\n 'originalAssigneeMemberId',\n );\n\n if (!assigneeMemberId) {\n const candidateMemberIds = readStringArrayField(\n payload,\n 'candidateMemberIds',\n );\n\n return candidateMemberIds.length\n ? `候選簽核人:${candidateMemberIds\n .map((memberId) =>\n readMemberDisplayText(memberId, memberProfilesById),\n )\n .join('、')}`\n : null;\n }\n\n const assigneeLabel = readMemberDisplayText(\n assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n originalAssigneeMemberId,\n memberProfilesById,\n );\n\n return originalAssigneeMemberId &&\n originalAssigneeMemberId !== assigneeMemberId\n ? `待簽人:${assigneeLabel}(原簽核人:${originalAssigneeLabel})`\n : `待簽人:${assigneeLabel}`;\n }\n\n if (activityLog.eventType === 'TASK_DECIDED') {\n const action = readStringField(payload, 'action');\n const comment = readStringField(payload, 'comment');\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n const transferToMemberId = readStringField(payload, 'transferToMemberId');\n\n return action === 'REJECTED' && comment\n ? [decisionLabel, `拒絕原因:${comment}`]\n .filter(isPresentText)\n .join(' · ')\n : action === 'TRANSFERRED'\n ? [\n decisionLabel,\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n ]\n .filter(isPresentText)\n .join(' · ')\n : decisionLabel;\n }\n\n if (activityLog.eventType === 'TOKEN_ADVANCED') {\n const action = readStringField(payload, 'action');\n\n if (action) {\n return `流程結果:${readTaskDecisionActionLabel(action)}`;\n }\n\n const arrivedCount = readNumberField(payload, 'arrivedCount');\n const requiredCount = readNumberField(payload, 'requiredCount');\n\n if (arrivedCount !== null && requiredCount !== null) {\n return `等待匯合:${arrivedCount}/${requiredCount}`;\n }\n\n const fromNodeId = readStringField(payload, 'fromNodeId');\n const toNodeId = readStringField(payload, 'toNodeId');\n\n if (fromNodeId && toNodeId) {\n return `由 ${readNodeDisplayLabel(fromNodeId, workflow)} 前進至 ${readNodeDisplayLabel(toNodeId, workflow)}`;\n }\n }\n\n if (activityLog.eventType === 'ENGINE_PROCESS_REQUESTED') {\n const state = readStringField(payload, 'state');\n\n return state ? `案件狀態:${readInstanceStateLabel(state)}` : null;\n }\n\n return null;\n}\n\nfunction readActivityDetailParts(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): readonly ActivityStepDescriptionPart[] {\n if (activityLog.eventType !== 'TASK_DECIDED') {\n return [\n readTextDescriptionPart(\n readActivityDetail(\n activityLog,\n payload,\n workflow,\n memberProfilesById,\n ),\n ),\n ].filter(isActivityDescriptionPart);\n }\n\n const taskDecision = activityLog.taskId\n ? taskDecisionsByTaskId.get(activityLog.taskId)\n : null;\n const action =\n readStringField(payload, 'action') ?? taskDecision?.action ?? null;\n const comment =\n readStringField(payload, 'comment') ?? taskDecision?.comment ?? null;\n const transferToMemberId =\n readStringField(payload, 'transferToMemberId') ??\n taskDecision?.transferToMemberId ??\n null;\n const signatureId =\n readStringField(payload, 'signatureId') ??\n taskDecision?.signatureId ??\n null;\n const signature = signatureId ? signaturesById.get(signatureId) : null;\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n return [\n readTextDescriptionPart(decisionLabel),\n action === 'REJECTED'\n ? readDangerTextDescriptionPart(`拒絕原因:${comment ?? '-'}`)\n : null,\n action === 'RETURNED'\n ? readTextDescriptionPart(`退回說明:${comment ?? '-'}`)\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n )\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(`轉派說明:${comment ?? '-'}`)\n : null,\n signature\n ? readTextDescriptionPart(\n signatureVerification?.valid\n ? `簽章:已驗證(${readShortHash(signature.signedPayloadHash)})`\n : `簽章:待檢查(${readShortHash(signature.signedPayloadHash)})`,\n )\n : null,\n ].filter(isActivityDescriptionPart);\n}\n\nfunction readActivityNodeLabel(\n nodeId: string | null,\n workflow: WorkflowDefinition | null,\n): string | null {\n return nodeId ? readNodeDisplayLabel(nodeId, workflow) : null;\n}\n\nfunction readNodeDisplayLabel(\n nodeId: string,\n workflow: WorkflowDefinition | null,\n): string {\n return (\n workflow?.nodes.find((node) => node.id === nodeId)?.data.label ?? nodeId\n );\n}\n\nfunction readReturnTargetOptions(\n workflow: WorkflowDefinition,\n node: WorkflowNode,\n): readonly { readonly id: string; readonly name: string }[] {\n if (node.type !== 'userTask' || !node.data.returnBehavior.allowReturn) {\n return [];\n }\n\n if (node.data.returnBehavior.allowedTargets === 'ANY') {\n return workflow.nodes\n .filter((candidate) => candidate.id !== node.id)\n .map((candidate) => ({\n id: candidate.id,\n name: `${candidate.data.label}(${readNodeKindLabel(candidate.type)})`,\n }));\n }\n\n const targetNodeId =\n node.data.returnBehavior.allowedTargets === 'INITIATOR'\n ? workflow.nodes.find((candidate) => candidate.type === 'startEvent')?.id\n : workflow.edges.find((edge) => edge.target === node.id)?.source;\n const targetNode = workflow.nodes.find(\n (candidate) => candidate.id === targetNodeId,\n );\n\n return targetNode\n ? [\n {\n id: targetNode.id,\n name: `${targetNode.data.label}(${readNodeKindLabel(\n targetNode.type,\n )})`,\n },\n ]\n : [];\n}\n\nfunction readTaskDecisionActionLabel(action: string): string {\n if (action === 'APPROVED') {\n return '同意';\n }\n\n if (action === 'REJECTED') {\n return '拒絕';\n }\n\n if (action === 'RETURNED') {\n return '退回';\n }\n\n if (action === 'TRANSFERRED') {\n return '轉派';\n }\n\n return action;\n}\n\nfunction readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') {\n return '待處理';\n }\n\n if (status === 'IN_PROGRESS') {\n return '處理中';\n }\n\n if (status === 'COMPLETED') {\n return '已完成';\n }\n\n if (status === 'CANCELLED') {\n return '已取消';\n }\n\n if (status === 'TRANSFERRED') {\n return '已轉派';\n }\n\n return status;\n}\n\nfunction readTaskAssigneeLabel(\n task: TaskRecord,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord> = new Map(),\n): string {\n const delegationChain = readDelegationChain(task.delegationChainJson);\n\n if (!task.assigneeMemberId) {\n return task.candidateMemberIds.length\n ? `候選 ${task.candidateMemberIds\n .map((memberId) => readMemberDisplayText(memberId, memberProfilesById))\n .join('、')}`\n : '未指定';\n }\n\n const assigneeLabel = readMemberDisplayText(\n task.assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n task.originalAssigneeMemberId,\n memberProfilesById,\n );\n\n if (\n delegationChain.length === 0 ||\n task.originalAssigneeMemberId === task.assigneeMemberId\n ) {\n return assigneeLabel;\n }\n\n return `${assigneeLabel}(原:${originalAssigneeLabel})`;\n}\n\nfunction canMemberActOnTask(\n task: TaskRecord,\n memberId: string | null,\n): boolean {\n if (!memberId) {\n return false;\n }\n\n return (\n task.assigneeMemberId === memberId ||\n task.candidateMemberIds.includes(memberId)\n );\n}\n\nfunction readInstanceStateLabel(state: string): string {\n if (state === 'APPROVED') {\n return '已同意';\n }\n\n if (state === 'CANCELLED') {\n return '已取消';\n }\n\n if (state === 'DRAFT') {\n return '草稿';\n }\n\n if (state === 'EXPIRED') {\n return '已逾期';\n }\n\n if (state === 'REJECTED') {\n return '已拒絕';\n }\n\n if (state === 'RETURNED') {\n return '已退回';\n }\n\n if (state === 'RUNNING') {\n return '進行中';\n }\n\n return state;\n}\n\nfunction isActivityError(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n): boolean {\n return (\n activityLog.eventType === 'SLA_TRIGGERED' ||\n readStringField(payload, 'action') === 'REJECTED' ||\n readStringField(payload, 'instanceState') === 'REJECTED'\n );\n}\n\nfunction formatActivityDateTime(value: string): string {\n return formatDateTime(value);\n}\n\nfunction readStringField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): string | null {\n const value = record[key];\n\n return typeof value === 'string' ? value : null;\n}\n\nfunction readStringArrayField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): readonly string[] {\n const value = record[key];\n\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nfunction readMemberOption(profile: MemberProfileRecord): MemberOption {\n return {\n email: profile.email,\n id: profile.memberId,\n name: `${profile.name} · ${profile.email}`,\n };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const email = value.email;\n const id = value.id;\n const name = value.name;\n\n return typeof id === 'string' && typeof name === 'string'\n ? { email: typeof email === 'string' ? email : null, id, name }\n : null;\n}\n\nfunction readUniqueMemberOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalizedSearchText = searchText.trim().toLocaleLowerCase();\n\n if (!normalizedSearchText) {\n return null;\n }\n\n const matches = options.filter((option) =>\n [option.id, option.name, option.email ?? ''].some((value) =>\n value.toLocaleLowerCase().includes(normalizedSearchText),\n ),\n );\n\n return matches.length === 1 ? (matches[0] ?? null) : null;\n}\n\ninterface DelegationChainStep {\n readonly from: string;\n readonly reason: string;\n readonly ruleId: string | null;\n readonly to: string;\n}\n\nfunction readDelegationChain(value: string): readonly DelegationChainStep[] {\n try {\n const parsed = JSON.parse(value) as unknown;\n\n return Array.isArray(parsed)\n ? parsed\n .map((item): DelegationChainStep | null =>\n isRecord(item) ? readDelegationChainStep(item) : null,\n )\n .filter((item): item is DelegationChainStep => item !== null)\n : [];\n } catch {\n return [];\n }\n}\n\nfunction readDelegationChainStep(\n item: Readonly<Record<string, unknown>>,\n): DelegationChainStep | null {\n const from = readStringField(item, 'from');\n const to = readStringField(item, 'to');\n const reason = readStringField(item, 'reason');\n\n if (!from || !to || !reason) {\n return null;\n }\n\n return {\n from,\n reason,\n ruleId: readStringField(item, 'ruleId'),\n to,\n };\n}\n\nfunction readNumberField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): number | null {\n const value = record[key];\n\n return typeof value === 'number' ? value : null;\n}\n\nfunction isPresentText(value: string | null): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isPendingTask(task: TaskRecord): boolean {\n return task.status === 'PENDING' || task.status === 'IN_PROGRESS';\n}\n\nfunction WorkflowRuntimeNodeCard({\n data,\n}: NodeProps<RuntimeFlowNode>): ReactElement {\n return (\n <div style={readNodeStyle(data.tone)}>\n <Handle\n isConnectable={false}\n position={Position.Left}\n style={NODE_HANDLE_STYLE}\n type=\"target\"\n />\n <Typography\n component=\"span\"\n ellipsis\n title={data.label}\n variant=\"label-primary\"\n >\n {data.label}\n </Typography>\n <span style={readNodeStatusStyle(data.tone)}>{data.statusLabel}</span>\n <span title={data.secondaryLabel} style={NODE_SECONDARY_STYLE}>\n {data.secondaryLabel || data.kindLabel}\n </span>\n <Handle\n isConnectable={false}\n position={Position.Right}\n style={NODE_HANDLE_STYLE}\n type=\"source\"\n />\n </div>\n );\n}\n\nfunction readRuntimeFlowNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): RuntimeFlowNode[] {\n return workflow.nodes.map((node): RuntimeFlowNode => {\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return {\n data: {\n kindLabel: readNodeKindLabel(node.type),\n label: node.data.label,\n secondaryLabel: state.secondaryLabel,\n statusLabel: state.statusLabel,\n tone: state.tone,\n },\n id: node.id,\n position: node.position,\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n type: 'workflowRuntime',\n };\n });\n}\n\nfunction layoutRuntimeWorkflowDefinition(\n workflow: WorkflowDefinition,\n): WorkflowDefinition {\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n nodesep: 56,\n rankdir: 'LR',\n ranksep: 120,\n });\n workflow.nodes.forEach((node): void => {\n graph.setNode(node.id, {\n height: FLOW_NODE_LAYOUT_HEIGHT,\n width: FLOW_NODE_LAYOUT_WIDTH,\n });\n });\n workflow.edges.forEach((edge): void => {\n graph.setEdge(edge.source, edge.target);\n });\n dagre.layout(graph);\n\n return {\n ...workflow,\n nodes: workflow.nodes.map((node): WorkflowNode => {\n const positionedNode = graph.node(node.id) as\n | { readonly x: number; readonly y: number }\n | undefined;\n\n return positionedNode\n ? {\n ...node,\n position: {\n x: positionedNode.x - FLOW_NODE_LAYOUT_WIDTH / 2,\n y: positionedNode.y - FLOW_NODE_LAYOUT_HEIGHT / 2,\n },\n }\n : node;\n }),\n };\n}\n\nfunction readRuntimeFlowEdges(workflow: WorkflowDefinition): RuntimeFlowEdge[] {\n return workflow.edges.map((edge): RuntimeFlowEdge => {\n const label = readEdgeLabel(edge);\n\n return {\n animated: false,\n id: edge.id,\n label,\n labelBgBorderRadius: 6,\n labelBgPadding: [8, 4],\n labelBgStyle: {\n fill: edge.data.isDefault ? '#f8fafc' : '#eff6ff',\n stroke: edge.data.isDefault ? '#64748b' : '#2563eb',\n strokeWidth: 1,\n },\n labelShowBg: Boolean(label),\n labelStyle: {\n fill: edge.data.isDefault ? '#475569' : '#2563eb',\n fontSize: 12,\n fontWeight: 600,\n },\n source: edge.source,\n style: {\n stroke: '#475569',\n strokeWidth: 1.5,\n },\n target: edge.target,\n type: edge.type ?? 'smoothstep',\n };\n });\n}\n\nfunction readNodeRuntimeState(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): Readonly<{\n secondaryLabel: string;\n statusLabel: string;\n tone: RuntimeTone;\n}> {\n const nodeTasks = tasks.filter((task) => task.nodeId === node.id);\n const pendingTask = nodeTasks.find(\n (task) => task.status === 'PENDING' || task.status === 'IN_PROGRESS',\n );\n const cancelledTask = nodeTasks.find((task) => task.status === 'CANCELLED');\n const completedTask = nodeTasks.find((task) => task.status === 'COMPLETED');\n const nodeTokens = tokens.filter((token) => token.currentNodeId === node.id);\n const activeToken = nodeTokens.find((token) => token.status === 'ACTIVE');\n const waitingToken = nodeTokens.find((token) => token.status === 'WAITING');\n\n if (pendingTask) {\n return {\n secondaryLabel: `處理者 ${readTaskAssigneeLabel(pendingTask)}`,\n statusLabel: '待處理',\n tone: 'current',\n };\n }\n\n if (cancelledTask) {\n return {\n secondaryLabel: `已取消 ${readTaskAssigneeLabel(cancelledTask)}`,\n statusLabel: '已取消',\n tone: 'cancelled',\n };\n }\n\n if (completedTask) {\n return {\n secondaryLabel: `已完成 ${readTaskAssigneeLabel(completedTask)}`,\n statusLabel: '已完成',\n tone: 'completed',\n };\n }\n\n if (activeToken) {\n return {\n secondaryLabel: `token ${activeToken.id}`,\n statusLabel: '執行中',\n tone: 'current',\n };\n }\n\n if (waitingToken) {\n return {\n secondaryLabel: `token ${waitingToken.id}`,\n statusLabel: '等待前置',\n tone: 'waiting',\n };\n }\n\n if (node.type === 'startEvent') {\n return {\n secondaryLabel: '流程已發起',\n statusLabel: '已發起',\n tone: 'completed',\n };\n }\n\n if (node.type === 'endEvent' && instanceState !== 'RUNNING') {\n return {\n secondaryLabel: instanceState,\n statusLabel: instanceState === 'REJECTED' ? '已拒絕' : '已完成',\n tone: instanceState === 'REJECTED' ? 'cancelled' : 'completed',\n };\n }\n\n return {\n secondaryLabel: readNodeKindLabel(node.type),\n statusLabel: '未抵達',\n tone: 'neutral',\n };\n}\n\nfunction readNodeKindLabel(type: WorkflowNode['type']): string {\n if (type === 'startEvent') {\n return '開始';\n }\n\n if (type === 'endEvent') {\n return '完成';\n }\n\n if (type === 'userTask') {\n return '簽核節點';\n }\n\n if (type === 'serviceTask') {\n return '知會節點';\n }\n\n if (type === 'exclusiveGateway') {\n return '條件分流';\n }\n\n return '平行處理';\n}\n\nfunction readNodeStyle(tone: RuntimeTone): CSSProperties {\n if (tone === 'current') {\n return {\n ...NODE_STYLE,\n border: '1px solid var(--mzn-color-primary, #0057ff)',\n boxShadow: '0 0 0 3px rgba(0, 87, 255, 0.14)',\n };\n }\n\n if (tone === 'completed') {\n return {\n ...NODE_STYLE,\n border: '1px solid #16a34a',\n };\n }\n\n if (tone === 'cancelled') {\n return {\n ...NODE_STYLE,\n border: '1px solid #dc2626',\n opacity: 0.72,\n };\n }\n\n if (tone === 'waiting') {\n return {\n ...NODE_STYLE,\n border: '1px dashed #64748b',\n };\n }\n\n return NODE_STYLE;\n}\n\nfunction readNodeStatusStyle(tone: RuntimeTone): CSSProperties {\n const baseStyle = NODE_STATUS_STYLE;\n\n if (tone === 'current') {\n return { ...baseStyle, background: '#eff6ff', color: '#2563eb' };\n }\n\n if (tone === 'completed') {\n return { ...baseStyle, background: '#f0fdf4', color: '#15803d' };\n }\n\n if (tone === 'cancelled') {\n return { ...baseStyle, background: '#fef2f2', color: '#dc2626' };\n }\n\n if (tone === 'waiting') {\n return { ...baseStyle, background: '#f8fafc', color: '#475569' };\n }\n\n return { ...baseStyle, background: '#f1f5f9', color: '#64748b' };\n}\n\nfunction readEdgeLabel(edge: WorkflowDefinition['edges'][number]): string {\n if (edge.data.label) {\n return edge.data.label;\n }\n\n if (edge.data.isDefault) {\n return '其他情況';\n }\n\n return edge.data.condition ?? '';\n}\n\nfunction readEdgeSummaries(workflow: WorkflowDefinition): readonly string[] {\n return workflow.edges\n .map(readEdgeLabel)\n .filter((label) => label.trim().length > 0);\n}\n"],"mappings":"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"}