@rytass/bpm-core-react 0.17.6 → 0.17.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/dist/chunks/{FormBuilderView-aBcA-_tt.cjs → FormBuilderView-CUOyS07f.cjs} +2 -2
- package/dist/chunks/{FormBuilderView-aBcA-_tt.cjs.map → FormBuilderView-CUOyS07f.cjs.map} +1 -1
- package/dist/chunks/{FormBuilderView-BYL42M0d.js → FormBuilderView-ClLnQ1e_.js} +2 -2
- package/dist/chunks/{FormBuilderView-BYL42M0d.js.map → FormBuilderView-ClLnQ1e_.js.map} +1 -1
- package/dist/chunks/{FormRendererView-cZGOOjU5.js → FormRendererView-BsTwZkqU.js} +207 -198
- package/dist/chunks/FormRendererView-BsTwZkqU.js.map +1 -0
- package/dist/chunks/FormRendererView-GpsE03np.cjs +4 -0
- package/dist/chunks/FormRendererView-GpsE03np.cjs.map +1 -0
- package/dist/chunks/approver-filled-form-D1DmqDVP.cjs +2 -0
- package/dist/chunks/approver-filled-form-D1DmqDVP.cjs.map +1 -0
- package/dist/chunks/approver-filled-form-DuQGPtNB.js +95 -0
- package/dist/chunks/approver-filled-form-DuQGPtNB.js.map +1 -0
- package/dist/chunks/{compose-DOEaPfEC.cjs → compose-Cock_B2Q.cjs} +2 -2
- package/dist/chunks/{compose-DOEaPfEC.cjs.map → compose-Cock_B2Q.cjs.map} +1 -1
- package/dist/chunks/{compose-v1Vcw9hE.js → compose-jnvnnVfN.js} +4 -4
- package/dist/chunks/{compose-v1Vcw9hE.js.map → compose-jnvnnVfN.js.map} +1 -1
- package/dist/chunks/{designer-DBBrktom.js → designer-B8Gvew_k.js} +1668 -1182
- package/dist/chunks/designer-B8Gvew_k.js.map +1 -0
- package/dist/chunks/designer-CAEFV1ve.cjs +65 -0
- package/dist/chunks/designer-CAEFV1ve.cjs.map +1 -0
- package/dist/chunks/detail-COh5sjAt.cjs +2 -0
- package/dist/chunks/detail-COh5sjAt.cjs.map +1 -0
- package/dist/chunks/detail-D6X61pkg.js +2581 -0
- package/dist/chunks/detail-D6X61pkg.js.map +1 -0
- package/dist/chunks/{providers-H_vPRsSN.js → providers-B_d5tbCL.js} +178 -167
- package/dist/chunks/providers-B_d5tbCL.js.map +1 -0
- package/dist/chunks/providers-chuJvMgv.cjs +2 -0
- package/dist/chunks/providers-chuJvMgv.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.js +1 -1
- package/dist/next/workflow-chat-route.cjs +1 -0
- package/dist/next/workflow-chat-route.cjs.map +1 -1
- package/dist/next/workflow-chat-route.d.cts +1 -1
- package/dist/next/workflow-chat-route.d.ts +1 -1
- package/dist/next/workflow-chat-route.js +1 -1
- package/dist/next/workflow-chat-route.js.map +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/renderer/FormRendererView.d.cts +16 -1
- package/dist/views/forms/renderer/FormRendererView.d.ts +16 -1
- package/dist/views/forms/renderer/index.cjs +1 -1
- package/dist/views/forms/renderer/index.js +1 -1
- package/dist/views/inbox/index.cjs +1 -1
- package/dist/views/inbox/index.cjs.map +1 -1
- package/dist/views/inbox/index.js +109 -99
- package/dist/views/inbox/index.js.map +1 -1
- package/dist/views/instances/approver-filled-form.d.cts +76 -0
- package/dist/views/instances/approver-filled-form.d.ts +76 -0
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +30 -2
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +30 -2
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.cts +4 -1
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +4 -1
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +28 -0
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +28 -0
- package/dist/views/instances/detail/sections/container-helpers.d.cts +1 -1
- package/dist/views/instances/detail/sections/container-helpers.d.ts +1 -1
- package/dist/views/instances/detail/sections/shared.d.cts +11 -2
- package/dist/views/instances/detail/sections/shared.d.ts +11 -2
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.cjs.map +1 -1
- package/dist/views/instances/new/index.js +88 -87
- package/dist/views/instances/new/index.js.map +1 -1
- package/dist/views/instances/viewer-field-access.d.cts +22 -0
- package/dist/views/instances/viewer-field-access.d.ts +22 -0
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.cts +33 -0
- package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.ts +33 -0
- package/dist/views/templates/designer/field-access-matrix/FieldAccessNodeSection.d.cts +20 -0
- package/dist/views/templates/designer/field-access-matrix/FieldAccessNodeSection.d.ts +20 -0
- package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.cts +22 -0
- package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.ts +22 -0
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunks/FormRendererView-DRFi_IH7.cjs +0 -4
- package/dist/chunks/FormRendererView-DRFi_IH7.cjs.map +0 -1
- package/dist/chunks/FormRendererView-cZGOOjU5.js.map +0 -1
- package/dist/chunks/designer-CTXMqCD2.cjs +0 -65
- package/dist/chunks/designer-CTXMqCD2.cjs.map +0 -1
- package/dist/chunks/designer-DBBrktom.js.map +0 -1
- package/dist/chunks/detail-BQSVgVlO.cjs +0 -2
- package/dist/chunks/detail-BQSVgVlO.cjs.map +0 -1
- package/dist/chunks/detail-B_bSg31B.js +0 -2387
- package/dist/chunks/detail-B_bSg31B.js.map +0 -1
- package/dist/chunks/providers-DP7b0TMN.cjs +0 -2
- package/dist/chunks/providers-DP7b0TMN.cjs.map +0 -1
- package/dist/chunks/providers-H_vPRsSN.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/rolldown-runtime-BocRIvOZ.cjs"),t=require("../../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../../chunks/auth-provider-4BeCw7cI.cjs"),r=require("../../../chunks/format-date-time-D-cx5M8z.cjs"),i=require("../../../chunks/routes-config-C1j_vFKo.cjs"),a=require("../../../chunks/FormRendererView-
|
|
1
|
+
"use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/rolldown-runtime-BocRIvOZ.cjs"),t=require("../../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../../chunks/auth-provider-4BeCw7cI.cjs"),r=require("../../../chunks/format-date-time-D-cx5M8z.cjs"),i=require("../../../chunks/routes-config-C1j_vFKo.cjs"),a=require("../../../chunks/approver-filled-form-D1DmqDVP.cjs"),o=require("../../../chunks/FormRendererView-GpsE03np.cjs");let s=require("react"),c=require("@mezzanine-ui/react"),l=require("react/jsx-runtime"),u=require("@rytass/bpm-core-client/workflow"),d=require("@mezzanine-ui/react/ContentHeader");d=e.t(d,1);let f=require("@mezzanine-ui/icons"),p=require("@rytass/bpm-core-client/form");var m={display:`grid`,gap:16};function h(e={}){return(0,l.jsx)(s.Suspense,{fallback:(0,l.jsx)(_,{}),children:(0,l.jsx)(g,{templateId:e.templateId??void 0})})}function g({templateId:e}){let h=t.r(),g=i.r(),{member:_}=n.n(),y=_?.memberId??null,b=e??null,[x,S]=(0,s.useState)(null),[C,w]=(0,s.useState)({}),[T,E]=(0,s.useState)([]),[D,O]=(0,s.useState)(null),[k,A]=(0,s.useState)({}),[j,M]=(0,s.useState)(!0),[N,P]=(0,s.useState)(!1),[F,I]=(0,s.useState)({}),L=(0,s.useMemo)(()=>x?a.n(x.formVersion.schema,x.templateVersion.workflowDefinition):null,[x]),R=(0,s.useCallback)((e,t)=>{I(n=>{let r=n[e];return r?.hasValue===t.hasValue&&r.status===t.status?n:{...n,[e]:{hasValue:t.hasValue,status:t.status}}})},[]);(0,s.useEffect)(()=>{b?U(b):H()},[b]);let z=(0,s.useMemo)(()=>T.map(e=>({...e,key:e.id,updatedAt:r.t(e.updatedAt),versionLabel:`v${e.version}`})),[T]),B=(0,s.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`模板名稱`,width:240},{dataIndex:`versionLabel`,key:`versionLabel`,title:`發布版本`,width:120},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:220}],[]),V=(0,s.useMemo)(()=>({render:e=>[{name:`發起`,onClick:()=>h.push(g.caseNew(e.id)),variant:`base-primary`}],variant:`base-secondary`,width:88}),[h]);async function H(){M(!0),O(null),S(null),I({});try{E(await(0,u.listLaunchableTemplates)())}catch(e){O(v(e))}finally{M(!1)}}async function U(e){M(!0),O(null),E([]),I({});try{S(await(0,u.readLaunchContext)(e))}catch(e){O(v(e))}finally{M(!1)}}async function W(){if(!x||!L||!y)return;P(!0),O(null),A({});let e=o.o(Object.values(F));if(e){O(e),P(!1);return}let t=a.r((0,p.buildFormRendererValues)(L.fields,C),x.templateVersion.workflowDefinition),n=(0,p.validateFormRendererValues)({schema:L,uiSchema:x.formVersion.uiSchema,values:t});if(!n.valid)A(n.errors),O(`請先補齊必填欄位。`),n.firstInvalidFieldKey&&(0,p.focusFormRendererField)(n.firstInvalidFieldKey),P(!1);else try{let e=await(0,u.submitApprovalInstance)({formData:t,initiatorMemberId:y,templateId:x.template.id,title:(0,u.readFormDataCaseTitle)({fallbackTitle:x.template.name,formData:t,schema:L,uiSchema:x.formVersion.uiSchema})});h.push(g.caseDetail(e))}catch(e){O(v(e))}finally{P(!1)}}async function G(e,t){if(!y)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,u.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:x?`${x.template.name} · 表單 v${x.formVersion.version}`:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`,children:x?(0,l.jsx)(c.Button,{disabled:j||N,icon:f.CheckedIcon,iconType:`leading`,onClick:W,variant:`base-primary`,children:`送出`}):null})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsx)(c.Section,{children:(0,l.jsxs)(`div`,{style:m,children:[D?(0,l.jsx)(c.Typography,{color:`text-error`,variant:`body`,children:D}):null,j?(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,x&&L?(0,l.jsx)(o.t,{dataSourceContext:{kind:`runtime`,templateId:x.template.id},errors:k,maxWidth:480,onChange:e=>{w(e),A({})},onDataSourceStateChange:R,onUploadAttachment:G,schema:L,singleColumn:!0,uiSchema:x.formVersion.uiSchema,value:C}):null,!b&&!j?z.length>0?(0,l.jsx)(c.Table,{actions:V,columns:B,dataSource:z,fullWidth:!0}):(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`目前沒有可發起的已發布模板。`}):null]})})})]})}function _(){return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsx)(c.Section,{children:(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`})})})]})}function v(e){return(0,p.readFormDataSourceErrorMessage)(e)||(e instanceof Error?e.message:`發生未知錯誤`)}exports.InstanceNewView=h;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Suspense","useRouterAdapter","useBPMRoutes","useAuth","useState","useCallback","useMemo","formatDateTime","listLaunchableTemplates","readLaunchContext","readFormDataSourceSubmissionBlockMessage","buildFormRendererValues","validateFormRendererValues","submitApprovalInstance","readFormDataCaseTitle","uploadAttachment","_Fragment","PageHeader","ContentHeader","Button","CheckedIcon","SectionGroup","Section","Typography","FormRenderer","Table","readFormDataSourceErrorMessage","require_rolldown_runtime","require_router_adapter","require_auth_provider","require_format_date_time","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","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 validateFormRendererValues,\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 { 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 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 || !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 = buildFormRendererValues(\n context.formVersion.schema.fields,\n formValues,\n );\n const validation = validateFormRendererValues({\n schema: context.formVersion.schema,\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 setSubmitting(false);\n\n return;\n }\n\n try {\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: context.formVersion.schema,\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 ? (\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={context.formVersion.schema}\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","useMemo","readApplicantFormSchema","useCallback","formatDateTime","listLaunchableTemplates","readLaunchContext","readFormDataSourceSubmissionBlockMessage","readApplicantSubmission","buildFormRendererValues","validateFormRendererValues","submitApprovalInstance","readFormDataCaseTitle","uploadAttachment","_Fragment","PageHeader","ContentHeader","Button","CheckedIcon","SectionGroup","Section","Typography","FormRenderer","Table","readFormDataSourceErrorMessage","require_rolldown_runtime","require_router_adapter","require_auth_provider","require_format_date_time","require_routes_config","require_approver_filled_form","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 validateFormRendererValues,\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 const validation = validateFormRendererValues({\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 setSubmitting(false);\n\n return;\n }\n\n try {\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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"}
|
|
@@ -3,28 +3,29 @@ import { r as e } from "../../../chunks/router-adapter-DftlFTOd.js";
|
|
|
3
3
|
import { n as t } from "../../../chunks/auth-provider-B5oPmvk2.js";
|
|
4
4
|
import { t as n } from "../../../chunks/format-date-time-CB-LxzqT.js";
|
|
5
5
|
import { r } from "../../../chunks/routes-config-yZbESPlw.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import w from "@
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
6
|
+
import { n as i, r as a } from "../../../chunks/approver-filled-form-DuQGPtNB.js";
|
|
7
|
+
import { o, t as s } from "../../../chunks/FormRendererView-BsTwZkqU.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, validateFormRendererValues as ne } from "@rytass/bpm-core-client/form";
|
|
14
15
|
//#region src/views/instances/new/InstanceNewView.tsx
|
|
15
|
-
var
|
|
16
|
+
var re = {
|
|
16
17
|
display: "grid",
|
|
17
18
|
gap: 16
|
|
18
19
|
};
|
|
19
|
-
function
|
|
20
|
-
return /* @__PURE__ */
|
|
21
|
-
fallback: /* @__PURE__ */
|
|
22
|
-
children: /* @__PURE__ */
|
|
20
|
+
function A(e = {}) {
|
|
21
|
+
return /* @__PURE__ */ v(c, {
|
|
22
|
+
fallback: /* @__PURE__ */ v(M, {}),
|
|
23
|
+
children: /* @__PURE__ */ v(j, { templateId: e.templateId ?? void 0 })
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
|
-
function
|
|
26
|
-
let
|
|
27
|
-
|
|
26
|
+
function j({ templateId: c }) {
|
|
27
|
+
let k = e(), A = r(), { member: j } = t(), 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 ? i(F.formVersion.schema, F.templateVersion.workflowDefinition) : null, [F]), ie = ee((e, t) => {
|
|
28
|
+
X((n) => {
|
|
28
29
|
let r = n[e];
|
|
29
30
|
return r?.hasValue === t.hasValue && r.status === t.status ? n : {
|
|
30
31
|
...n,
|
|
@@ -35,15 +36,15 @@ function M({ templateId: o }) {
|
|
|
35
36
|
};
|
|
36
37
|
});
|
|
37
38
|
}, []);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}, [
|
|
41
|
-
let
|
|
39
|
+
l(() => {
|
|
40
|
+
P ? se(P) : $();
|
|
41
|
+
}, [P]);
|
|
42
|
+
let Q = u(() => z.map((e) => ({
|
|
42
43
|
...e,
|
|
43
44
|
key: e.id,
|
|
44
45
|
updatedAt: n(e.updatedAt),
|
|
45
46
|
versionLabel: `v${e.version}`
|
|
46
|
-
})), [
|
|
47
|
+
})), [z]), ae = u(() => [
|
|
47
48
|
{
|
|
48
49
|
dataIndex: "name",
|
|
49
50
|
key: "name",
|
|
@@ -62,122 +63,122 @@ function M({ templateId: o }) {
|
|
|
62
63
|
title: "更新時間",
|
|
63
64
|
width: 220
|
|
64
65
|
}
|
|
65
|
-
], []),
|
|
66
|
+
], []), oe = u(() => ({
|
|
66
67
|
render: (e) => [{
|
|
67
68
|
name: "發起",
|
|
68
|
-
onClick: () =>
|
|
69
|
+
onClick: () => k.push(A.caseNew(e.id)),
|
|
69
70
|
variant: "base-primary"
|
|
70
71
|
}],
|
|
71
72
|
variant: "base-secondary",
|
|
72
73
|
width: 88
|
|
73
|
-
}), [
|
|
74
|
-
async function
|
|
75
|
-
|
|
74
|
+
}), [k]);
|
|
75
|
+
async function $() {
|
|
76
|
+
K(!0), H(null), I(null), X({});
|
|
76
77
|
try {
|
|
77
|
-
|
|
78
|
+
B(await b());
|
|
78
79
|
} catch (e) {
|
|
79
|
-
|
|
80
|
+
H(N(e));
|
|
80
81
|
} finally {
|
|
81
|
-
|
|
82
|
+
K(!1);
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
async function
|
|
85
|
-
|
|
85
|
+
async function se(e) {
|
|
86
|
+
K(!0), H(null), B([]), X({});
|
|
86
87
|
try {
|
|
87
|
-
|
|
88
|
+
I(await S(e));
|
|
88
89
|
} catch (e) {
|
|
89
|
-
|
|
90
|
+
H(N(e));
|
|
90
91
|
} finally {
|
|
91
|
-
|
|
92
|
+
K(!1);
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
|
-
async function
|
|
95
|
-
if (!
|
|
96
|
-
|
|
97
|
-
let e =
|
|
95
|
+
async function ce() {
|
|
96
|
+
if (!F || !Z || !M) return;
|
|
97
|
+
J(!0), H(null), W({});
|
|
98
|
+
let e = o(Object.values(Y));
|
|
98
99
|
if (e) {
|
|
99
|
-
|
|
100
|
+
H(e), J(!1);
|
|
100
101
|
return;
|
|
101
102
|
}
|
|
102
|
-
let t =
|
|
103
|
-
schema:
|
|
104
|
-
uiSchema:
|
|
103
|
+
let t = a(D(Z.fields, L), F.templateVersion.workflowDefinition), n = ne({
|
|
104
|
+
schema: Z,
|
|
105
|
+
uiSchema: F.formVersion.uiSchema,
|
|
105
106
|
values: t
|
|
106
107
|
});
|
|
107
|
-
if (!n.valid)
|
|
108
|
+
if (!n.valid) W(n.errors), H("請先補齊必填欄位。"), n.firstInvalidFieldKey && O(n.firstInvalidFieldKey), J(!1);
|
|
108
109
|
else try {
|
|
109
|
-
let e = await
|
|
110
|
+
let e = await C({
|
|
110
111
|
formData: t,
|
|
111
|
-
initiatorMemberId:
|
|
112
|
-
templateId:
|
|
113
|
-
title:
|
|
114
|
-
fallbackTitle:
|
|
112
|
+
initiatorMemberId: M,
|
|
113
|
+
templateId: F.template.id,
|
|
114
|
+
title: x({
|
|
115
|
+
fallbackTitle: F.template.name,
|
|
115
116
|
formData: t,
|
|
116
|
-
schema:
|
|
117
|
-
uiSchema:
|
|
117
|
+
schema: Z,
|
|
118
|
+
uiSchema: F.formVersion.uiSchema
|
|
118
119
|
})
|
|
119
120
|
});
|
|
120
|
-
|
|
121
|
+
k.push(A.caseDetail(e));
|
|
121
122
|
} catch (e) {
|
|
122
|
-
|
|
123
|
+
H(N(e));
|
|
123
124
|
} finally {
|
|
124
|
-
|
|
125
|
+
J(!1);
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
|
-
async function
|
|
128
|
-
if (!
|
|
129
|
-
return { id: (await
|
|
128
|
+
async function le(e, t) {
|
|
129
|
+
if (!M) throw Error("尚未登入,無法上傳附件");
|
|
130
|
+
return { id: (await w({
|
|
130
131
|
file: t,
|
|
131
132
|
formFieldPath: `form.${e.fieldKey}`
|
|
132
133
|
})).id };
|
|
133
134
|
}
|
|
134
|
-
return /* @__PURE__ */
|
|
135
|
-
description:
|
|
135
|
+
return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(p, { children: /* @__PURE__ */ v(T, {
|
|
136
|
+
description: F ? `${F.template.name} · 表單 v${F.formVersion.version}` : "選擇可發起的已發布模板後填寫表單內容。",
|
|
136
137
|
title: "發起簽核",
|
|
137
|
-
children:
|
|
138
|
-
disabled:
|
|
139
|
-
icon:
|
|
138
|
+
children: F ? /* @__PURE__ */ v(f, {
|
|
139
|
+
disabled: G || q,
|
|
140
|
+
icon: E,
|
|
140
141
|
iconType: "leading",
|
|
141
|
-
onClick:
|
|
142
|
+
onClick: ce,
|
|
142
143
|
variant: "base-primary",
|
|
143
144
|
children: "送出"
|
|
144
145
|
}) : null
|
|
145
|
-
}) }), /* @__PURE__ */
|
|
146
|
-
style:
|
|
146
|
+
}) }), /* @__PURE__ */ v(h, { children: /* @__PURE__ */ v(m, { children: /* @__PURE__ */ y("div", {
|
|
147
|
+
style: re,
|
|
147
148
|
children: [
|
|
148
|
-
|
|
149
|
+
V ? /* @__PURE__ */ v(g, {
|
|
149
150
|
color: "text-error",
|
|
150
151
|
variant: "body",
|
|
151
|
-
children:
|
|
152
|
+
children: V
|
|
152
153
|
}) : null,
|
|
153
|
-
|
|
154
|
+
G ? /* @__PURE__ */ v(g, {
|
|
154
155
|
color: "text-neutral",
|
|
155
156
|
variant: "body",
|
|
156
157
|
children: "載入中..."
|
|
157
158
|
}) : null,
|
|
158
|
-
|
|
159
|
+
F && Z ? /* @__PURE__ */ v(s, {
|
|
159
160
|
dataSourceContext: {
|
|
160
161
|
kind: "runtime",
|
|
161
|
-
templateId:
|
|
162
|
+
templateId: F.template.id
|
|
162
163
|
},
|
|
163
|
-
errors:
|
|
164
|
+
errors: U,
|
|
164
165
|
maxWidth: 480,
|
|
165
166
|
onChange: (e) => {
|
|
166
|
-
|
|
167
|
+
R(e), W({});
|
|
167
168
|
},
|
|
168
|
-
onDataSourceStateChange:
|
|
169
|
-
onUploadAttachment:
|
|
170
|
-
schema:
|
|
169
|
+
onDataSourceStateChange: ie,
|
|
170
|
+
onUploadAttachment: le,
|
|
171
|
+
schema: Z,
|
|
171
172
|
singleColumn: !0,
|
|
172
|
-
uiSchema:
|
|
173
|
-
value:
|
|
173
|
+
uiSchema: F.formVersion.uiSchema,
|
|
174
|
+
value: L
|
|
174
175
|
}) : null,
|
|
175
|
-
!
|
|
176
|
-
actions:
|
|
177
|
-
columns:
|
|
178
|
-
dataSource:
|
|
176
|
+
!P && !G ? Q.length > 0 ? /* @__PURE__ */ v(te, {
|
|
177
|
+
actions: oe,
|
|
178
|
+
columns: ae,
|
|
179
|
+
dataSource: Q,
|
|
179
180
|
fullWidth: !0
|
|
180
|
-
}) : /* @__PURE__ */
|
|
181
|
+
}) : /* @__PURE__ */ v(g, {
|
|
181
182
|
color: "text-neutral",
|
|
182
183
|
variant: "body",
|
|
183
184
|
children: "目前沒有可發起的已發布模板。"
|
|
@@ -185,20 +186,20 @@ function M({ templateId: o }) {
|
|
|
185
186
|
]
|
|
186
187
|
}) }) })] });
|
|
187
188
|
}
|
|
188
|
-
function
|
|
189
|
-
return /* @__PURE__ */
|
|
189
|
+
function M() {
|
|
190
|
+
return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(p, { children: /* @__PURE__ */ v(T, {
|
|
190
191
|
description: "選擇可發起的已發布模板後填寫表單內容。",
|
|
191
192
|
title: "發起簽核"
|
|
192
|
-
}) }), /* @__PURE__ */
|
|
193
|
+
}) }), /* @__PURE__ */ v(h, { children: /* @__PURE__ */ v(m, { children: /* @__PURE__ */ v(g, {
|
|
193
194
|
color: "text-neutral",
|
|
194
195
|
variant: "body",
|
|
195
196
|
children: "載入中..."
|
|
196
197
|
}) }) })] });
|
|
197
198
|
}
|
|
198
|
-
function
|
|
199
|
-
return
|
|
199
|
+
function N(e) {
|
|
200
|
+
return k(e) || (e instanceof Error ? e.message : "發生未知錯誤");
|
|
200
201
|
}
|
|
201
202
|
//#endregion
|
|
202
|
-
export {
|
|
203
|
+
export { A as InstanceNewView };
|
|
203
204
|
|
|
204
205
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readFormDataSourceSubmissionBlockMessage","FormRenderer","Fragment$1","ContentHeader","FORM_SECTION_STYLE","InstanceNewView","Suspense","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","useBPMRoutes","currentMemberId","member","templateId","context","setContext","useState","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","handleDataSourceStateChange","useCallback","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","useMemo","template","columns","tableActions","record","listLaunchableTemplates","requestError","readErrorMessage","readLaunchContext","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","buildFormRendererValues","validation","validateFormRendererValues","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 validateFormRendererValues,\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 { 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 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 || !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 = buildFormRendererValues(\n context.formVersion.schema.fields,\n formValues,\n );\n const validation = validateFormRendererValues({\n schema: context.formVersion.schema,\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 setSubmitting(false);\n\n return;\n }\n\n try {\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: context.formVersion.schema,\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 ? (\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={context.formVersion.schema}\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","useRouterAdapter","useAuth","formatDateTime","readApplicantFormSchema","readApplicantSubmission","FormRenderer","Fragment$1","ContentHeader","FORM_SECTION_STYLE","InstanceNewView","Suspense","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","useBPMRoutes","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","readFormDataSourceSubmissionBlockMessage","submittedValues","buildFormRendererValues","validation","validateFormRendererValues","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 validateFormRendererValues,\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 const validation = validateFormRendererValues({\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 setSubmitting(false);\n\n return;\n }\n\n try {\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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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ResolvedFieldAccess } from '@rytass/bpm-core-shared';
|
|
2
|
+
import { ActivityLogRecord, ApprovalInstanceRecord, TaskRecord } from '@rytass/bpm-core-client/workflow';
|
|
3
|
+
/**
|
|
4
|
+
* The nodes that have produced a non-ad-hoc task (docs/08 §8.3): every
|
|
5
|
+
* `TASK_CREATED` whose task is not ad hoc. The task decides, not the log
|
|
6
|
+
* payload — the original task reopened after a refused pre-approval carries an
|
|
7
|
+
* `adhocDirectiveId` too, yet it is the node's own task. A log whose task is
|
|
8
|
+
* not in `tasks` is skipped, since nothing tells whether it was ad hoc.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readRevealedNodeIds(activityLogs: readonly ActivityLogRecord[], tasks: readonly TaskRecord[]): ReadonlySet<string>;
|
|
11
|
+
/**
|
|
12
|
+
* What the viewer may see and edit per top-level form field (ADR 20 §3.3).
|
|
13
|
+
* `actingTask` is the task the viewer may act on now, or `null` for the
|
|
14
|
+
* applicant, an administrator or a closed instance, who get the revealed
|
|
15
|
+
* fields read-only and nothing else editable.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readViewerFieldAccess({ activityLogs, actingTask, instance, tasks, }: {
|
|
18
|
+
readonly activityLogs: readonly ActivityLogRecord[];
|
|
19
|
+
readonly actingTask: TaskRecord | null;
|
|
20
|
+
readonly instance: Pick<ApprovalInstanceRecord, 'formDefinitionSnapshot' | 'workflowSnapshot'>;
|
|
21
|
+
readonly tasks: readonly TaskRecord[];
|
|
22
|
+
}): Readonly<Record<string, ResolvedFieldAccess>>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ResolvedFieldAccess } from '@rytass/bpm-core-shared';
|
|
2
|
+
import { ActivityLogRecord, ApprovalInstanceRecord, TaskRecord } from '@rytass/bpm-core-client/workflow';
|
|
3
|
+
/**
|
|
4
|
+
* The nodes that have produced a non-ad-hoc task (docs/08 §8.3): every
|
|
5
|
+
* `TASK_CREATED` whose task is not ad hoc. The task decides, not the log
|
|
6
|
+
* payload — the original task reopened after a refused pre-approval carries an
|
|
7
|
+
* `adhocDirectiveId` too, yet it is the node's own task. A log whose task is
|
|
8
|
+
* not in `tasks` is skipped, since nothing tells whether it was ad hoc.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readRevealedNodeIds(activityLogs: readonly ActivityLogRecord[], tasks: readonly TaskRecord[]): ReadonlySet<string>;
|
|
11
|
+
/**
|
|
12
|
+
* What the viewer may see and edit per top-level form field (ADR 20 §3.3).
|
|
13
|
+
* `actingTask` is the task the viewer may act on now, or `null` for the
|
|
14
|
+
* applicant, an administrator or a closed instance, who get the revealed
|
|
15
|
+
* fields read-only and nothing else editable.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readViewerFieldAccess({ activityLogs, actingTask, instance, tasks, }: {
|
|
18
|
+
readonly activityLogs: readonly ActivityLogRecord[];
|
|
19
|
+
readonly actingTask: TaskRecord | null;
|
|
20
|
+
readonly instance: Pick<ApprovalInstanceRecord, 'formDefinitionSnapshot' | 'workflowSnapshot'>;
|
|
21
|
+
readonly tasks: readonly TaskRecord[];
|
|
22
|
+
}): Readonly<Record<string, ResolvedFieldAccess>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/compose-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/compose-Cock_B2Q.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-
|
|
1
|
+
export { n as EMPTY_COMPOSE_FORM_SCHEMA, r as EMPTY_COMPOSE_FORM_UI_SCHEMA, t as TemplateComposeWizardView, i as useTemplateComposeWizard } from "../../../chunks/compose-jnvnnVfN.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { FieldAccessChoice, FieldAccessMatrixEntry } from '@rytass/bpm-core-shared';
|
|
3
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
|
|
4
|
+
import { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';
|
|
5
|
+
import { BPMLanguage } from '../../../../lib/language-provider.cjs';
|
|
6
|
+
export interface FieldAccessMatrixDrawerProps {
|
|
7
|
+
readonly definition: WorkflowDefinition;
|
|
8
|
+
readonly formSchema: FormDefinitionSchema | null;
|
|
9
|
+
readonly language: BPMLanguage;
|
|
10
|
+
/**
|
|
11
|
+
* Called with the whole matrix, only when it differs from `definition`.
|
|
12
|
+
* Answers why it could not be applied, or `null` once it was.
|
|
13
|
+
*/
|
|
14
|
+
readonly onApply: (entries: readonly FieldAccessMatrixEntry[]) => string | null;
|
|
15
|
+
readonly onClose: () => void;
|
|
16
|
+
readonly open: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Sets one cell of the draft; `DEFAULT` removes its entry. */
|
|
19
|
+
export declare function updateFieldAccessDraft(entries: readonly FieldAccessMatrixEntry[], nodeId: string, fieldKey: string, choice: FieldAccessChoice): readonly FieldAccessMatrixEntry[];
|
|
20
|
+
/**
|
|
21
|
+
* The cells edited in the drawer (`draft` against `initial`), laid onto the
|
|
22
|
+
* entries the flow holds now. An undo or an assistant edit made while the
|
|
23
|
+
* drawer was open keeps every cell the drawer did not touch, and a node that
|
|
24
|
+
* stopped being a user task meanwhile is dropped.
|
|
25
|
+
*/
|
|
26
|
+
export declare function rebaseFieldAccessDraft(current: readonly FieldAccessMatrixEntry[], initial: readonly FieldAccessMatrixEntry[], draft: readonly FieldAccessMatrixEntry[], userTaskIds: ReadonlySet<string>): readonly FieldAccessMatrixEntry[];
|
|
27
|
+
/**
|
|
28
|
+
* The 欄位與關卡總覽 (ADR 20 §3.3): one row per form field, one column per
|
|
29
|
+
* user task in flow order, edited as a draft and written in one
|
|
30
|
+
* `setFieldAccessMatrix` on 套用. The checks are recomputed from the draft
|
|
31
|
+
* with the publish lint's own rules, so a conflict shows before applying.
|
|
32
|
+
*/
|
|
33
|
+
export declare function FieldAccessMatrixDrawer({ definition, formSchema, language, onApply, onClose, open, }: FieldAccessMatrixDrawerProps): ReactElement;
|