@rytass/bpm-core-react 0.18.1 → 0.20.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 (131) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/chunks/{FormBuilderView-vQfVc08Z.js → FormBuilderView-CFRiw04B.js} +563 -475
  3. package/dist/chunks/FormBuilderView-CFRiw04B.js.map +1 -0
  4. package/dist/chunks/FormBuilderView-CpUgbSbt.cjs +3 -0
  5. package/dist/chunks/FormBuilderView-CpUgbSbt.cjs.map +1 -0
  6. package/dist/chunks/FormRendererView-GfbVWEGa.js +1321 -0
  7. package/dist/chunks/FormRendererView-GfbVWEGa.js.map +1 -0
  8. package/dist/chunks/FormRendererView-lYSaR8CQ.cjs +6 -0
  9. package/dist/chunks/FormRendererView-lYSaR8CQ.cjs.map +1 -0
  10. package/dist/chunks/{compose-DtfX8DQ9.cjs → compose-Bb5bUVFd.cjs} +2 -2
  11. package/dist/chunks/{compose-DtfX8DQ9.cjs.map → compose-Bb5bUVFd.cjs.map} +1 -1
  12. package/dist/chunks/{compose-D9ipJpF_.js → compose-egQlRjuZ.js} +5 -4
  13. package/dist/chunks/{compose-D9ipJpF_.js.map → compose-egQlRjuZ.js.map} +1 -1
  14. package/dist/chunks/{delegations-BfhCDz5e.js → delegations-9-yvWWws.js} +3 -2
  15. package/dist/chunks/delegations-9-yvWWws.js.map +1 -0
  16. package/dist/chunks/delegations-CVmtpkRn.cjs +2 -0
  17. package/dist/chunks/delegations-CVmtpkRn.cjs.map +1 -0
  18. package/dist/chunks/delegations-CrfjsH94.cjs +2 -0
  19. package/dist/chunks/delegations-CrfjsH94.cjs.map +1 -0
  20. package/dist/chunks/{delegations-DBh5TT6G.js → delegations-CxnNvTCc.js} +3 -2
  21. package/dist/chunks/delegations-CxnNvTCc.js.map +1 -0
  22. package/dist/chunks/designer-CX9bhYJS.cjs +69 -0
  23. package/dist/chunks/designer-CX9bhYJS.cjs.map +1 -0
  24. package/dist/chunks/{designer-ubnZbP-A.js → designer-CZDlQ9Nf.js} +2341 -1584
  25. package/dist/chunks/designer-CZDlQ9Nf.js.map +1 -0
  26. package/dist/chunks/{detail-C6XKZjlF.js → detail-ByZV1XaI.js} +853 -840
  27. package/dist/chunks/detail-ByZV1XaI.js.map +1 -0
  28. package/dist/chunks/detail-ChseSF55.cjs +5 -0
  29. package/dist/chunks/detail-ChseSF55.cjs.map +1 -0
  30. package/dist/chunks/{approver-filled-form-B4zPg9kz.cjs → instance-error-message-DTARGbGo.cjs} +2 -2
  31. package/dist/chunks/instance-error-message-DTARGbGo.cjs.map +1 -0
  32. package/dist/chunks/{approver-filled-form-Bgazhbvd.js → instance-error-message-q6gy5evy.js} +44 -36
  33. package/dist/chunks/instance-error-message-q6gy5evy.js.map +1 -0
  34. package/dist/chunks/workflow-chat-prompt-B4wCFKPB.js +25 -0
  35. package/dist/chunks/workflow-chat-prompt-B4wCFKPB.js.map +1 -0
  36. package/dist/chunks/workflow-chat-prompt-B803qVdt.cjs +27 -0
  37. package/dist/chunks/workflow-chat-prompt-B803qVdt.cjs.map +1 -0
  38. package/dist/next/workflow-chat-route.cjs +8 -19
  39. package/dist/next/workflow-chat-route.cjs.map +1 -1
  40. package/dist/next/workflow-chat-route.d.cts +92 -4
  41. package/dist/next/workflow-chat-route.d.ts +92 -4
  42. package/dist/next/workflow-chat-route.js +127 -19
  43. package/dist/next/workflow-chat-route.js.map +1 -1
  44. package/dist/pages/admin/delegations/index.cjs +1 -1
  45. package/dist/pages/admin/delegations/index.js +1 -1
  46. package/dist/pages/delegations/index.cjs +1 -1
  47. package/dist/pages/delegations/index.js +1 -1
  48. package/dist/pages/instances/detail/index.cjs +1 -1
  49. package/dist/pages/instances/detail/index.js +1 -1
  50. package/dist/pages/templates/compose/index.cjs +1 -1
  51. package/dist/pages/templates/compose/index.js +1 -1
  52. package/dist/pages/templates/designer/index.cjs +1 -1
  53. package/dist/pages/templates/designer/index.js +1 -1
  54. package/dist/views/admin/delegations/index.cjs +1 -1
  55. package/dist/views/admin/delegations/index.js +1 -1
  56. package/dist/views/admin/index.cjs +1 -1
  57. package/dist/views/admin/index.js +1 -1
  58. package/dist/views/delegations/index.cjs +1 -1
  59. package/dist/views/delegations/index.js +1 -1
  60. package/dist/views/forms/builder/index.cjs +1 -1
  61. package/dist/views/forms/builder/index.js +1 -1
  62. package/dist/views/forms/renderer/FormRendererView.d.cts +25 -2
  63. package/dist/views/forms/renderer/FormRendererView.d.ts +25 -2
  64. package/dist/views/forms/renderer/file-upload-field.d.cts +84 -0
  65. package/dist/views/forms/renderer/file-upload-field.d.ts +84 -0
  66. package/dist/views/forms/renderer/form-data-source-field.d.cts +9 -1
  67. package/dist/views/forms/renderer/form-data-source-field.d.ts +9 -1
  68. package/dist/views/forms/renderer/form-value-readers.d.cts +7 -0
  69. package/dist/views/forms/renderer/form-value-readers.d.ts +7 -0
  70. package/dist/views/forms/renderer/index.cjs +1 -1
  71. package/dist/views/forms/renderer/index.d.cts +1 -0
  72. package/dist/views/forms/renderer/index.d.ts +1 -0
  73. package/dist/views/forms/renderer/index.js +1 -1
  74. package/dist/views/instances/detail/index.cjs +1 -1
  75. package/dist/views/instances/detail/index.js +1 -1
  76. package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +20 -3
  77. package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +20 -3
  78. package/dist/views/instances/detail/sections/shared.d.cts +1 -2
  79. package/dist/views/instances/detail/sections/shared.d.ts +1 -2
  80. package/dist/views/instances/instance-error-message.d.cts +5 -0
  81. package/dist/views/instances/instance-error-message.d.ts +5 -0
  82. package/dist/views/instances/new/index.cjs +1 -1
  83. package/dist/views/instances/new/index.cjs.map +1 -1
  84. package/dist/views/instances/new/index.js +79 -76
  85. package/dist/views/instances/new/index.js.map +1 -1
  86. package/dist/views/templates/compose/index.cjs +1 -1
  87. package/dist/views/templates/compose/index.js +1 -1
  88. package/dist/views/templates/designer/designer-version-labels.d.cts +7 -0
  89. package/dist/views/templates/designer/designer-version-labels.d.ts +7 -0
  90. package/dist/views/templates/designer/expression/DialectUpgradeModal.d.cts +25 -0
  91. package/dist/views/templates/designer/expression/DialectUpgradeModal.d.ts +25 -0
  92. package/dist/views/templates/designer/expression/ExpressionField.d.cts +79 -0
  93. package/dist/views/templates/designer/expression/ExpressionField.d.ts +79 -0
  94. package/dist/views/templates/designer/expression/use-workflow-expression-references.d.cts +22 -0
  95. package/dist/views/templates/designer/expression/use-workflow-expression-references.d.ts +22 -0
  96. package/dist/views/templates/designer/expression/workflow-expression-edits.d.cts +58 -0
  97. package/dist/views/templates/designer/expression/workflow-expression-edits.d.ts +58 -0
  98. package/dist/views/templates/designer/expression/workflow-expression-tools.d.cts +14 -0
  99. package/dist/views/templates/designer/expression/workflow-expression-tools.d.ts +14 -0
  100. package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.cts +7 -1
  101. package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.ts +7 -1
  102. package/dist/views/templates/designer/index.cjs +1 -1
  103. package/dist/views/templates/designer/index.js +1 -1
  104. package/dist/views/templates/designer/notify-webhook-designer.d.cts +8 -0
  105. package/dist/views/templates/designer/notify-webhook-designer.d.ts +8 -0
  106. package/dist/views/templates/designer/use-workflow-designer-controller.d.cts +8 -2
  107. package/dist/views/templates/designer/use-workflow-designer-controller.d.ts +8 -2
  108. package/dist/views/templates/designer/workflow-chat-prompt.d.cts +18 -0
  109. package/dist/views/templates/designer/workflow-chat-prompt.d.ts +18 -0
  110. package/package.json +3 -3
  111. package/dist/chunks/FormBuilderView-CHaAQL5v.cjs +0 -3
  112. package/dist/chunks/FormBuilderView-CHaAQL5v.cjs.map +0 -1
  113. package/dist/chunks/FormBuilderView-vQfVc08Z.js.map +0 -1
  114. package/dist/chunks/FormRendererView-CTLlG13b.js +0 -1106
  115. package/dist/chunks/FormRendererView-CTLlG13b.js.map +0 -1
  116. package/dist/chunks/FormRendererView-ChmM_4Yc.cjs +0 -4
  117. package/dist/chunks/FormRendererView-ChmM_4Yc.cjs.map +0 -1
  118. package/dist/chunks/approver-filled-form-B4zPg9kz.cjs.map +0 -1
  119. package/dist/chunks/approver-filled-form-Bgazhbvd.js.map +0 -1
  120. package/dist/chunks/delegations-BfhCDz5e.js.map +0 -1
  121. package/dist/chunks/delegations-BmFGcuhA.cjs +0 -2
  122. package/dist/chunks/delegations-BmFGcuhA.cjs.map +0 -1
  123. package/dist/chunks/delegations-CcS0SHbf.cjs +0 -2
  124. package/dist/chunks/delegations-CcS0SHbf.cjs.map +0 -1
  125. package/dist/chunks/delegations-DBh5TT6G.js.map +0 -1
  126. package/dist/chunks/designer-Df79YzUn.cjs +0 -65
  127. package/dist/chunks/designer-Df79YzUn.cjs.map +0 -1
  128. package/dist/chunks/designer-ubnZbP-A.js.map +0 -1
  129. package/dist/chunks/detail-BBC9kqXd.cjs +0 -5
  130. package/dist/chunks/detail-BBC9kqXd.cjs.map +0 -1
  131. package/dist/chunks/detail-C6XKZjlF.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Suspense","useRouterAdapter","useBPMRoutes","useAuth","useState","useMemo","readApplicantFormSchema","useCallback","formatDateTime","listLaunchableTemplates","readLaunchContext","readFormDataSourceSubmissionBlockMessage","readApplicantSubmission","buildFormRendererValues","validateFormRendererValuesInWorker","submitApprovalInstance","readFormDataCaseTitle","uploadAttachment","_Fragment","PageHeader","ContentHeader","Button","CheckedIcon","SectionGroup","Section","Typography","FormRenderer","Table","readFormDataSourceErrorMessage","require_rolldown_runtime","require_approver_filled_form","require_format_date_time","require_auth_provider","require_router_adapter","require_routes_config","require_FormRendererView","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_form","FORM_SECTION_STYLE","InstanceNewView","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","currentMemberId","member","templateId","context","setContext","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","applicantSchema","handleDataSourceStateChange","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","requestError","readErrorMessage","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","validation","instanceId","handleUploadAttachment","field","values"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n readFormDataSourceErrorMessage,\n validateFormRendererValuesInWorker,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n // Inside the `try`, so a validation that throws still clears `submitting`\n // and shows its error instead of leaving the button busy for good.\n try {\n // The format patterns run in a worker under the engine's time budget, so\n // a pattern that backtracks cannot freeze the page.\n const validation = await validateFormRendererValuesInWorker({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先修正表單中標示的欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n return;\n }\n\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(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 return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["Suspense","useRouterAdapter","useBPMRoutes","useAuth","useState","useFileUploadFieldStates","useMemo","readApplicantFormSchema","useCallback","formatDateTime","listLaunchableTemplates","readErrorMessage","readLaunchContext","readFormDataSourceSubmissionBlockMessage","readApplicantSubmission","buildFormRendererValues","validateFormRendererValuesInWorker","submitApprovalInstance","readFormDataCaseTitle","uploadAttachment","_Fragment","PageHeader","ContentHeader","Button","CheckedIcon","SectionGroup","Section","Typography","FormRenderer","Table","require_rolldown_runtime","require_instance_error_message","require_format_date_time","require_auth_provider","require_router_adapter","require_routes_config","require_FormRendererView","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_form","FORM_SECTION_STYLE","InstanceNewView","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","currentMemberId","member","templateId","context","setContext","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","fileUploads","applicantSchema","handleDataSourceStateChange","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","requestError","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","validation","instanceId","handleUploadAttachment","field","values"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n validateFormRendererValuesInWorker,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\nimport { useFileUploadFieldStates } from '../../forms/renderer/file-upload-field';\nimport { readErrorMessage } from '../instance-error-message';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<\n string,\n Pick<FormDataSourceFieldState, 'hasValue' | 'selectionExpired' | 'status'>\n >\n >\n >({});\n const fileUploads = useFileUploadFieldStates();\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'selectionExpired' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.selectionExpired === (state.selectionExpired === true) &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n selectionExpired: state.selectionExpired === true,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // A file still uploading, or one that failed, is listed in its field but\n // is not in the value; submitting now would leave it off the case.\n if (fileUploads.blockMessage) {\n setError(fileUploads.blockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n // Inside the `try`, so a validation that throws still clears `submitting`\n // and shows its error instead of leaving the button busy for good.\n try {\n // The format patterns run in a worker under the engine's time budget, so\n // a pattern that backtracks cannot freeze the page.\n const validation = await validateFormRendererValuesInWorker({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先修正表單中標示的欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n return;\n }\n\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(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 return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onFileUploadStateChange={fileUploads.onFileUploadStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\n"],"mappings":"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"}
@@ -1,50 +1,51 @@
1
1
  "use client";
2
- import { n as e, r as t } from "../../../chunks/approver-filled-form-Bgazhbvd.js";
3
- import { t as n } from "../../../chunks/format-date-time-B0LdmWg4.js";
4
- import { n as r } from "../../../chunks/auth-provider-C2b-5mGt.js";
5
- import { r as i } from "../../../chunks/router-adapter-CkxCyzf5.js";
6
- import { r as a } from "../../../chunks/routes-config-BcNaWJWJ.js";
7
- import { s as o, t as s } from "../../../chunks/FormRendererView-CTLlG13b.js";
8
- import { Suspense as c, useCallback as ee, useEffect as l, useMemo as u, useState as d } from "react";
9
- import { Button as f, PageHeader as p, Section as m, SectionGroup as h, Table as te, Typography as g } from "@mezzanine-ui/react";
10
- import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
11
- import { listLaunchableTemplates as b, readFormDataCaseTitle as x, readLaunchContext as S, submitApprovalInstance as C, uploadAttachment as w } from "@rytass/bpm-core-client/workflow";
12
- import T from "@mezzanine-ui/react/ContentHeader";
13
- import { CheckedIcon as E } from "@mezzanine-ui/icons";
14
- import { buildFormRendererValues as D, focusFormRendererField as O, readFormDataSourceErrorMessage as k, validateFormRendererValuesInWorker as ne } from "@rytass/bpm-core-client/form";
2
+ import { i as e, r as t, t as n } from "../../../chunks/instance-error-message-q6gy5evy.js";
3
+ import { t as r } from "../../../chunks/format-date-time-B0LdmWg4.js";
4
+ import { n as i } from "../../../chunks/auth-provider-C2b-5mGt.js";
5
+ import { r as a } from "../../../chunks/router-adapter-CkxCyzf5.js";
6
+ import { r as o } from "../../../chunks/routes-config-BcNaWJWJ.js";
7
+ import { l as s, o as c, t as l } from "../../../chunks/FormRendererView-GfbVWEGa.js";
8
+ import { Suspense as u, useCallback as d, useEffect as f, useMemo as p, useState as m } from "react";
9
+ import { Button as ee, PageHeader as h, Section as g, SectionGroup as _, Table as v, Typography as y } from "@mezzanine-ui/react";
10
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
11
+ import { listLaunchableTemplates as C, readFormDataCaseTitle as w, readLaunchContext as T, submitApprovalInstance as E, uploadAttachment as D } from "@rytass/bpm-core-client/workflow";
12
+ import O from "@mezzanine-ui/react/ContentHeader";
13
+ import { CheckedIcon as k } from "@mezzanine-ui/icons";
14
+ import { buildFormRendererValues as te, focusFormRendererField as ne, validateFormRendererValuesInWorker as re } from "@rytass/bpm-core-client/form";
15
15
  // src/views/instances/new/InstanceNewView.tsx
16
- var re = {
16
+ var ie = {
17
17
  display: "grid",
18
18
  gap: 16
19
19
  };
20
20
  function A(e = {}) {
21
- return /* @__PURE__ */ v(c, {
22
- fallback: /* @__PURE__ */ v(M, {}),
23
- children: /* @__PURE__ */ v(j, { templateId: e.templateId ?? void 0 })
21
+ return /* @__PURE__ */ x(u, {
22
+ fallback: /* @__PURE__ */ x(M, {}),
23
+ children: /* @__PURE__ */ x(j, { templateId: e.templateId ?? void 0 })
24
24
  });
25
25
  }
26
- function j({ templateId: c }) {
27
- let k = i(), A = a(), { member: j } = r(), M = j?.memberId ?? null, P = c ?? null, [F, I] = d(null), [L, R] = d({}), [z, B] = d([]), [V, H] = d(null), [U, W] = d({}), [G, K] = d(!0), [q, J] = d(!1), [Y, X] = d({}), Z = u(() => F ? e(F.formVersion.schema, F.templateVersion.workflowDefinition) : null, [F]), ie = ee((e, t) => {
28
- X((n) => {
26
+ function j({ templateId: u }) {
27
+ let A = a(), j = o(), { member: M } = i(), N = M?.memberId ?? null, P = u ?? null, [F, I] = m(null), [L, R] = m({}), [z, B] = m([]), [V, H] = m(null), [U, W] = m({}), [G, K] = m(!0), [q, J] = m(!1), [ae, Y] = m({}), X = c(), Z = p(() => F ? t(F.formVersion.schema, F.templateVersion.workflowDefinition) : null, [F]), oe = d((e, t) => {
28
+ Y((n) => {
29
29
  let r = n[e];
30
- return r?.hasValue === t.hasValue && r.status === t.status ? n : {
30
+ return r?.hasValue === t.hasValue && r.selectionExpired === (t.selectionExpired === !0) && r.status === t.status ? n : {
31
31
  ...n,
32
32
  [e]: {
33
33
  hasValue: t.hasValue,
34
+ selectionExpired: t.selectionExpired === !0,
34
35
  status: t.status
35
36
  }
36
37
  };
37
38
  });
38
39
  }, []);
39
- l(() => {
40
- P ? se(P) : $();
40
+ f(() => {
41
+ P ? $(P) : le();
41
42
  }, [P]);
42
- let Q = u(() => z.map((e) => ({
43
+ let Q = p(() => z.map((e) => ({
43
44
  ...e,
44
45
  key: e.id,
45
- updatedAt: n(e.updatedAt),
46
+ updatedAt: r(e.updatedAt),
46
47
  versionLabel: `v${e.version}`
47
- })), [z]), ae = u(() => [
48
+ })), [z]), se = p(() => [
48
49
  {
49
50
  dataIndex: "name",
50
51
  key: "name",
@@ -63,104 +64,108 @@ function j({ templateId: c }) {
63
64
  title: "更新時間",
64
65
  width: 220
65
66
  }
66
- ], []), oe = u(() => ({
67
+ ], []), ce = p(() => ({
67
68
  render: (e) => [{
68
69
  name: "發起",
69
- onClick: () => k.push(A.caseNew(e.id)),
70
+ onClick: () => A.push(j.caseNew(e.id)),
70
71
  variant: "base-primary"
71
72
  }],
72
73
  variant: "base-secondary",
73
74
  width: 88
74
- }), [k]);
75
- async function $() {
76
- K(!0), H(null), I(null), X({});
75
+ }), [A]);
76
+ async function le() {
77
+ K(!0), H(null), I(null), Y({});
77
78
  try {
78
- B(await b());
79
+ B(await C());
79
80
  } catch (e) {
80
- H(N(e));
81
+ H(n(e));
81
82
  } finally {
82
83
  K(!1);
83
84
  }
84
85
  }
85
- async function se(e) {
86
- K(!0), H(null), B([]), X({});
86
+ async function $(e) {
87
+ K(!0), H(null), B([]), Y({});
87
88
  try {
88
- I(await S(e));
89
+ I(await T(e));
89
90
  } catch (e) {
90
- H(N(e));
91
+ H(n(e));
91
92
  } finally {
92
93
  K(!1);
93
94
  }
94
95
  }
95
- async function ce() {
96
- if (!F || !Z || !M) return;
96
+ async function ue() {
97
+ if (!F || !Z || !N) return;
97
98
  J(!0), H(null), W({});
98
- let e = o(Object.values(Y));
99
- if (e) {
100
- H(e), J(!1);
99
+ let t = s(Object.values(ae));
100
+ if (t) {
101
+ H(t), J(!1);
101
102
  return;
102
103
  }
103
- let n = t(D(Z.fields, L), F.templateVersion.workflowDefinition);
104
+ if (X.blockMessage) {
105
+ H(X.blockMessage), J(!1);
106
+ return;
107
+ }
108
+ let r = e(te(Z.fields, L), F.templateVersion.workflowDefinition);
104
109
  try {
105
- let e = await ne({
110
+ let e = await re({
106
111
  schema: Z,
107
112
  uiSchema: F.formVersion.uiSchema,
108
- values: n
113
+ values: r
109
114
  });
110
115
  if (!e.valid) {
111
- W(e.errors), H("請先修正表單中標示的欄位。"), e.firstInvalidFieldKey && O(e.firstInvalidFieldKey);
116
+ W(e.errors), H("請先修正表單中標示的欄位。"), e.firstInvalidFieldKey && ne(e.firstInvalidFieldKey);
112
117
  return;
113
118
  }
114
- let t = await C({
115
- formData: n,
116
- initiatorMemberId: M,
119
+ let t = await E({
120
+ formData: r,
121
+ initiatorMemberId: N,
117
122
  templateId: F.template.id,
118
- title: x({
123
+ title: w({
119
124
  fallbackTitle: F.template.name,
120
- formData: n,
125
+ formData: r,
121
126
  schema: Z,
122
127
  uiSchema: F.formVersion.uiSchema
123
128
  })
124
129
  });
125
- k.push(A.caseDetail(t));
130
+ A.push(j.caseDetail(t));
126
131
  } catch (e) {
127
- H(N(e));
132
+ H(n(e));
128
133
  } finally {
129
134
  J(!1);
130
135
  }
131
136
  }
132
- async function le(e, t) {
133
- if (!M) throw Error("尚未登入,無法上傳附件");
134
- return { id: (await w({
137
+ async function de(e, t) {
138
+ if (!N) throw Error("尚未登入,無法上傳附件");
139
+ return { id: (await D({
135
140
  file: t,
136
141
  formFieldPath: `form.${e.fieldKey}`
137
142
  })).id };
138
143
  }
139
- return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(p, { children: /* @__PURE__ */ v(T, {
144
+ return /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(h, { children: /* @__PURE__ */ x(O, {
140
145
  description: F ? `${F.template.name} · 表單 v${F.formVersion.version}` : "選擇可發起的已發布模板後填寫表單內容。",
141
146
  title: "發起簽核",
142
- children: F ? /* @__PURE__ */ v(f, {
147
+ children: F ? /* @__PURE__ */ x(ee, {
143
148
  disabled: G || q,
144
- icon: E,
149
+ icon: k,
145
150
  iconType: "leading",
146
- onClick: ce,
151
+ onClick: ue,
147
152
  variant: "base-primary",
148
153
  children: "送出"
149
154
  }) : null
150
- }) }), /* @__PURE__ */ v(h, { children: /* @__PURE__ */ v(m, { children: /* @__PURE__ */ y("div", {
151
- style: re,
155
+ }) }), /* @__PURE__ */ x(_, { children: /* @__PURE__ */ x(g, { children: /* @__PURE__ */ S("div", {
156
+ style: ie,
152
157
  children: [
153
- V ? /* @__PURE__ */ v(g, {
158
+ V ? /* @__PURE__ */ x(y, {
154
159
  color: "text-error",
155
160
  variant: "body",
156
161
  children: V
157
162
  }) : null,
158
- G ? /* @__PURE__ */ v(g, {
163
+ G ? /* @__PURE__ */ x(y, {
159
164
  color: "text-neutral",
160
165
  variant: "body",
161
166
  children: "載入中..."
162
167
  }) : null,
163
- F && Z ? /* @__PURE__ */ v(s, {
168
+ F && Z ? /* @__PURE__ */ x(l, {
164
169
  dataSourceContext: {
165
170
  kind: "runtime",
166
171
  templateId: F.template.id
@@ -170,19 +175,20 @@ function j({ templateId: c }) {
170
175
  onChange: (e) => {
171
176
  R(e), W({});
172
177
  },
173
- onDataSourceStateChange: ie,
174
- onUploadAttachment: le,
178
+ onDataSourceStateChange: oe,
179
+ onFileUploadStateChange: X.onFileUploadStateChange,
180
+ onUploadAttachment: de,
175
181
  schema: Z,
176
182
  singleColumn: !0,
177
183
  uiSchema: F.formVersion.uiSchema,
178
184
  value: L
179
185
  }) : null,
180
- !P && !G ? Q.length > 0 ? /* @__PURE__ */ v(te, {
181
- actions: oe,
182
- columns: ae,
186
+ !P && !G ? Q.length > 0 ? /* @__PURE__ */ x(v, {
187
+ actions: ce,
188
+ columns: se,
183
189
  dataSource: Q,
184
190
  fullWidth: !0
185
- }) : /* @__PURE__ */ v(g, {
191
+ }) : /* @__PURE__ */ x(y, {
186
192
  color: "text-neutral",
187
193
  variant: "body",
188
194
  children: "目前沒有可發起的已發布模板。"
@@ -191,18 +197,15 @@ function j({ templateId: c }) {
191
197
  }) }) })] });
192
198
  }
193
199
  function M() {
194
- return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(p, { children: /* @__PURE__ */ v(T, {
200
+ return /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(h, { children: /* @__PURE__ */ x(O, {
195
201
  description: "選擇可發起的已發布模板後填寫表單內容。",
196
202
  title: "發起簽核"
197
- }) }), /* @__PURE__ */ v(h, { children: /* @__PURE__ */ v(m, { children: /* @__PURE__ */ v(g, {
203
+ }) }), /* @__PURE__ */ x(_, { children: /* @__PURE__ */ x(g, { children: /* @__PURE__ */ x(y, {
198
204
  color: "text-neutral",
199
205
  variant: "body",
200
206
  children: "載入中..."
201
207
  }) }) })] });
202
208
  }
203
- function N(e) {
204
- return k(e) || (e instanceof Error ? e.message : "發生未知錯誤");
205
- }
206
209
  export { A as InstanceNewView };
207
210
 
208
211
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_Fragment","readApplicantFormSchema","readApplicantSubmission","formatDateTime","useAuth","useRouterAdapter","useBPMRoutes","readFormDataSourceSubmissionBlockMessage","FormRenderer","Fragment$1","ContentHeader","FORM_SECTION_STYLE","InstanceNewView","Suspense","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","currentMemberId","member","templateId","context","setContext","useState","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","applicantSchema","useMemo","handleDataSourceStateChange","useCallback","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","listLaunchableTemplates","requestError","readErrorMessage","readLaunchContext","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","buildFormRendererValues","validation","validateFormRendererValuesInWorker","focusFormRendererField","instanceId","submitApprovalInstance","readFormDataCaseTitle","handleUploadAttachment","uploadAttachment","field","PageHeader","Button","CheckedIcon","SectionGroup","Section","Typography","values","Table","readFormDataSourceErrorMessage"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n readFormDataSourceErrorMessage,\n validateFormRendererValuesInWorker,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n // Inside the `try`, so a validation that throws still clears `submitting`\n // and shows its error instead of leaving the button busy for good.\n try {\n // The format patterns run in a worker under the engine's time budget, so\n // a pattern that backtracks cannot freeze the page.\n const validation = await validateFormRendererValuesInWorker({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先修正表單中標示的欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n return;\n }\n\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(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 return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["_Fragment","readApplicantSubmission","readApplicantFormSchema","readErrorMessage","formatDateTime","useAuth","useRouterAdapter","useBPMRoutes","readFormDataSourceSubmissionBlockMessage","useFileUploadFieldStates","FormRenderer","Fragment$1","ContentHeader","FORM_SECTION_STYLE","InstanceNewView","Suspense","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","currentMemberId","member","templateId","context","setContext","useState","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","fileUploads","applicantSchema","useMemo","handleDataSourceStateChange","useCallback","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","listLaunchableTemplates","requestError","readLaunchContext","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","buildFormRendererValues","validation","validateFormRendererValuesInWorker","focusFormRendererField","instanceId","submitApprovalInstance","readFormDataCaseTitle","handleUploadAttachment","uploadAttachment","field","PageHeader","Button","CheckedIcon","SectionGroup","Section","Typography","values","Table"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n validateFormRendererValuesInWorker,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\nimport { useFileUploadFieldStates } from '../../forms/renderer/file-upload-field';\nimport { readErrorMessage } from '../instance-error-message';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<\n string,\n Pick<FormDataSourceFieldState, 'hasValue' | 'selectionExpired' | 'status'>\n >\n >\n >({});\n const fileUploads = useFileUploadFieldStates();\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'selectionExpired' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.selectionExpired === (state.selectionExpired === true) &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n selectionExpired: state.selectionExpired === true,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // A file still uploading, or one that failed, is listed in its field but\n // is not in the value; submitting now would leave it off the case.\n if (fileUploads.blockMessage) {\n setError(fileUploads.blockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n // Inside the `try`, so a validation that throws still clears `submitting`\n // and shows its error instead of leaving the button busy for good.\n try {\n // The format patterns run in a worker under the engine's time budget, so\n // a pattern that backtracks cannot freeze the page.\n const validation = await validateFormRendererValuesInWorker({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先修正表單中標示的欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n return;\n }\n\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(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 return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onFileUploadStateChange={fileUploads.onFileUploadStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\n"],"mappings":"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"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/compose-DtfX8DQ9.cjs");exports.EMPTY_COMPOSE_FORM_SCHEMA=e.n,exports.EMPTY_COMPOSE_FORM_UI_SCHEMA=e.r,exports.TemplateComposeWizardView=e.t,exports.useTemplateComposeWizard=e.i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/compose-Bb5bUVFd.cjs");exports.EMPTY_COMPOSE_FORM_SCHEMA=e.n,exports.EMPTY_COMPOSE_FORM_UI_SCHEMA=e.r,exports.TemplateComposeWizardView=e.t,exports.useTemplateComposeWizard=e.i;
@@ -1 +1 @@
1
- export { n as EMPTY_COMPOSE_FORM_SCHEMA, r as EMPTY_COMPOSE_FORM_UI_SCHEMA, t as TemplateComposeWizardView, i as useTemplateComposeWizard } from "../../../chunks/compose-D9ipJpF_.js";
1
+ export { n as EMPTY_COMPOSE_FORM_SCHEMA, r as EMPTY_COMPOSE_FORM_UI_SCHEMA, t as TemplateComposeWizardView, i as useTemplateComposeWizard } from "../../../chunks/compose-egQlRjuZ.js";
@@ -8,5 +8,12 @@ export declare function readTemplateVersionDescription(input: {
8
8
  hasPublishedVersion: boolean;
9
9
  publishedVersion: number | null;
10
10
  }): string;
11
+ /**
12
+ * The designer header's description line: the version line plus the
13
+ * definition's expression dialect. `ContentHeader` drops any child that is not
14
+ * a button, filter or back link, so a dialect `Tag` there never rendered; its
15
+ * `description` string is the slot it does show.
16
+ */
17
+ export declare function readTemplateHeaderDescription(versionDescription: string, expressionDialect: string): string;
11
18
  /** The bound form's version, labelled so it is not mistaken for the template's. */
12
19
  export declare function readFormVersionLabel(formName: string, version: number): string;
@@ -8,5 +8,12 @@ export declare function readTemplateVersionDescription(input: {
8
8
  hasPublishedVersion: boolean;
9
9
  publishedVersion: number | null;
10
10
  }): string;
11
+ /**
12
+ * The designer header's description line: the version line plus the
13
+ * definition's expression dialect. `ContentHeader` drops any child that is not
14
+ * a button, filter or back link, so a dialect `Tag` there never rendered; its
15
+ * `description` string is the slot it does show.
16
+ */
17
+ export declare function readTemplateHeaderDescription(versionDescription: string, expressionDialect: string): string;
11
18
  /** The bound form's version, labelled so it is not mistaken for the template's. */
12
19
  export declare function readFormVersionLabel(formName: string, version: number): string;
@@ -0,0 +1,25 @@
1
+ import { ReactElement } from 'react';
2
+ import { WorkflowDialectUpgradePreviewRecord, WorkflowExpressionsDraft } from '@rytass/bpm-core-client/template';
3
+ export interface DialectUpgradeModalProps {
4
+ /** The draft to check: the designer's current state, saved or not. */
5
+ readonly draft: WorkflowExpressionsDraft;
6
+ readonly onCancel: () => void;
7
+ /** The user confirmed; the host switches the draft to cel-v2. */
8
+ readonly onConfirm: () => void;
9
+ readonly open: boolean;
10
+ /** Injectable for tests and Storybook. */
11
+ readonly preview?: (draft: WorkflowExpressionsDraft) => Promise<WorkflowDialectUpgradePreviewRecord>;
12
+ }
13
+ /** `ok:<json>` / `err:<code>` as the designer reads it. */
14
+ export declare function readDialectOutcomeText(outcome: string): string;
15
+ /** Whether the check lets the user upgrade on it. */
16
+ export declare function canConfirmDialectUpgrade(result: WorkflowDialectUpgradePreviewRecord | null): boolean;
17
+ /**
18
+ * The whole-draft dialect upgrade (Phase 23 P4, docs/24 §1): before a draft
19
+ * moves from cel-legacy to cel-v2 the backend runs every expression under
20
+ * both engines on sample data and lists where the answers differ, e.g.
21
+ * `7 / 2` is 3.5 on legacy and an integer division on cel-v2. Nothing is
22
+ * changed here; confirming hands the decision back to the designer, which
23
+ * sets the dialect on the draft and saves it the usual way.
24
+ */
25
+ export declare function DialectUpgradeModal({ draft, onCancel, onConfirm, open, preview, }: DialectUpgradeModalProps): ReactElement;
@@ -0,0 +1,25 @@
1
+ import { ReactElement } from 'react';
2
+ import { WorkflowDialectUpgradePreviewRecord, WorkflowExpressionsDraft } from '@rytass/bpm-core-client/template';
3
+ export interface DialectUpgradeModalProps {
4
+ /** The draft to check: the designer's current state, saved or not. */
5
+ readonly draft: WorkflowExpressionsDraft;
6
+ readonly onCancel: () => void;
7
+ /** The user confirmed; the host switches the draft to cel-v2. */
8
+ readonly onConfirm: () => void;
9
+ readonly open: boolean;
10
+ /** Injectable for tests and Storybook. */
11
+ readonly preview?: (draft: WorkflowExpressionsDraft) => Promise<WorkflowDialectUpgradePreviewRecord>;
12
+ }
13
+ /** `ok:<json>` / `err:<code>` as the designer reads it. */
14
+ export declare function readDialectOutcomeText(outcome: string): string;
15
+ /** Whether the check lets the user upgrade on it. */
16
+ export declare function canConfirmDialectUpgrade(result: WorkflowDialectUpgradePreviewRecord | null): boolean;
17
+ /**
18
+ * The whole-draft dialect upgrade (Phase 23 P4, docs/24 §1): before a draft
19
+ * moves from cel-legacy to cel-v2 the backend runs every expression under
20
+ * both engines on sample data and lists where the answers differ, e.g.
21
+ * `7 / 2` is 3.5 on legacy and an integer division on cel-v2. Nothing is
22
+ * changed here; confirming hands the decision back to the designer, which
23
+ * sets the dialect on the draft and saves it the usual way.
24
+ */
25
+ export declare function DialectUpgradeModal({ draft, onCancel, onConfirm, open, preview, }: DialectUpgradeModalProps): ReactElement;