@rytass/bpm-core-react 0.20.1 → 0.21.1
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 +80 -0
- package/README.md +1 -1
- package/dist/approval-instance-list-page.css +1 -1
- package/dist/chunks/{FormBuilderView-CFRiw04B.js → FormBuilderView-6KdApi-D.js} +667 -584
- package/dist/chunks/FormBuilderView-6KdApi-D.js.map +1 -0
- package/dist/chunks/FormBuilderView-CGKkuVFi.cjs +4 -0
- package/dist/chunks/FormBuilderView-CGKkuVFi.cjs.map +1 -0
- package/dist/chunks/{FormRendererView-lYSaR8CQ.cjs → FormRendererView-B-xycC9S.cjs} +3 -3
- package/dist/chunks/{FormRendererView-lYSaR8CQ.cjs.map → FormRendererView-B-xycC9S.cjs.map} +1 -1
- package/dist/chunks/{FormRendererView-GfbVWEGa.js → FormRendererView-BcQKUi1A.js} +238 -238
- package/dist/chunks/{FormRendererView-GfbVWEGa.js.map → FormRendererView-BcQKUi1A.js.map} +1 -1
- package/dist/chunks/approval-instance-list-page-BI5fIXc-.js +724 -0
- package/dist/chunks/approval-instance-list-page-BI5fIXc-.js.map +1 -0
- package/dist/chunks/approval-instance-list-page-Cv5I1YPX.cjs +2 -0
- package/dist/chunks/approval-instance-list-page-Cv5I1YPX.cjs.map +1 -0
- package/dist/chunks/{categories-DQUtVEiV.cjs → categories-CyyqG6wG.cjs} +2 -2
- package/dist/chunks/{categories-DQUtVEiV.cjs.map → categories-CyyqG6wG.cjs.map} +1 -1
- package/dist/chunks/{categories-BAdxjNSA.js → categories-f7E-RJEc.js} +9 -9
- package/dist/chunks/{categories-BAdxjNSA.js.map → categories-f7E-RJEc.js.map} +1 -1
- package/dist/chunks/{compose-egQlRjuZ.js → compose-DFuLPmOA.js} +5 -5
- package/dist/chunks/{compose-egQlRjuZ.js.map → compose-DFuLPmOA.js.map} +1 -1
- package/dist/chunks/compose-DK3ocWwG.cjs +2 -0
- package/dist/chunks/compose-DK3ocWwG.cjs.map +1 -0
- package/dist/chunks/{delegations-CVmtpkRn.cjs → delegations-ClRCwD1I.cjs} +2 -2
- package/dist/chunks/{delegations-CVmtpkRn.cjs.map → delegations-ClRCwD1I.cjs.map} +1 -1
- package/dist/chunks/{delegations-9-yvWWws.js → delegations-CqND-Qtz.js} +5 -5
- package/dist/chunks/{delegations-9-yvWWws.js.map → delegations-CqND-Qtz.js.map} +1 -1
- package/dist/chunks/{delegations-CrfjsH94.cjs → delegations-D43VDSz1.cjs} +2 -2
- package/dist/chunks/{delegations-CrfjsH94.cjs.map → delegations-D43VDSz1.cjs.map} +1 -1
- package/dist/chunks/{delegations-CxnNvTCc.js → delegations-zisffLwk.js} +5 -5
- package/dist/chunks/{delegations-CxnNvTCc.js.map → delegations-zisffLwk.js.map} +1 -1
- package/dist/chunks/designer-CAUWEKJ4.cjs +69 -0
- package/dist/chunks/designer-CAUWEKJ4.cjs.map +1 -0
- package/dist/chunks/{designer-CZDlQ9Nf.js → designer-CCy5EbOe.js} +2380 -1786
- package/dist/chunks/designer-CCy5EbOe.js.map +1 -0
- package/dist/chunks/detail-C5KrUC7s.cjs +5 -0
- package/dist/chunks/detail-C5KrUC7s.cjs.map +1 -0
- package/dist/chunks/{detail-ByZV1XaI.js → detail-Dnc4PPWO.js} +804 -777
- package/dist/chunks/detail-Dnc4PPWO.js.map +1 -0
- package/dist/chunks/instance-error-message-BEM4O_Kj.js +208 -0
- package/dist/chunks/instance-error-message-BEM4O_Kj.js.map +1 -0
- package/dist/chunks/instance-error-message-BpCLCOjp.cjs +2 -0
- package/dist/chunks/instance-error-message-BpCLCOjp.cjs.map +1 -0
- package/dist/chunks/organization-time-zone-provider-B7CXQril.cjs +2 -0
- package/dist/chunks/organization-time-zone-provider-B7CXQril.cjs.map +1 -0
- package/dist/chunks/organization-time-zone-provider-DNL8yo4-.js +42 -0
- package/dist/chunks/organization-time-zone-provider-DNL8yo4-.js.map +1 -0
- package/dist/chunks/{providers-BbCs23sk.js → providers-CQWekD7_.js} +197 -196
- package/dist/chunks/providers-CQWekD7_.js.map +1 -0
- package/dist/chunks/providers-VUOh6i0i.cjs +2 -0
- package/dist/chunks/providers-VUOh6i0i.cjs.map +1 -0
- package/dist/components/approval-instance-field-filter-controls.d.cts +12 -0
- package/dist/components/approval-instance-field-filter-controls.d.ts +12 -0
- package/dist/components/approval-instance-field-filters.d.cts +86 -0
- package/dist/components/approval-instance-field-filters.d.ts +86 -0
- package/dist/components/approval-instance-list-page.d.cts +4 -0
- package/dist/components/approval-instance-list-page.d.ts +4 -0
- package/dist/components/notification-drawer-options.d.cts +18 -0
- package/dist/components/notification-drawer-options.d.ts +18 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +23 -23
- package/dist/index.js.map +1 -1
- package/dist/lib/organization-time-zone-provider.d.cts +20 -0
- package/dist/lib/organization-time-zone-provider.d.ts +20 -0
- package/dist/lib/organization-time-zone.d.cts +8 -0
- package/dist/lib/organization-time-zone.d.ts +8 -0
- package/dist/lib/providers.d.cts +10 -1
- package/dist/lib/providers.d.ts +10 -1
- package/dist/next/BPMNextProviders.d.cts +8 -1
- package/dist/next/BPMNextProviders.d.ts +8 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.js +12 -11
- package/dist/next/index.js.map +1 -1
- package/dist/next/workflow-chat-route.cjs +2 -2
- package/dist/next/workflow-chat-route.cjs.map +1 -1
- package/dist/next/workflow-chat-route.js +13 -13
- package/dist/pages/admin/delegations/index.cjs +1 -1
- package/dist/pages/admin/delegations/index.js +1 -1
- package/dist/pages/delegations/index.cjs +1 -1
- package/dist/pages/delegations/index.js +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/templates/categories/index.cjs +1 -1
- package/dist/pages/templates/categories/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/admin/delegations/index.cjs +1 -1
- package/dist/views/admin/delegations/index.js +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.js +1 -1
- package/dist/views/admin/webhook-endpoints/index.cjs +1 -1
- package/dist/views/admin/webhook-endpoints/index.cjs.map +1 -1
- package/dist/views/admin/webhook-endpoints/index.js +60 -60
- package/dist/views/admin/webhook-endpoints/index.js.map +1 -1
- package/dist/views/cc/index.cjs +1 -1
- package/dist/views/cc/index.js +1 -1
- package/dist/views/delegations/index.cjs +1 -1
- package/dist/views/delegations/index.js +1 -1
- package/dist/views/forms/builder/FormBuilderView.d.cts +8 -1
- package/dist/views/forms/builder/FormBuilderView.d.ts +8 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/renderer/index.cjs +1 -1
- package/dist/views/forms/renderer/index.js +1 -1
- package/dist/views/instances/approver-filled-form.d.cts +8 -5
- package/dist/views/instances/approver-filled-form.d.ts +8 -5
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +2 -1
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +2 -1
- package/dist/views/instances/detail/sections/shared.d.cts +0 -1
- package/dist/views/instances/detail/sections/shared.d.ts +0 -1
- 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 +8 -8
- package/dist/views/instances/new/index.js.map +1 -1
- package/dist/views/search/index.cjs +1 -1
- package/dist/views/search/index.js +1 -1
- package/dist/views/sent/index.cjs +1 -1
- package/dist/views/sent/index.js +1 -1
- package/dist/views/templates/categories/index.cjs +1 -1
- package/dist/views/templates/categories/index.js +1 -1
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/designer/NotifyWebhookTargetsEditor.d.cts +2 -0
- package/dist/views/templates/designer/NotifyWebhookTargetsEditor.d.ts +2 -0
- package/dist/views/templates/designer/approver-resolver-model.d.cts +105 -1
- package/dist/views/templates/designer/approver-resolver-model.d.ts +105 -1
- package/dist/views/templates/designer/dynamic-form-resolver-options.d.cts +5 -0
- package/dist/views/templates/designer/dynamic-form-resolver-options.d.ts +5 -0
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/dist/views/templates/designer/node-actor-resolver-options.d.cts +44 -1
- package/dist/views/templates/designer/node-actor-resolver-options.d.ts +44 -1
- package/dist/views/templates/designer/notify-recipient-options.d.cts +81 -0
- package/dist/views/templates/designer/notify-recipient-options.d.ts +81 -0
- package/dist/views/templates/designer/position-level-options.d.cts +3 -1
- package/dist/views/templates/designer/position-level-options.d.ts +3 -1
- package/dist/views/templates/designer/position-scope.d.cts +51 -0
- package/dist/views/templates/designer/position-scope.d.ts +51 -0
- package/dist/views/templates/index.cjs +1 -1
- package/dist/views/templates/index.cjs.map +1 -1
- package/dist/views/templates/index.js +7 -7
- package/package.json +3 -3
- package/dist/chunks/FormBuilderView-CFRiw04B.js.map +0 -1
- package/dist/chunks/FormBuilderView-CpUgbSbt.cjs +0 -3
- package/dist/chunks/FormBuilderView-CpUgbSbt.cjs.map +0 -1
- package/dist/chunks/approval-instance-list-page-BnI4t5mD.js +0 -279
- package/dist/chunks/approval-instance-list-page-BnI4t5mD.js.map +0 -1
- package/dist/chunks/approval-instance-list-page-fqvmkBlg.cjs +0 -2
- package/dist/chunks/approval-instance-list-page-fqvmkBlg.cjs.map +0 -1
- package/dist/chunks/compose-Bb5bUVFd.cjs +0 -2
- package/dist/chunks/compose-Bb5bUVFd.cjs.map +0 -1
- package/dist/chunks/designer-CX9bhYJS.cjs +0 -69
- package/dist/chunks/designer-CX9bhYJS.cjs.map +0 -1
- package/dist/chunks/designer-CZDlQ9Nf.js.map +0 -1
- package/dist/chunks/detail-ByZV1XaI.js.map +0 -1
- package/dist/chunks/detail-ChseSF55.cjs +0 -5
- package/dist/chunks/detail-ChseSF55.cjs.map +0 -1
- package/dist/chunks/instance-error-message-DTARGbGo.cjs +0 -2
- package/dist/chunks/instance-error-message-DTARGbGo.cjs.map +0 -1
- package/dist/chunks/instance-error-message-q6gy5evy.js +0 -120
- package/dist/chunks/instance-error-message-q6gy5evy.js.map +0 -1
- package/dist/chunks/language-provider-Bdnx3Gxl.cjs +0 -2
- package/dist/chunks/language-provider-Bdnx3Gxl.cjs.map +0 -1
- package/dist/chunks/language-provider-phkWOapf.js +0 -17
- package/dist/chunks/language-provider-phkWOapf.js.map +0 -1
- package/dist/chunks/providers-BbCs23sk.js.map +0 -1
- package/dist/chunks/providers-D_KAgOOu.cjs +0 -2
- package/dist/chunks/providers-D_KAgOOu.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories-BAdxjNSA.js","names":["_Fragment","styles","BPMFormField","Fragment$1","ContentHeader","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","useState","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","useCallback","categoryPageResult","listApprovalTemplateCategoriesPage","readCategoryStatus","requestError","readErrorMessage","rows","useMemo","category","formatDateTime","columns","CategoryStatusBadge","record","Typography","handleSaveCategory","updateApprovalTemplateCategory","input","createApprovalTemplateCategory","handleToggleCategory","handleConfirmDelete","deleteApprovalTemplateCategory","tableActions","PageHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","Tab","readCategoryStatusTabKey","activeKey","TabItem","statusTab","Table","page","pageSize","from","to","total","CategoryModal","Modal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","Textarea","isActive","Badge","status"],"sources":["../../src/views/templates/templates.module.scss","../../src/views/templates/categories/TemplateCategoriesView.tsx"],"sourcesContent":[".templateFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n\n.templateModalFields {\n display: grid;\n gap: 16px;\n}\n","'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport {\n ApprovalTemplateCategoryRecord,\n ApprovalTemplateCategoryStatus,\n createApprovalTemplateCategory,\n deleteApprovalTemplateCategory,\n listApprovalTemplateCategoriesPage,\n updateApprovalTemplateCategory,\n} from '@rytass/bpm-core-client/template';\nimport styles from '../templates.module.scss';\n\nconst CATEGORY_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst CATEGORY_STATUS_TABS: readonly {\n readonly key: CategoryStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'ACTIVE', label: '啟用' },\n { key: 'INACTIVE', label: '停用' },\n];\ntype CategoryStatusTabKey = 'ACTIVE' | 'ALL' | 'INACTIVE';\n\ntype CategoryRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateCategoryRecord & {\n key: string;\n updatedAtLabel: string;\n }\n>;\n\ntype CategoryModalState = Readonly<{\n record: ApprovalTemplateCategoryRecord | null;\n type: 'CREATE' | 'EDIT';\n}>;\n\ntype DeleteConfirmationState = Readonly<{\n id: string;\n name: string;\n}>;\n\n\nexport function TemplateCategoriesView(): ReactElement {\n const [categories, setCategories] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n const [categoryPage, setCategoryPage] = useState(1);\n const [categoryPageSize, setCategoryPageSize] = useState(10);\n const [categoryStatus, setCategoryStatus] =\n useState<CategoryStatusTabKey>('ALL');\n const [categoryTotalCount, setCategoryTotalCount] = useState(0);\n const [deleteConfirmation, setDeleteConfirmation] =\n useState<DeleteConfirmationState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [modalState, setModalState] = useState<CategoryModalState | null>(null);\n const [saving, setSaving] = useState(false);\n const [searchText, setSearchText] = useState('');\n\n const refreshCategories = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const categoryPageResult = await listApprovalTemplateCategoriesPage({\n page: categoryPage,\n pageSize: categoryPageSize,\n searchText,\n status: readCategoryStatus(categoryStatus),\n });\n\n setCategories(categoryPageResult.categories);\n setCategoryTotalCount(categoryPageResult.totalCount);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [categoryPage, categoryPageSize, categoryStatus, searchText]);\n\n useEffect((): void => {\n void refreshCategories();\n }, [refreshCategories]);\n\n const rows = useMemo(\n (): CategoryRow[] =>\n categories.map((category) => ({\n ...category,\n key: category.id,\n updatedAtLabel: formatDateTime(category.updatedAt),\n })),\n [categories],\n );\n\n const columns = useMemo(\n (): TableColumn<CategoryRow>[] => [\n { dataIndex: 'name', key: 'name', title: '分類名稱', width: 180 },\n {\n key: 'status',\n render: (record: CategoryRow): ReactElement => (\n <CategoryStatusBadge isActive={record.isActive} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n dataIndex: 'sortOrder',\n key: 'sortOrder',\n title: '排序',\n width: 100,\n },\n {\n key: 'description',\n render: (record: CategoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.description || '無'}\n </Typography>\n ),\n title: '說明',\n width: 260,\n },\n {\n dataIndex: 'updatedAtLabel',\n key: 'updatedAtLabel',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function handleSaveCategory(input: CategoryFormInput): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n if (modalState?.type === 'EDIT' && modalState.record) {\n await updateApprovalTemplateCategory({\n ...input,\n id: modalState.record.id,\n });\n } else {\n await createApprovalTemplateCategory(input);\n }\n\n setModalState(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n throw requestError;\n } finally {\n setSaving(false);\n }\n }\n\n async function handleToggleCategory(\n record: ApprovalTemplateCategoryRecord,\n ): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n await updateApprovalTemplateCategory({\n description: record.description,\n id: record.id,\n isActive: !record.isActive,\n name: record.name,\n sortOrder: record.sortOrder,\n });\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handleConfirmDelete(): Promise<void> {\n if (!deleteConfirmation) {\n return;\n }\n\n setSaving(true);\n setError(null);\n\n try {\n await deleteApprovalTemplateCategory(deleteConfirmation.id);\n setDeleteConfirmation(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n const tableActions = useMemo(\n (): TableActions<CategoryRow> => ({\n render: (record): ReturnType<TableActions<CategoryRow>['render']> => [\n {\n name: '編輯',\n onClick: (): void => setModalState({ record, type: 'EDIT' }),\n },\n {\n name: record.isActive ? '停用' : '啟用',\n onClick: (): void => void handleToggleCategory(record),\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n {\n name: '刪除',\n onClick: (): void =>\n setDeleteConfirmation({ id: record.id, name: record.name }),\n variant: 'destructive-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [refreshCategories],\n );\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"維護簽核模板分類,供模板建立、篩選與列表標示使用。\"\n title=\"簽核模板分類\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n setModalState({ record: null, type: 'CREATE' })\n }\n variant=\"base-primary\"\n >\n 建立分類\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"categorySearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setCategoryPage(1);\n }}\n placeholder=\"關鍵字:搜尋分類名稱或說明\"\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={categoryStatus}\n onChange={(activeKey): void => {\n setCategoryStatus(readCategoryStatusTabKey(activeKey));\n setCategoryPage(1);\n }}\n >\n {CATEGORY_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading || saving}\n pagination={{\n current: categoryPage,\n onChange: (page): void => {\n setCategoryPage(page);\n },\n onChangePageSize: (pageSize): void => {\n setCategoryPage(1);\n setCategoryPageSize(pageSize);\n },\n pageSize: categoryPageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: CATEGORY_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: categoryTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n\n <CategoryModal\n loading={saving}\n modal={modalState}\n onClose={(): void => setModalState(null)}\n onSubmit={handleSaveCategory}\n />\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"刪除\"\n loading={saving}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setDeleteConfirmation(null)}\n onClose={(): void => setDeleteConfirmation(null)}\n onConfirm={(): void => void handleConfirmDelete()}\n open={Boolean(deleteConfirmation)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"已被模板使用的分類無法刪除,請改用「停用」。\"\n title=\"刪除分類\"\n >\n <Typography color=\"text-neutral\" variant=\"body\">\n 確定要刪除「{deleteConfirmation?.name ?? ''}」嗎?\n </Typography>\n </Modal>\n </>\n );\n}\n\ninterface CategoryFormInput {\n readonly description: string | null;\n readonly isActive: boolean;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nfunction CategoryModal({\n loading,\n modal,\n onClose,\n onSubmit,\n}: {\n readonly loading: boolean;\n readonly modal: CategoryModalState | null;\n readonly onClose: () => void;\n readonly onSubmit: (input: CategoryFormInput) => Promise<void>;\n}): ReactElement {\n const [description, setDescription] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [sortOrder, setSortOrder] = useState('0');\n\n useEffect((): void => {\n if (!modal) {\n return;\n }\n\n setDescription(modal.record?.description ?? '');\n setError(null);\n setName(modal.record?.name ?? '');\n setSortOrder(String(modal.record?.sortOrder ?? 0));\n }, [modal]);\n\n async function handleConfirm(): Promise<void> {\n const trimmedName = name.trim();\n const parsedSortOrder = Number(sortOrder);\n\n if (!trimmedName) {\n setError('請輸入分類名稱');\n return;\n }\n\n if (!Number.isInteger(parsedSortOrder)) {\n setError('排序必須是整數');\n return;\n }\n\n try {\n await onSubmit({\n description: description.trim() || null,\n isActive: modal?.record?.isActive ?? true,\n name: trimmedName,\n sortOrder: parsedSortOrder,\n });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !name.trim() }}\n confirmText={modal?.type === 'EDIT' ? '儲存' : '建立'}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={Boolean(modal)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={modal?.type === 'EDIT' ? '編輯分類' : '建立分類'}\n >\n <div className={styles.templateModalFields}>\n <BPMFormField label=\"分類名稱\" name=\"categoryName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:行政管理\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"排序\" name=\"categorySortOrder\">\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortOrder(event.target.value);\n setError(null);\n }}\n placeholder=\"0\"\n value={sortOrder}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"說明\" name=\"categoryDescription\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setDescription(event.target.value);\n setError(null);\n }}\n placeholder=\"補充分類用途\"\n value={description}\n />\n </BPMFormField>\n </div>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction CategoryStatusBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n return isActive ? (\n <Badge size=\"sub\" text=\"啟用\" variant=\"dot-success\" />\n ) : (\n <Badge size=\"sub\" text=\"停用\" variant=\"dot-inactive\" />\n );\n}\n\nfunction readCategoryStatusTabKey(activeKey: Key): CategoryStatusTabKey {\n if (activeKey === 'ACTIVE' || activeKey === 'INACTIVE') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction readCategoryStatus(\n status: CategoryStatusTabKey,\n): ApprovalTemplateCategoryStatus {\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"categories-f7E-RJEc.js","names":["_Fragment","styles","BPMFormField","Fragment$1","ContentHeader","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","useState","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","useCallback","categoryPageResult","listApprovalTemplateCategoriesPage","readCategoryStatus","requestError","readErrorMessage","rows","useMemo","category","formatDateTime","columns","CategoryStatusBadge","record","Typography","handleSaveCategory","updateApprovalTemplateCategory","input","createApprovalTemplateCategory","handleToggleCategory","handleConfirmDelete","deleteApprovalTemplateCategory","tableActions","PageHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","Tab","readCategoryStatusTabKey","activeKey","TabItem","statusTab","Table","page","pageSize","from","to","total","CategoryModal","Modal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","Textarea","isActive","Badge","status"],"sources":["../../src/views/templates/templates.module.scss","../../src/views/templates/categories/TemplateCategoriesView.tsx"],"sourcesContent":[".templateFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n\n.templateModalFields {\n display: grid;\n gap: 16px;\n}\n","'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport {\n ApprovalTemplateCategoryRecord,\n ApprovalTemplateCategoryStatus,\n createApprovalTemplateCategory,\n deleteApprovalTemplateCategory,\n listApprovalTemplateCategoriesPage,\n updateApprovalTemplateCategory,\n} from '@rytass/bpm-core-client/template';\nimport styles from '../templates.module.scss';\n\nconst CATEGORY_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst CATEGORY_STATUS_TABS: readonly {\n readonly key: CategoryStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'ACTIVE', label: '啟用' },\n { key: 'INACTIVE', label: '停用' },\n];\ntype CategoryStatusTabKey = 'ACTIVE' | 'ALL' | 'INACTIVE';\n\ntype CategoryRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateCategoryRecord & {\n key: string;\n updatedAtLabel: string;\n }\n>;\n\ntype CategoryModalState = Readonly<{\n record: ApprovalTemplateCategoryRecord | null;\n type: 'CREATE' | 'EDIT';\n}>;\n\ntype DeleteConfirmationState = Readonly<{\n id: string;\n name: string;\n}>;\n\n\nexport function TemplateCategoriesView(): ReactElement {\n const [categories, setCategories] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n const [categoryPage, setCategoryPage] = useState(1);\n const [categoryPageSize, setCategoryPageSize] = useState(10);\n const [categoryStatus, setCategoryStatus] =\n useState<CategoryStatusTabKey>('ALL');\n const [categoryTotalCount, setCategoryTotalCount] = useState(0);\n const [deleteConfirmation, setDeleteConfirmation] =\n useState<DeleteConfirmationState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [modalState, setModalState] = useState<CategoryModalState | null>(null);\n const [saving, setSaving] = useState(false);\n const [searchText, setSearchText] = useState('');\n\n const refreshCategories = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const categoryPageResult = await listApprovalTemplateCategoriesPage({\n page: categoryPage,\n pageSize: categoryPageSize,\n searchText,\n status: readCategoryStatus(categoryStatus),\n });\n\n setCategories(categoryPageResult.categories);\n setCategoryTotalCount(categoryPageResult.totalCount);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [categoryPage, categoryPageSize, categoryStatus, searchText]);\n\n useEffect((): void => {\n void refreshCategories();\n }, [refreshCategories]);\n\n const rows = useMemo(\n (): CategoryRow[] =>\n categories.map((category) => ({\n ...category,\n key: category.id,\n updatedAtLabel: formatDateTime(category.updatedAt),\n })),\n [categories],\n );\n\n const columns = useMemo(\n (): TableColumn<CategoryRow>[] => [\n { dataIndex: 'name', key: 'name', title: '分類名稱', width: 180 },\n {\n key: 'status',\n render: (record: CategoryRow): ReactElement => (\n <CategoryStatusBadge isActive={record.isActive} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n dataIndex: 'sortOrder',\n key: 'sortOrder',\n title: '排序',\n width: 100,\n },\n {\n key: 'description',\n render: (record: CategoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.description || '無'}\n </Typography>\n ),\n title: '說明',\n width: 260,\n },\n {\n dataIndex: 'updatedAtLabel',\n key: 'updatedAtLabel',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function handleSaveCategory(input: CategoryFormInput): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n if (modalState?.type === 'EDIT' && modalState.record) {\n await updateApprovalTemplateCategory({\n ...input,\n id: modalState.record.id,\n });\n } else {\n await createApprovalTemplateCategory(input);\n }\n\n setModalState(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n throw requestError;\n } finally {\n setSaving(false);\n }\n }\n\n async function handleToggleCategory(\n record: ApprovalTemplateCategoryRecord,\n ): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n await updateApprovalTemplateCategory({\n description: record.description,\n id: record.id,\n isActive: !record.isActive,\n name: record.name,\n sortOrder: record.sortOrder,\n });\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handleConfirmDelete(): Promise<void> {\n if (!deleteConfirmation) {\n return;\n }\n\n setSaving(true);\n setError(null);\n\n try {\n await deleteApprovalTemplateCategory(deleteConfirmation.id);\n setDeleteConfirmation(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n const tableActions = useMemo(\n (): TableActions<CategoryRow> => ({\n render: (record): ReturnType<TableActions<CategoryRow>['render']> => [\n {\n name: '編輯',\n onClick: (): void => setModalState({ record, type: 'EDIT' }),\n },\n {\n name: record.isActive ? '停用' : '啟用',\n onClick: (): void => void handleToggleCategory(record),\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n {\n name: '刪除',\n onClick: (): void =>\n setDeleteConfirmation({ id: record.id, name: record.name }),\n variant: 'destructive-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [refreshCategories],\n );\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"維護簽核模板分類,供模板建立、篩選與列表標示使用。\"\n title=\"簽核模板分類\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n setModalState({ record: null, type: 'CREATE' })\n }\n variant=\"base-primary\"\n >\n 建立分類\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"categorySearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setCategoryPage(1);\n }}\n placeholder=\"關鍵字:搜尋分類名稱或說明\"\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={categoryStatus}\n onChange={(activeKey): void => {\n setCategoryStatus(readCategoryStatusTabKey(activeKey));\n setCategoryPage(1);\n }}\n >\n {CATEGORY_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading || saving}\n pagination={{\n current: categoryPage,\n onChange: (page): void => {\n setCategoryPage(page);\n },\n onChangePageSize: (pageSize): void => {\n setCategoryPage(1);\n setCategoryPageSize(pageSize);\n },\n pageSize: categoryPageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: CATEGORY_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: categoryTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n\n <CategoryModal\n loading={saving}\n modal={modalState}\n onClose={(): void => setModalState(null)}\n onSubmit={handleSaveCategory}\n />\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"刪除\"\n loading={saving}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setDeleteConfirmation(null)}\n onClose={(): void => setDeleteConfirmation(null)}\n onConfirm={(): void => void handleConfirmDelete()}\n open={Boolean(deleteConfirmation)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"已被模板使用的分類無法刪除,請改用「停用」。\"\n title=\"刪除分類\"\n >\n <Typography color=\"text-neutral\" variant=\"body\">\n 確定要刪除「{deleteConfirmation?.name ?? ''}」嗎?\n </Typography>\n </Modal>\n </>\n );\n}\n\ninterface CategoryFormInput {\n readonly description: string | null;\n readonly isActive: boolean;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nfunction CategoryModal({\n loading,\n modal,\n onClose,\n onSubmit,\n}: {\n readonly loading: boolean;\n readonly modal: CategoryModalState | null;\n readonly onClose: () => void;\n readonly onSubmit: (input: CategoryFormInput) => Promise<void>;\n}): ReactElement {\n const [description, setDescription] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [sortOrder, setSortOrder] = useState('0');\n\n useEffect((): void => {\n if (!modal) {\n return;\n }\n\n setDescription(modal.record?.description ?? '');\n setError(null);\n setName(modal.record?.name ?? '');\n setSortOrder(String(modal.record?.sortOrder ?? 0));\n }, [modal]);\n\n async function handleConfirm(): Promise<void> {\n const trimmedName = name.trim();\n const parsedSortOrder = Number(sortOrder);\n\n if (!trimmedName) {\n setError('請輸入分類名稱');\n return;\n }\n\n if (!Number.isInteger(parsedSortOrder)) {\n setError('排序必須是整數');\n return;\n }\n\n try {\n await onSubmit({\n description: description.trim() || null,\n isActive: modal?.record?.isActive ?? true,\n name: trimmedName,\n sortOrder: parsedSortOrder,\n });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !name.trim() }}\n confirmText={modal?.type === 'EDIT' ? '儲存' : '建立'}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={Boolean(modal)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={modal?.type === 'EDIT' ? '編輯分類' : '建立分類'}\n >\n <div className={styles.templateModalFields}>\n <BPMFormField label=\"分類名稱\" name=\"categoryName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:行政管理\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"排序\" name=\"categorySortOrder\">\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortOrder(event.target.value);\n setError(null);\n }}\n placeholder=\"0\"\n value={sortOrder}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"說明\" name=\"categoryDescription\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setDescription(event.target.value);\n setError(null);\n }}\n placeholder=\"補充分類用途\"\n value={description}\n />\n </BPMFormField>\n </div>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction CategoryStatusBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n return isActive ? (\n <Badge size=\"sub\" text=\"啟用\" variant=\"dot-success\" />\n ) : (\n <Badge size=\"sub\" text=\"停用\" variant=\"dot-inactive\" />\n );\n}\n\nfunction readCategoryStatusTabKey(activeKey: Key): CategoryStatusTabKey {\n if (activeKey === 'ACTIVE' || activeKey === 'INACTIVE') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction readCategoryStatus(\n status: CategoryStatusTabKey,\n): ApprovalTemplateCategoryStatus {\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { r as e } from "./router-adapter-CkxCyzf5.js";
|
|
3
3
|
import { r as t } from "./routes-config-BcNaWJWJ.js";
|
|
4
|
-
import { t as n } from "./FormBuilderView-
|
|
5
|
-
import { t as r } from "./FormRendererView-
|
|
6
|
-
import { n as i, r as a, t as o } from "./designer-
|
|
7
|
-
import {
|
|
4
|
+
import { t as n } from "./FormBuilderView-6KdApi-D.js";
|
|
5
|
+
import { t as r } from "./FormRendererView-BcQKUi1A.js";
|
|
6
|
+
import { n as i, r as a, t as o } from "./designer-CCy5EbOe.js";
|
|
7
|
+
import { o as s } from "./organization-time-zone-provider-DNL8yo4-.js";
|
|
8
8
|
import { useCallback as c, useEffect as l, useState as u } from "react";
|
|
9
9
|
import { Button as d, Empty as f, FormField as p, Input as m, PageHeader as h, Section as g, SectionGroup as _, Select as v, Step as y, Stepper as b, Table as x, Tag as S, Typography as C } from "@mezzanine-ui/react";
|
|
10
10
|
import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
|
|
@@ -438,4 +438,4 @@ var J = {
|
|
|
438
438
|
};
|
|
439
439
|
export { G as i, U as n, W as r, q as t };
|
|
440
440
|
|
|
441
|
-
//# sourceMappingURL=compose-
|
|
441
|
+
//# sourceMappingURL=compose-DFuLPmOA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose-egQlRjuZ.js","names":["_Fragment","_Fragment","_Fragment","_Fragment","useRouterAdapter","useBPMRoutes","FormBuilderView","FormRenderer","readTemplateErrorMessage","readApproverResolverDetail","TemplateDesignerView","useBPMLanguage","Fragment$1","ContentHeader","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","useState","active","result","listApprovalTemplateCategoriesPage","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","FormField","FormFieldLayout","Input","onNameChange","event","name","Select","onCategoryIdChange","Typography","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","Empty","Table","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","Tag","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","language","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","useCallback","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","submittedDefinition","EMPTY_WORKFLOW_DEFINITION","composeApprovalTemplateWithForm","requestError","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","PageHeader","Button","SectionGroup","Section","Stepper","Step","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\nimport { readApproverResolverDetail } from '../../designer/approver-resolver-model';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n return readApproverResolverDetail(node.data.approverResolver);\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { useBPMLanguage } from '../../../lib/language-provider';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\nimport { readTemplateErrorMessage } from '../template-error-message';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const language = useBPMLanguage();\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n const submittedDefinition =\n workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION;\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: submittedDefinition,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(\n readTemplateErrorMessage(requestError, language, submittedDefinition),\n );\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n language,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\n// Phase 23 P4: templates created through the wizard start on cel-v2.\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n expressionDialect: 'cel-v2',\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compose-DFuLPmOA.js","names":["_Fragment","_Fragment","_Fragment","_Fragment","useRouterAdapter","useBPMRoutes","FormBuilderView","FormRenderer","readTemplateErrorMessage","readApproverResolverDetail","TemplateDesignerView","useBPMLanguage","Fragment$1","ContentHeader","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","useState","active","result","listApprovalTemplateCategoriesPage","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","FormField","FormFieldLayout","Input","onNameChange","event","name","Select","onCategoryIdChange","Typography","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","Empty","Table","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","Tag","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","language","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","useCallback","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","submittedDefinition","EMPTY_WORKFLOW_DEFINITION","composeApprovalTemplateWithForm","requestError","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","PageHeader","Button","SectionGroup","Section","Stepper","Step","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\nimport { readApproverResolverDetail } from '../../designer/approver-resolver-model';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n return readApproverResolverDetail(node.data.approverResolver);\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { useBPMLanguage } from '../../../lib/language-provider';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\nimport { readTemplateErrorMessage } from '../template-error-message';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const language = useBPMLanguage();\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n const submittedDefinition =\n workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION;\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: submittedDefinition,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(\n readTemplateErrorMessage(requestError, language, submittedDefinition),\n );\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n language,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\n// Phase 23 P4: templates created through the wizard start on cel-v2.\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n expressionDialect: 'cel-v2',\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-C1j_vFKo.cjs"),r=require("./FormBuilderView-CGKkuVFi.cjs"),i=require("./FormRendererView-B-xycC9S.cjs"),a=require("./designer-CAUWEKJ4.cjs"),o=require("./organization-time-zone-provider-B7CXQril.cjs");let s=require("react"),c=require("@mezzanine-ui/react"),l=require("react/jsx-runtime"),u=require("@mezzanine-ui/core/form"),d=require("@mezzanine-ui/react/ContentHeader");d=e.t(d,1);let f=require("@rytass/bpm-core-client/template");var p={id:`UNCATEGORIZED`,name:`未分類`},m=100;function h({categoryId:e,formSchema:t,formUiSchema:n,name:i,onCategoryIdChange:a,onFormChange:o,onNameChange:d}){let[h,_]=(0,s.useState)([]);(0,s.useEffect)(()=>{let e=!0;return(async()=>{try{let t=await(0,f.listApprovalTemplateCategoriesPage)({page:1,pageSize:m,searchText:``,status:`ACTIVE`});e&&_(t.categories)}catch{e&&_([])}})(),()=>{e=!1}},[]);let v=[p,...h.map(e=>({id:e.id,name:e.name}))],y=v.find(t=>t.id===e)??p;return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`div`,{style:g,children:[(0,l.jsx)(c.FormField,{label:`名稱`,layout:u.FormFieldLayout.VERTICAL,name:`composeName`,children:(0,l.jsx)(c.Input,{fullWidth:!0,onChange:e=>d(e.target.value),placeholder:`例如:請款簽核`,value:i})}),(0,l.jsx)(c.FormField,{label:`分類(選填)`,layout:u.FormFieldLayout.VERTICAL,name:`composeCategory`,children:(0,l.jsx)(c.Select,{clearable:!1,fullWidth:!0,onChange:e=>a(e&&e.id!==p.id?e.id:null),options:v,placeholder:`未分類`,value:y})})]}),(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`caption`,children:`先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。`}),(0,l.jsx)(r.t,{onChange:o,value:{schema:t,uiSchema:n}})]})}var g={display:`grid`,gap:16,gridTemplateColumns:`repeat(auto-fit, minmax(220px, 1fr))`};function _({formSchema:e,formUiSchema:t,initiatorPolicyCel:n,name:r,publishError:a,workflowDefinition:o}){let s=o?.nodes??[],u=o?.edges??[],d=e.fields.length,f=new Map(s.map(e=>[e.id,e.data.label])),p=s.map(e=>({detail:x(e)??`—`,key:e.id,label:e.data.label,typeLabel:b(e)})),m=u.filter(e=>!!e.data.condition).map(e=>({condition:e.data.condition??``,key:e.id,source:f.get(e.source)??e.source,target:f.get(e.target)??e.target}));return(0,l.jsxs)(`div`,{style:S,children:[(0,l.jsx)(c.Typography,{component:`h2`,style:C,variant:`h2`,children:r||`(未命名)`}),(0,l.jsxs)(`div`,{style:S,children:[(0,l.jsx)(c.Typography,{variant:`h3`,children:`表單預覽`}),d>0?(0,l.jsx)(i.t,{dataSourceContext:{kind:`preview`},readonly:!0,schema:e,uiSchema:t}):(0,l.jsx)(c.Empty,{title:`尚未設計表單欄位`})]}),(0,l.jsxs)(`div`,{style:S,children:[(0,l.jsx)(c.Typography,{variant:`h3`,children:`流程概覽`}),s.length>0?(0,l.jsx)(c.Table,{columns:v,dataSource:p,fullWidth:!0}):(0,l.jsx)(c.Empty,{title:`尚未設計流程節點`}),m.length>0?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`caption`,children:`條件分流`}),(0,l.jsx)(c.Table,{columns:y,dataSource:m,fullWidth:!0})]}):null,n?(0,l.jsxs)(c.Typography,{color:`text-neutral`,variant:`caption`,children:[`發起權限:`,n]}):null]}),a?(0,l.jsx)(c.Typography,{color:`text-error`,variant:`body`,children:a}):null]})}var v=[{key:`type`,render:e=>(0,l.jsx)(c.Tag,{label:e.typeLabel,size:`sub`,type:`static`}),title:`類型`,width:130},{dataIndex:`label`,key:`label`,title:`節點`},{dataIndex:`detail`,key:`detail`,title:`簽核方式`,width:160}],y=[{dataIndex:`source`,key:`source`,title:`來源`,width:180},{dataIndex:`target`,key:`target`,title:`目標`,width:180},{dataIndex:`condition`,key:`condition`,title:`條件`}];function b(e){switch(e.type){case`startEvent`:return`開始`;case`endEvent`:return e.data.endState===`REJECTED`?`結束(駁回)`:`結束(核准)`;case`userTask`:return`簽核`;case`serviceTask`:return`服務`;case`exclusiveGateway`:return`條件閘道`;case`parallelGateway`:return`平行閘道`;default:return`節點`}}function x(e){return e.type===`userTask`?a.r(e.data.approverResolver):null}var S={display:`grid`,gap:12},C={marginTop:`var(--mzn-spacing-padding-vertical-spacious)`};function w({aiAssistantAvailable:e=!1,formSchema:t,initiatorPolicyCel:n,onInitiatorPolicyChange:r,onWorkflowChange:i,showAiAssistant:o=!1,workflowDefinition:s}){return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`caption`,children:`設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。`}),(0,l.jsx)(a.t,{aiAssistantAvailable:e,embedded:!0,formSchemaOverride:t,initialInitiatorPolicyCel:n,initialWorkflowDefinition:s??void 0,onInitiatorPolicyChange:r,onWorkflowChange:i,showAiAssistant:o})]})}var T={fields:[],schemaVersion:1},E={layout:[],schemaVersion:1};function D(){let e=o.o(),[t,n]=(0,s.useState)(0),[r,i]=(0,s.useState)(``),[c,l]=(0,s.useState)(null),[u,d]=(0,s.useState)(T),[p,m]=(0,s.useState)(E),[h,g]=(0,s.useState)(null),[_,v]=(0,s.useState)(null),[y,b]=(0,s.useState)(`idle`),[x,S]=(0,s.useState)(null),C=r.trim().length>0&&u.fields.length>0,w=(0,s.useCallback)(e=>{n(e)},[]),D=(0,s.useCallback)(()=>{n(e=>e<2?e+1:e)},[]),k=(0,s.useCallback)(()=>{n(e=>e>0?e-1:e)},[]),A=(0,s.useCallback)(e=>{d(e.schema),m(e.uiSchema)},[]),j=(0,s.useCallback)(e=>{g(e)},[]),M=(0,s.useCallback)(e=>{v(e)},[]);return{canLeaveBasics:C,categoryId:c,currentStep:t,formSchema:u,formUiSchema:p,goBack:k,goNext:D,goToStep:w,initiatorPolicyCel:_,name:r,publish:(0,s.useCallback)(async()=>{b(`submitting`),S(null);let t=h??O;try{let e=await(0,f.composeApprovalTemplateWithForm)({category:null,categoryId:c,formDefinitionId:null,formDescription:null,formName:r,initiatorPolicyCel:_,notificationConfig:null,publish:!0,schema:u,slaDefaults:null,templateDescription:null,templateId:null,templateName:r,uiSchema:p,workflowDefinition:t});return b(`success`),e}catch(n){return S(a.n(n,e,t)),b(`error`),null}},[c,u,p,_,e,r,h]),publishError:x,publishPhase:y,setCategoryId:l,setFormValue:A,setInitiatorPolicyCel:M,setName:i,setWorkflowDefinition:j,workflowDefinition:h}}var O={edges:[],expressionDialect:`cel-v2`,meta:{schemaVersion:1},nodes:[{data:{label:`開始`},id:`start`,position:{x:80,y:160},type:`startEvent`},{data:{endState:`APPROVED`,label:`完成`,triggerMode:`AND`},id:`end`,position:{x:560,y:160},type:`endEvent`}]};function k({aiAssistantAvailable:e=!1,showAiAssistant:r=!1}={}){let i=t.r(),a=n.r(),o=D(),s=o.publishPhase===`submitting`;async function u(){let e=await o.publish();e&&i.push(a.templateDesigner(e.templateId))}return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:`一次完成表單與流程設計,發佈後即可直接發起。`,title:`建立模板(表單 + 流程)`,children:(0,l.jsx)(c.Button,{disabled:s,onClick:()=>i.push(a.templates()),variant:`base-secondary`,children:`返回模板列表`})})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsxs)(c.Section,{children:[(0,l.jsxs)(c.Stepper,{currentStep:o.currentStep,children:[(0,l.jsx)(c.Step,{description:`設計欄位與版面`,title:`表單設計`}),(0,l.jsx)(c.Step,{description:`設計簽核節點與條件`,title:`流程設計`}),(0,l.jsx)(c.Step,{description:`確認後發佈`,title:`檢視並發佈`})]}),o.currentStep===0?(0,l.jsx)(h,{categoryId:o.categoryId,formSchema:o.formSchema,formUiSchema:o.formUiSchema,name:o.name,onCategoryIdChange:o.setCategoryId,onFormChange:o.setFormValue,onNameChange:o.setName}):null,o.currentStep===1?(0,l.jsx)(w,{aiAssistantAvailable:e,formSchema:o.formSchema,initiatorPolicyCel:o.initiatorPolicyCel,onInitiatorPolicyChange:o.setInitiatorPolicyCel,onWorkflowChange:o.setWorkflowDefinition,showAiAssistant:r,workflowDefinition:o.workflowDefinition}):null,o.currentStep===2?(0,l.jsx)(_,{formSchema:o.formSchema,formUiSchema:o.formUiSchema,initiatorPolicyCel:o.initiatorPolicyCel,name:o.name,publishError:o.publishError,workflowDefinition:o.workflowDefinition}):null,(0,l.jsxs)(`div`,{style:A,children:[o.currentStep===0&&!o.canLeaveBasics?(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`caption`,children:`請填寫模板名稱、表單名稱,並至少新增一個表單欄位。`}):(0,l.jsx)(`span`,{}),(0,l.jsxs)(`div`,{style:j,children:[(0,l.jsx)(c.Button,{disabled:o.currentStep===0||s,onClick:o.goBack,variant:`base-secondary`,children:`上一步`}),o.currentStep<2?(0,l.jsx)(c.Button,{disabled:o.currentStep===0&&!o.canLeaveBasics,onClick:o.goNext,variant:`base-primary`,children:`下一步`}):(0,l.jsx)(c.Button,{disabled:s,loading:s,onClick:()=>{u()},variant:`base-primary`,children:`發佈`})]})]})]})})]})}var A={alignItems:`center`,display:`flex`,marginTop:`var(--mzn-spacing-padding-vertical-spacious)`,justifyContent:`space-between`,gap:16},j={display:`flex`,gap:8};Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return k}});
|
|
2
|
+
//# sourceMappingURL=compose-DK3ocWwG.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-DK3ocWwG.cjs","names":["useState","listApprovalTemplateCategoriesPage","_Fragment","FormField","FormFieldLayout","Input","Select","Typography","FormBuilderView","Typography","FormRenderer","Empty","Table","_Fragment","Tag","readApproverResolverDetail","_Fragment","Typography","TemplateDesignerView","useBPMLanguage","useState","useCallback","composeApprovalTemplateWithForm","readTemplateErrorMessage","useRouterAdapter","useBPMRoutes","_Fragment","PageHeader","ContentHeader","Button","SectionGroup","Section","Stepper","Step","Typography","require_rolldown_runtime","require_router_adapter","require_routes_config","require_FormBuilderView","require_FormRendererView","require_designer","require_organization_time_zone_provider","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_rytass_bpm_core_client_template","UNCATEGORIZED_OPTION","CATEGORY_PAGE_SIZE","ComposeFormStep","categoryOptions","setCategoryOptions","active","result","selectOptions","category","selectedOption","option","categoryId","BASICS_GRID_STYLE","onNameChange","event","name","onCategoryIdChange","onFormChange","formSchema","formUiSchema","ComposeReviewStep","nodes","workflowDefinition","edges","fieldCount","nodeLabelById","node","nodeRows","readNodeDetail","readNodeTypeLabel","branchRows","edge","STACK_STYLE","TITLE_STYLE","NODE_COLUMNS","BRANCH_COLUMNS","initiatorPolicyCel","publishError","record","ComposeWorkflowStep","EMPTY_COMPOSE_FORM_SCHEMA","EMPTY_COMPOSE_FORM_UI_SCHEMA","useTemplateComposeWizard","language","currentStep","setCurrentStep","setName","setCategoryId","setFormSchema","setFormUiSchema","setWorkflowDefinitionState","setInitiatorPolicyCelState","publishPhase","setPublishPhase","setPublishError","canLeaveBasics","goToStep","step","goNext","goBack","setFormValue","next","setWorkflowDefinition","definition","setInitiatorPolicyCel","cel","submittedDefinition","EMPTY_WORKFLOW_DEFINITION","requestError","TemplateComposeWizardView","router","routes","wizard","submitting","handlePublish","FOOTER_STYLE","FOOTER_ACTIONS_STYLE"],"sources":["../../src/views/templates/compose/steps/ComposeFormStep.tsx","../../src/views/templates/compose/steps/ComposeReviewStep.tsx","../../src/views/templates/compose/steps/ComposeWorkflowStep.tsx","../../src/views/templates/compose/use-template-compose-wizard.ts","../../src/views/templates/compose/TemplateComposeWizardView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { FormField, Input, Select, Typography } from '@mezzanine-ui/react';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { SelectValue } from '@mezzanine-ui/react/Select';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport {\n ApprovalTemplateCategoryRecord,\n listApprovalTemplateCategoriesPage,\n} from '@rytass/bpm-core-client/template';\nimport { FormBuilderView } from '../../../forms/builder';\n\nconst UNCATEGORIZED_OPTION: SelectValue = {\n id: 'UNCATEGORIZED',\n name: '未分類',\n};\n\nconst CATEGORY_PAGE_SIZE = 100;\n\nexport interface ComposeFormStepProps {\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly onNameChange: (value: string) => void;\n readonly onCategoryIdChange: (value: string | null) => void;\n readonly onFormChange: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function ComposeFormStep({\n categoryId,\n formSchema,\n formUiSchema,\n name,\n onCategoryIdChange,\n onFormChange,\n onNameChange,\n}: ComposeFormStepProps): ReactElement {\n const [categoryOptions, setCategoryOptions] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void (async (): Promise<void> => {\n try {\n const result = await listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n });\n\n if (active) {\n setCategoryOptions(result.categories);\n }\n } catch {\n if (active) {\n setCategoryOptions([]);\n }\n }\n })();\n\n return (): void => {\n active = false;\n };\n }, []);\n\n const selectOptions: SelectValue[] = [\n UNCATEGORIZED_OPTION,\n ...categoryOptions.map((category) => ({\n id: category.id,\n name: category.name,\n })),\n ];\n const selectedOption =\n selectOptions.find((option) => option.id === categoryId) ??\n UNCATEGORIZED_OPTION;\n\n return (\n <>\n <div style={BASICS_GRID_STYLE}>\n <FormField\n label=\"名稱\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeName\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onNameChange(event.target.value)\n }\n placeholder=\"例如:請款簽核\"\n value={name}\n />\n </FormField>\n <FormField\n label=\"分類(選填)\"\n layout={FormFieldLayout.VERTICAL}\n name=\"composeCategory\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n onCategoryIdChange(\n option && option.id !== UNCATEGORIZED_OPTION.id\n ? option.id\n : null,\n )\n }\n options={selectOptions}\n placeholder=\"未分類\"\n value={selectedOption}\n />\n </FormField>\n </div>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 先設計表單欄位,下一步的流程條件分流即可直接引用這些欄位。\n </Typography>\n <FormBuilderView\n onChange={onFormChange}\n value={{ schema: formSchema, uiSchema: formUiSchema }}\n />\n </>\n );\n}\n\nconst BASICS_GRID_STYLE = {\n display: 'grid',\n gap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n} as const;\n","'use client';\n\nimport type { CSSProperties, ReactElement } from 'react';\nimport { Empty, Table, Tag, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\nimport { readApproverResolverDetail } from '../../designer/approver-resolver-model';\n\ntype FlowNodeRow = Readonly<\n Record<string, unknown> & {\n detail: string;\n key: string;\n label: string;\n typeLabel: string;\n }\n>;\n\ntype BranchRow = Readonly<\n Record<string, unknown> & {\n condition: string;\n key: string;\n source: string;\n target: string;\n }\n>;\n\nexport interface ComposeReviewStepProps {\n readonly name: string;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishError: string | null;\n}\n\nexport function ComposeReviewStep({\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n name,\n publishError,\n workflowDefinition,\n}: ComposeReviewStepProps): ReactElement {\n const nodes = workflowDefinition?.nodes ?? [];\n const edges = workflowDefinition?.edges ?? [];\n const fieldCount = formSchema.fields.length;\n const nodeLabelById = new Map(\n nodes.map((node) => [node.id, node.data.label] as const),\n );\n const nodeRows: FlowNodeRow[] = nodes.map((node) => ({\n detail: readNodeDetail(node) ?? '—',\n key: node.id,\n label: node.data.label,\n typeLabel: readNodeTypeLabel(node),\n }));\n const branchRows: BranchRow[] = edges\n .filter((edge) => Boolean(edge.data.condition))\n .map((edge) => ({\n condition: edge.data.condition ?? '',\n key: edge.id,\n source: nodeLabelById.get(edge.source) ?? edge.source,\n target: nodeLabelById.get(edge.target) ?? edge.target,\n }));\n\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" style={TITLE_STYLE} variant=\"h2\">\n {name || '(未命名)'}\n </Typography>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">表單預覽</Typography>\n {fieldCount > 0 ? (\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n readonly\n schema={formSchema}\n uiSchema={formUiSchema}\n />\n ) : (\n <Empty title=\"尚未設計表單欄位\" />\n )}\n </div>\n\n <div style={STACK_STYLE}>\n <Typography variant=\"h3\">流程概覽</Typography>\n {nodes.length > 0 ? (\n <Table columns={NODE_COLUMNS} dataSource={nodeRows} fullWidth />\n ) : (\n <Empty title=\"尚未設計流程節點\" />\n )}\n {branchRows.length > 0 ? (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 條件分流\n </Typography>\n <Table columns={BRANCH_COLUMNS} dataSource={branchRows} fullWidth />\n </>\n ) : null}\n {initiatorPolicyCel ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 發起權限:{initiatorPolicyCel}\n </Typography>\n ) : null}\n </div>\n\n {publishError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {publishError}\n </Typography>\n ) : null}\n </div>\n );\n}\n\nconst NODE_COLUMNS: TableColumn<FlowNodeRow>[] = [\n {\n key: 'type',\n render: (record: FlowNodeRow): ReactElement => (\n <Tag label={record.typeLabel} size=\"sub\" type=\"static\" />\n ),\n title: '類型',\n width: 130,\n },\n { dataIndex: 'label', key: 'label', title: '節點' },\n { dataIndex: 'detail', key: 'detail', title: '簽核方式', width: 160 },\n];\n\nconst BRANCH_COLUMNS: TableColumn<BranchRow>[] = [\n { dataIndex: 'source', key: 'source', title: '來源', width: 180 },\n { dataIndex: 'target', key: 'target', title: '目標', width: 180 },\n { dataIndex: 'condition', key: 'condition', title: '條件' },\n];\n\nfunction readNodeTypeLabel(node: WorkflowNode): string {\n switch (node.type) {\n case 'startEvent':\n return '開始';\n case 'endEvent':\n return node.data.endState === 'REJECTED' ? '結束(駁回)' : '結束(核准)';\n case 'userTask':\n return '簽核';\n case 'serviceTask':\n return '服務';\n case 'exclusiveGateway':\n return '條件閘道';\n case 'parallelGateway':\n return '平行閘道';\n default:\n return '節點';\n }\n}\n\nfunction readNodeDetail(node: WorkflowNode): string | null {\n if (node.type !== 'userTask') {\n return null;\n }\n\n return readApproverResolverDetail(node.data.approverResolver);\n}\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\n// Match the breathing room between the stepper and the PageHeader, which is the\n// Section's top padding token.\nconst TITLE_STYLE: CSSProperties = {\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { TemplateDesignerView } from '../../designer';\n\nexport interface ComposeWorkflowStepProps {\n readonly formSchema: FormDefinitionSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly onWorkflowChange: (definition: WorkflowDefinition) => void;\n readonly onInitiatorPolicyChange: (cel: string | null) => void;\n /**\n * Show the AI assistant button inside the embedded designer's side panel.\n * Follows the same opt-in contract as the standalone designer page; default\n * hidden. Wired up the stack from the server page's `BPM_AI_ASSISTANT_ENABLED`.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\nexport function ComposeWorkflowStep({\n aiAssistantAvailable = false,\n formSchema,\n initiatorPolicyCel,\n onInitiatorPolicyChange,\n onWorkflowChange,\n showAiAssistant = false,\n workflowDefinition,\n}: ComposeWorkflowStepProps): ReactElement {\n return (\n <>\n <Typography color=\"text-neutral\" variant=\"caption\">\n 設計簽核節點與條件分流;條件可直接引用上一步設計的表單欄位。\n </Typography>\n <TemplateDesignerView\n aiAssistantAvailable={aiAssistantAvailable}\n embedded\n formSchemaOverride={formSchema}\n initialInitiatorPolicyCel={initiatorPolicyCel}\n initialWorkflowDefinition={workflowDefinition ?? undefined}\n onInitiatorPolicyChange={onInitiatorPolicyChange}\n onWorkflowChange={onWorkflowChange}\n showAiAssistant={showAiAssistant}\n />\n </>\n );\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type {\n FormDefinitionSchema,\n FormUiSchema,\n} from '@rytass/bpm-core-shared/form';\nimport type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport { useBPMLanguage } from '../../../lib/language-provider';\nimport {\n ComposeApprovalTemplateWithFormResult,\n composeApprovalTemplateWithForm,\n} from '@rytass/bpm-core-client/template';\nimport { readTemplateErrorMessage } from '../template-error-message';\n\nexport type ComposeWizardStep = 0 | 1 | 2;\n\nexport type ComposePublishPhase = 'error' | 'idle' | 'submitting' | 'success';\n\nexport const EMPTY_COMPOSE_FORM_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nexport const EMPTY_COMPOSE_FORM_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nexport interface TemplateComposeWizard {\n readonly currentStep: ComposeWizardStep;\n /**\n * Single user-facing name. Persisted to both the template and the form\n * (`templateName` / `formName`) at the `composeApprovalTemplateWithForm`\n * boundary — the DB keeps two columns, the UI keeps one field.\n */\n readonly name: string;\n readonly categoryId: string | null;\n readonly formSchema: FormDefinitionSchema;\n readonly formUiSchema: FormUiSchema;\n readonly workflowDefinition: WorkflowDefinition | null;\n readonly initiatorPolicyCel: string | null;\n readonly publishPhase: ComposePublishPhase;\n readonly publishError: string | null;\n readonly canLeaveBasics: boolean;\n readonly goToStep: (step: ComposeWizardStep) => void;\n readonly goNext: () => void;\n readonly goBack: () => void;\n readonly setName: (value: string) => void;\n readonly setCategoryId: (value: string | null) => void;\n readonly setFormValue: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n readonly setWorkflowDefinition: (definition: WorkflowDefinition) => void;\n readonly setInitiatorPolicyCel: (cel: string | null) => void;\n readonly publish: () => Promise<ComposeApprovalTemplateWithFormResult | null>;\n}\n\n/**\n * Owns the cross-step state for the unified \"form + flow\" template wizard.\n *\n * Step 0 (表單) edits `formSchema`/`formUiSchema`; that same in-memory schema\n * feeds Step 1 (流程) as the field source for condition branches, so the\n * embedded designer never needs a published form version. Step 2 (檢視發佈)\n * submits everything through the atomic `composeApprovalTemplateWithForm`\n * mutation.\n */\nexport function useTemplateComposeWizard(): TemplateComposeWizard {\n const language = useBPMLanguage();\n const [currentStep, setCurrentStep] = useState<ComposeWizardStep>(0);\n const [name, setName] = useState('');\n const [categoryId, setCategoryId] = useState<string | null>(null);\n const [formSchema, setFormSchema] = useState<FormDefinitionSchema>(\n EMPTY_COMPOSE_FORM_SCHEMA,\n );\n const [formUiSchema, setFormUiSchema] = useState<FormUiSchema>(\n EMPTY_COMPOSE_FORM_UI_SCHEMA,\n );\n const [workflowDefinition, setWorkflowDefinitionState] =\n useState<WorkflowDefinition | null>(null);\n const [initiatorPolicyCel, setInitiatorPolicyCelState] = useState<\n string | null\n >(null);\n const [publishPhase, setPublishPhase] = useState<ComposePublishPhase>('idle');\n const [publishError, setPublishError] = useState<string | null>(null);\n\n const canLeaveBasics = name.trim().length > 0 && formSchema.fields.length > 0;\n\n const goToStep = useCallback((step: ComposeWizardStep): void => {\n setCurrentStep(step);\n }, []);\n\n const goNext = useCallback((): void => {\n setCurrentStep((step) =>\n step < 2 ? ((step + 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const goBack = useCallback((): void => {\n setCurrentStep((step) =>\n step > 0 ? ((step - 1) as ComposeWizardStep) : step,\n );\n }, []);\n\n const setFormValue = useCallback(\n (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }): void => {\n setFormSchema(next.schema);\n setFormUiSchema(next.uiSchema);\n },\n [],\n );\n\n const setWorkflowDefinition = useCallback(\n (definition: WorkflowDefinition): void => {\n setWorkflowDefinitionState(definition);\n },\n [],\n );\n\n const setInitiatorPolicyCel = useCallback((cel: string | null): void => {\n setInitiatorPolicyCelState(cel);\n }, []);\n\n const publish =\n useCallback(async (): Promise<ComposeApprovalTemplateWithFormResult | null> => {\n setPublishPhase('submitting');\n setPublishError(null);\n\n const submittedDefinition =\n workflowDefinition ?? EMPTY_WORKFLOW_DEFINITION;\n\n try {\n const result = await composeApprovalTemplateWithForm({\n category: null,\n categoryId,\n formDefinitionId: null,\n formDescription: null,\n // One UI name fans out to both persisted columns.\n formName: name,\n initiatorPolicyCel,\n notificationConfig: null,\n publish: true,\n schema: formSchema,\n slaDefaults: null,\n templateDescription: null,\n templateId: null,\n templateName: name,\n uiSchema: formUiSchema,\n workflowDefinition: submittedDefinition,\n });\n\n setPublishPhase('success');\n\n return result;\n } catch (requestError: unknown) {\n setPublishError(\n readTemplateErrorMessage(requestError, language, submittedDefinition),\n );\n setPublishPhase('error');\n\n return null;\n }\n }, [\n categoryId,\n formSchema,\n formUiSchema,\n initiatorPolicyCel,\n language,\n name,\n workflowDefinition,\n ]);\n\n return {\n canLeaveBasics,\n categoryId,\n currentStep,\n formSchema,\n formUiSchema,\n goBack,\n goNext,\n goToStep,\n initiatorPolicyCel,\n name,\n publish,\n publishError,\n publishPhase,\n setCategoryId,\n setFormValue,\n setInitiatorPolicyCel,\n setName,\n setWorkflowDefinition,\n workflowDefinition,\n };\n}\n\n// Phase 23 P4: templates created through the wizard start on cel-v2.\nconst EMPTY_WORKFLOW_DEFINITION: WorkflowDefinition = {\n edges: [],\n expressionDialect: 'cel-v2',\n meta: { schemaVersion: 1 },\n nodes: [\n {\n data: { label: '開始' },\n id: 'start',\n position: { x: 80, y: 160 },\n type: 'startEvent',\n },\n {\n data: { endState: 'APPROVED', label: '完成', triggerMode: 'AND' },\n id: 'end',\n position: { x: 560, y: 160 },\n type: 'endEvent',\n },\n ],\n};\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Step,\n Stepper,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { ComposeFormStep } from './steps/ComposeFormStep';\nimport { ComposeReviewStep } from './steps/ComposeReviewStep';\nimport { ComposeWorkflowStep } from './steps/ComposeWorkflowStep';\nimport { useTemplateComposeWizard } from './use-template-compose-wizard';\n\nexport interface TemplateComposeWizardViewProps {\n /**\n * Show the workflow designer AI assistant inside Step 1 (流程設計). Opt-in,\n * default hidden — the server page maps `BPM_AI_ASSISTANT_ENABLED` to it.\n */\n readonly showAiAssistant?: boolean;\n /**\n * Whether the LLM backend is configured (host has an API key). When `false`\n * the AI button shows disabled as a placeholder. Default `false`.\n */\n readonly aiAssistantAvailable?: boolean;\n}\n\n/**\n * Unified \"form + flow\" template creation wizard. Walks the user through\n * Step 0 表單設計 → Step 1 流程設計 → Step 2 檢視並發佈, then commits both\n * sides atomically through `composeApprovalTemplateWithForm`. This is the\n * template entry point; the form builder is intentionally controlled here\n * instead of exposed as a standalone `/forms` page.\n */\nexport function TemplateComposeWizardView({\n aiAssistantAvailable = false,\n showAiAssistant = false,\n}: TemplateComposeWizardViewProps = {}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const wizard = useTemplateComposeWizard();\n const submitting = wizard.publishPhase === 'submitting';\n\n async function handlePublish(): Promise<void> {\n const result = await wizard.publish();\n\n if (result) {\n router.push(routes.templateDesigner(result.templateId));\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"一次完成表單與流程設計,發佈後即可直接發起。\"\n title=\"建立模板(表單 + 流程)\"\n >\n <Button\n disabled={submitting}\n onClick={(): void => router.push(routes.templates())}\n variant=\"base-secondary\"\n >\n 返回模板列表\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Stepper currentStep={wizard.currentStep}>\n <Step description=\"設計欄位與版面\" title=\"表單設計\" />\n <Step description=\"設計簽核節點與條件\" title=\"流程設計\" />\n <Step description=\"確認後發佈\" title=\"檢視並發佈\" />\n </Stepper>\n\n {wizard.currentStep === 0 ? (\n <ComposeFormStep\n categoryId={wizard.categoryId}\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n name={wizard.name}\n onCategoryIdChange={wizard.setCategoryId}\n onFormChange={wizard.setFormValue}\n onNameChange={wizard.setName}\n />\n ) : null}\n\n {wizard.currentStep === 1 ? (\n <ComposeWorkflowStep\n aiAssistantAvailable={aiAssistantAvailable}\n formSchema={wizard.formSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n onInitiatorPolicyChange={wizard.setInitiatorPolicyCel}\n onWorkflowChange={wizard.setWorkflowDefinition}\n showAiAssistant={showAiAssistant}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n {wizard.currentStep === 2 ? (\n <ComposeReviewStep\n formSchema={wizard.formSchema}\n formUiSchema={wizard.formUiSchema}\n initiatorPolicyCel={wizard.initiatorPolicyCel}\n name={wizard.name}\n publishError={wizard.publishError}\n workflowDefinition={wizard.workflowDefinition}\n />\n ) : null}\n\n <div style={FOOTER_STYLE}>\n {wizard.currentStep === 0 && !wizard.canLeaveBasics ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 請填寫模板名稱、表單名稱,並至少新增一個表單欄位。\n </Typography>\n ) : (\n <span />\n )}\n <div style={FOOTER_ACTIONS_STYLE}>\n <Button\n disabled={wizard.currentStep === 0 || submitting}\n onClick={wizard.goBack}\n variant=\"base-secondary\"\n >\n 上一步\n </Button>\n {wizard.currentStep < 2 ? (\n <Button\n disabled={wizard.currentStep === 0 && !wizard.canLeaveBasics}\n onClick={wizard.goNext}\n variant=\"base-primary\"\n >\n 下一步\n </Button>\n ) : (\n <Button\n disabled={submitting}\n loading={submitting}\n onClick={(): void => {\n void handlePublish();\n }}\n variant=\"base-primary\"\n >\n 發佈\n </Button>\n )}\n </div>\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nconst FOOTER_STYLE = {\n alignItems: 'center',\n display: 'flex',\n // Match the breathing room used elsewhere (the Section's top padding token).\n marginTop: 'var(--mzn-spacing-padding-vertical-spacious)',\n justifyContent: 'space-between',\n gap: 16,\n} as const;\n\nconst FOOTER_ACTIONS_STYLE = {\n display: 'flex',\n gap: 8,\n} as const;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";require('../delegations.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./bpm-form-field-Bc6k4ZEO.cjs"),n=require("./format-date-time-D-cx5M8z.cjs"),r=require("./auth-provider-4BeCw7cI.cjs"),i=require("./format-member-label-t7ANTF62.cjs");let a=require("react"),o=require("@mezzanine-ui/react"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@mezzanine-ui/icons"),ee=require("@rytass/bpm-core-client/template");var f={delegationModalFields:`bpm_delegationModalFields_gUlCQ`,delegationFilterArea:`bpm_delegationFilterArea_QDZkw`,memberNameWithTooltip:`bpm_memberNameWithTooltip_RggTW`},p=l.FormFieldLayout.HORIZONTAL,m=[10,20,50],te=[{key:`ALL`,label:`全部`},{key:`ACTIVE`,label:`啟用中`},{key:`REVOKED`,label:`已撤銷`},{key:`EXPIRED`,label:`已過期`}],h=[{id:`ALL`,name:`全部簽核`},{id:`TEMPLATE_LIST`,name:`指定模板`}],g=[{id:`ALL_SCOPES`,name:`全部範圍`,scopeType:null},{id:`ALL`,name:`全部簽核`,scopeType:`ALL`},{id:`TEMPLATE_LIST`,name:`指定模板`,scopeType:`TEMPLATE_LIST`}];function _(){let{member:e}=r.n(),i=e?.memberId??null,[p,_]=(0,a.useState)(null),[y,x]=(0,a.useState)(``),[S,T]=(0,a.useState)(null),[pe,E]=(0,a.useState)(!0),[O,me]=(0,a.useState)(!1),[k,he]=(0,a.useState)([]),[A,ge]=(0,a.useState)(null),[j,_e]=(0,a.useState)(null),[ve,M]=(0,a.useState)(!1),[N,P]=(0,a.useState)(null),[F,I]=(0,a.useState)(`100`),[L,R]=(0,a.useState)(1),[z,ye]=(0,a.useState)(10),[B,be]=(0,a.useState)(`ALL`),[xe,Se]=(0,a.useState)(0),[V,Ce]=(0,a.useState)([]),[H,U]=(0,a.useState)(!1),[W,we]=(0,a.useState)([]),[G,Te]=(0,a.useState)(g[0]),[Ee,De]=(0,a.useState)(h[0]),[K,Oe]=(0,a.useState)(``),[ke,Ae]=(0,a.useState)(!1),[je,q]=(0,a.useState)([]),J=(0,a.useCallback)(async()=>{E(!0),T(null);try{let[e,t]=await Promise.all([(0,c.listDelegationRulesPage)({agentMemberId:j?.id??null,includeInactive:!0,page:L,pageSize:z,principalMemberId:A?.id??null,scopeType:G.scopeType,status:B===`ALL`?null:B}),(0,c.searchMembers)(``)]);Ce(e.rules),Se(e.totalCount),he(t.map(ne))}catch(e){T(D(e))}finally{E(!1)}},[j,A,L,z,B,G]);(0,a.useEffect)(()=>{J()},[J]);let Y=(0,a.useMemo)(()=>new Map(k.map(e=>[e.id,e])),[k]),Me=(0,a.useMemo)(()=>V.map(e=>({...e,agentEmail:Y.get(e.agentMemberId)?.email??null,agentName:Y.get(e.agentMemberId)?.displayName??e.agentMemberId,key:e.id,principalEmail:Y.get(e.principalMemberId)?.email??null,principalName:Y.get(e.principalMemberId)?.displayName??e.principalMemberId,scopeLabel:le(e)})),[Y,V]),X=h.find(e=>e.id===Ee.id)??h[0],Ne=(0,a.useMemo)(()=>[{key:`principal`,render:e=>(0,s.jsx)(b,{email:e.principalEmail,name:e.principalName}),title:`原簽核人`,width:220},{key:`agent`,render:e=>(0,s.jsx)(b,{email:e.agentEmail,name:e.agentName}),title:`代理人`,width:220},{dataIndex:`scopeLabel`,key:`scope`,title:`代理範圍`,width:220},{key:`status`,render:e=>(0,s.jsx)(ue,{status:e.status}),title:`狀態`,width:120},{dataIndex:`priority`,key:`priority`,title:`優先序`,width:100},{key:`startAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.startAt)}),title:`開始時間`,width:220},{key:`endAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:e.endAt?n.t(e.endAt):`-`}),title:`結束時間`,width:220}],[]),Pe=(0,a.useCallback)(async e=>{if(i){T(null);try{await(0,c.revokeDelegationRule)({id:e,revokedByMemberId:i}),await J()}catch(e){T(D(e))}}},[i,J]),Fe=(0,a.useMemo)(()=>({render:e=>e.status===`ACTIVE`?[{name:`撤銷`,onClick:()=>void Pe(e.id)}]:[],variant:`destructive-secondary`,width:88}),[Pe]);async function Z(e){me(!0);try{he((await(0,c.searchMembers)(e)).map(ne))}catch(e){T(D(e))}finally{me(!1)}}async function Q(e,t=W){Ae(!0);try{let n=(await(0,ee.listApprovalTemplates)()).map(re);q(oe(t,ae(n,e)))}catch(e){T(D(e))}finally{Ae(!1)}}function Ie(){_(null),x(``),P(null),I(`100`),we([]),De(h[0]),Oe(``),q([]),Q(``,[]),M(!0)}function $(){H||M(!1)}async function Le(){if(i){if(!N||!p)T(`請選擇原簽核人與代理人`);else if(X.id===`TEMPLATE_LIST`&&W.length<1)T(`請選擇至少一個簽核模板`);else if(fe(K,y))T(`結束時間必須晚於起始時間`);else{U(!0),T(null);try{await(0,c.createDelegationRule)({agentMemberId:p.id,createdByMemberId:i,endAt:y||null,principalMemberId:N.id,priority:Number(F)||100,requiresConfirmation:!1,scopeConditionCel:null,scopeConditionDialect:`cel-v2`,scopeTemplateIds:X.id===`TEMPLATE_LIST`?W.map(e=>e.id):[],scopeType:X.id,startAt:K||null}),M(!1),L===1?await J():R(1)}catch(e){T(D(e))}finally{U(!1)}}}}return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.PageHeader,{children:(0,s.jsx)(u.default,{description:`設定簽核代理規則,讓符合範圍的待簽任務自動改派給代理人。`,title:`代理設定`,children:(0,s.jsx)(o.Button,{icon:d.PlusIcon,iconType:`leading`,onClick:Ie,variant:`base-primary`,children:`建立代理`})})}),(0,s.jsx)(o.SectionGroup,{children:(0,s.jsxs)(o.Section,{filterArea:(0,s.jsx)(o.FilterArea,{className:f.delegationFilterArea,children:(0,s.jsxs)(o.FilterLine,{children:[(0,s.jsx)(o.Filter,{span:2,children:(0,s.jsx)(v,{hideLabel:!0,label:`原簽核人`,loading:O,name:`principalFilterMemberId`,onChange:e=>{ge(e),R(1)},onSearch:Z,options:k,required:!1,layout:l.FormFieldLayout.VERTICAL,size:`sub`,value:A})}),(0,s.jsx)(o.Filter,{span:2,children:(0,s.jsx)(v,{hideLabel:!0,label:`代理人`,loading:O,name:`agentFilterMemberId`,onChange:e=>{_e(e),R(1)},onSearch:Z,options:k,required:!1,layout:l.FormFieldLayout.VERTICAL,size:`sub`,value:j})}),(0,s.jsx)(o.Filter,{span:2,children:(0,s.jsx)(o.FormField,{fullWidth:!0,layout:l.FormFieldLayout.VERTICAL,name:`scopeFilterType`,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>{Te(ce(e)),R(1)},options:[...g],placeholder:`代理範圍`,size:`sub`,value:G})})})]})}),tab:(0,s.jsx)(o.Tab,{activeKey:B,onChange:e=>{be(de(e)),R(1)},children:te.map(e=>(0,s.jsx)(o.TabItem,{children:e.label},e.key))}),children:[S?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:S}):null,(0,s.jsx)(o.Table,{actions:Fe,columns:Ne,dataSource:Me,fullWidth:!0,loading:pe,pagination:{current:L,onChange:e=>{R(e)},onChangePageSize:e=>{R(1),ye(e)},pageSize:z,pageSizeLabel:`每頁筆數`,pageSizeOptions:m,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:xe}})]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!N||!p},confirmText:`建立代理`,loading:H,modalType:`standard`,onCancel:$,onClose:$,onConfirm:()=>void Le(),open:ve,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`代理生效後,後續建立的待簽任務會依範圍自動指派。`,title:`建立代理`,children:(0,s.jsxs)(`div`,{className:f.delegationModalFields,children:[(0,s.jsx)(v,{label:`原簽核人`,loading:O,name:`principalMemberId`,onChange:P,onSearch:Z,options:k,value:N}),(0,s.jsx)(v,{label:`代理人`,loading:O,name:`agentMemberId`,onChange:_,onSearch:Z,options:k,value:p}),(0,s.jsx)(t.t,{label:`代理範圍`,name:`scopeType`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>De(se(e)),options:[...h],value:X})}),X.id===`TEMPLATE_LIST`?(0,s.jsx)(t.t,{label:`簽核模板`,name:`scopeTemplateIds`,required:!0,children:(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的模板`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`scopeTemplateIds`,spellCheck:!1},loading:ke,loadingText:`搜尋模板中...`,mode:`multiple`,onChange:e=>{let t=ie(e);we(t),q(e=>oe(t,e))},onSearch:Q,onVisibilityChange:e=>{e&&Q(``)},options:[...je],overflowStrategy:`wrap`,placeholder:`搜尋並選取簽核模板`,searchDebounceTime:300,value:[...W]})}):null,(0,s.jsx)(t.t,{hintText:`數字越大越優先。同一位被代理人同時命中多條規則時,採用優先序最高的那條;優先序相同時採用較早建立的。`,label:`優先序`,name:`priority`,children:(0,s.jsx)(o.Input,{fullWidth:!0,onChange:e=>I(e.target.value),value:F,variant:`base`})}),(0,s.jsx)(t.t,{label:`起始時間`,name:`startAt`,children:(0,s.jsx)(o.DateTimePicker,{formatDate:`YYYY-MM-DD`,formatTime:`HH:mm`,fullWidth:!0,hideSecond:!0,onChange:e=>Oe(w(e)),placeholderLeft:`留空立即生效`,placeholderRight:`選擇時間`,value:C(K)})}),(0,s.jsx)(t.t,{label:`結束時間`,name:`endAt`,children:(0,s.jsx)(o.DateTimePicker,{formatDate:`YYYY-MM-DD`,formatTime:`HH:mm`,fullWidth:!0,hideSecond:!0,onChange:e=>x(w(e)),placeholderLeft:`可留空`,placeholderRight:`選擇時間`,value:C(y)})})]})})]})}function v({hideLabel:e=!1,label:n,layout:r=p,loading:i,name:a,onChange:c,onSearch:l,options:u,required:d=!0,size:ee,value:f}){let m=(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:a,spellCheck:!1},loading:i,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>c(y(e)),onSearch:l,onSearchTextChange:e=>c(x(e,u)),onVisibilityChange:e=>{e&&l(``)},options:[...u],placeholder:e?n:`搜尋姓名或信箱`,searchDebounceTime:300,size:ee,value:f});return e?(0,s.jsx)(o.FormField,{fullWidth:!0,layout:r,name:a,children:m}):(0,s.jsx)(t.t,{label:n,layout:r,name:a,required:d,children:m})}function ne(e){return{displayName:e.name,email:e.email,id:e.memberId,name:i.t(e.name,e.email,`dot`)}}function y(e){if(!O(e))return null;let t=e.id,n=e.name,r=e.email,i=e.displayName;return typeof t==`string`&&typeof n==`string`?{displayName:typeof i==`string`?i:n,email:typeof r==`string`?r:null,id:t,name:n}:null}function b({email:e,name:t}){return e?(0,s.jsx)(o.Tooltip,{title:e,children:({ref:e,...n})=>(0,s.jsx)(`span`,{...n,className:f.memberNameWithTooltip,ref:e,children:t})}):(0,s.jsx)(`span`,{children:t})}function x(e,t){let n=e.trim().toLocaleLowerCase();if(!n)return null;let r=t.filter(e=>[e.id,e.name,e.email??``].some(e=>e.toLocaleLowerCase().includes(n)));return r.length===1?r[0]??null:null}function re(e){return{id:e.id,name:e.name}}function ie(e){return e.flatMap(e=>{if(!O(e))return[];let t=e.id,n=e.name;return typeof t==`string`&&typeof n==`string`?[{id:t,name:n}]:[]})}function ae(e,t){let n=t.trim().toLocaleLowerCase();return n?e.filter(e=>[e.id,e.name].some(e=>e.toLocaleLowerCase().includes(n))):e}function oe(e,t){return[...e,...t].reduce((e,t)=>e.some(e=>e.id===t.id)?e:[...e,t],[])}function se(e){return!O(e)||!S(e.id)?h[0]:h.find(t=>t.id===e.id)??h[0]}function ce(e){if(!O(e))return g[0];let t=e.id;return g.find(e=>e.id===t)??g[0]}function S(e){return e===`ALL`||e===`TEMPLATE_LIST`}function le(e){return e.scopeType===`ALL`?`全部簽核`:e.scopeType===`TEMPLATE_LIST`?`指定模板:${e.scopeTemplateIds.length}`:e.scopeConditionCel?`條件(${e.scopeConditionDialect}):${e.scopeConditionCel}`:`條件式`}function ue({status:e}){return e===`ACTIVE`?(0,s.jsx)(o.Badge,{size:`sub`,text:`啟用中`,variant:`dot-success`}):e===`REVOKED`?(0,s.jsx)(o.Badge,{size:`sub`,text:`已撤銷`,variant:`dot-inactive`}):e===`EXPIRED`?(0,s.jsx)(o.Badge,{size:`sub`,text:`已過期`,variant:`dot-warning`}):(0,s.jsx)(o.Badge,{size:`sub`,text:e,variant:`dot-info`})}function de(e){return e===`ACTIVE`||e===`REVOKED`||e===`EXPIRED`?e:`ALL`}function C(e){let t=e?T(e):null;return t?`${pe(t)}T${E(t.getHours())}:${E(t.getMinutes())}`:void 0}function w(e){let t=e?T(e):null;return t?t.toISOString():``}function fe(e,t){if(!e||!t)return!1;let n=T(e),r=T(t);return!!n&&!!r&&r.getTime()<=n.getTime()}function T(e){if(e.endsWith(`Z`)||/[+-]\d{2}:\d{2}$/.test(e)){let t=new Date(e);return Number.isNaN(t.getTime())?null:t}let[t=``,n=`00:00`]=e.split(`T`),[r=0,i=1,a=1]=t.split(`-`).map(Number),[o=0,s=0]=n.split(`:`).map(Number),c=new Date(r,i-1,a,o,s);return Number.isNaN(c.getTime())?null:c}function pe(e){return`${e.getFullYear()}-${E(e.getMonth()+1)}-${E(e.getDate())}`}function E(e){return String(e).padStart(2,`0`)}function D(e){return e instanceof Error?e.message:`發生未知錯誤`}function O(e){return typeof e==`object`&&!!e}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return _}});
|
|
2
|
-
//# sourceMappingURL=delegations-
|
|
1
|
+
"use client";require('../delegations.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./bpm-form-field-Bc6k4ZEO.cjs"),n=require("./format-date-time-D-cx5M8z.cjs"),r=require("./auth-provider-4BeCw7cI.cjs"),i=require("./format-member-label-t7ANTF62.cjs");let a=require("react"),o=require("@mezzanine-ui/react"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);let d=require("@rytass/bpm-core-client/template"),ee=require("@mezzanine-ui/icons");var f={delegationModalFields:`bpm_delegationModalFields_gUlCQ`,delegationFilterArea:`bpm_delegationFilterArea_QDZkw`,memberNameWithTooltip:`bpm_memberNameWithTooltip_RggTW`},p=l.FormFieldLayout.HORIZONTAL,m=[10,20,50],te=[{key:`ALL`,label:`全部`},{key:`ACTIVE`,label:`啟用中`},{key:`REVOKED`,label:`已撤銷`},{key:`EXPIRED`,label:`已過期`}],h=[{id:`ALL`,name:`全部簽核`},{id:`TEMPLATE_LIST`,name:`指定模板`}],g=[{id:`ALL_SCOPES`,name:`全部範圍`,scopeType:null},{id:`ALL`,name:`全部簽核`,scopeType:`ALL`},{id:`TEMPLATE_LIST`,name:`指定模板`,scopeType:`TEMPLATE_LIST`}];function _(){let{member:e}=r.n(),i=e?.memberId??null,[p,_]=(0,a.useState)(null),[y,x]=(0,a.useState)(``),[S,T]=(0,a.useState)(null),[pe,E]=(0,a.useState)(!0),[O,me]=(0,a.useState)(!1),[k,he]=(0,a.useState)([]),[A,ge]=(0,a.useState)(null),[j,_e]=(0,a.useState)(null),[ve,M]=(0,a.useState)(!1),[N,P]=(0,a.useState)(null),[F,I]=(0,a.useState)(`100`),[L,R]=(0,a.useState)(1),[z,ye]=(0,a.useState)(10),[B,be]=(0,a.useState)(`ALL`),[xe,Se]=(0,a.useState)(0),[V,Ce]=(0,a.useState)([]),[H,U]=(0,a.useState)(!1),[W,we]=(0,a.useState)([]),[G,Te]=(0,a.useState)(g[0]),[Ee,De]=(0,a.useState)(h[0]),[K,Oe]=(0,a.useState)(``),[ke,Ae]=(0,a.useState)(!1),[je,q]=(0,a.useState)([]),J=(0,a.useCallback)(async()=>{E(!0),T(null);try{let[e,t]=await Promise.all([(0,c.listDelegationRulesPage)({agentMemberId:j?.id??null,includeInactive:!0,page:L,pageSize:z,principalMemberId:A?.id??null,scopeType:G.scopeType,status:B===`ALL`?null:B}),(0,c.searchMembers)(``)]);Ce(e.rules),Se(e.totalCount),he(t.map(ne))}catch(e){T(D(e))}finally{E(!1)}},[j,A,L,z,B,G]);(0,a.useEffect)(()=>{J()},[J]);let Y=(0,a.useMemo)(()=>new Map(k.map(e=>[e.id,e])),[k]),Me=(0,a.useMemo)(()=>V.map(e=>({...e,agentEmail:Y.get(e.agentMemberId)?.email??null,agentName:Y.get(e.agentMemberId)?.displayName??e.agentMemberId,key:e.id,principalEmail:Y.get(e.principalMemberId)?.email??null,principalName:Y.get(e.principalMemberId)?.displayName??e.principalMemberId,scopeLabel:le(e)})),[Y,V]),X=h.find(e=>e.id===Ee.id)??h[0],Ne=(0,a.useMemo)(()=>[{key:`principal`,render:e=>(0,s.jsx)(b,{email:e.principalEmail,name:e.principalName}),title:`原簽核人`,width:220},{key:`agent`,render:e=>(0,s.jsx)(b,{email:e.agentEmail,name:e.agentName}),title:`代理人`,width:220},{dataIndex:`scopeLabel`,key:`scope`,title:`代理範圍`,width:220},{key:`status`,render:e=>(0,s.jsx)(ue,{status:e.status}),title:`狀態`,width:120},{dataIndex:`priority`,key:`priority`,title:`優先序`,width:100},{key:`startAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.startAt)}),title:`開始時間`,width:220},{key:`endAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:e.endAt?n.t(e.endAt):`-`}),title:`結束時間`,width:220}],[]),Pe=(0,a.useCallback)(async e=>{if(i){T(null);try{await(0,c.revokeDelegationRule)({id:e,revokedByMemberId:i}),await J()}catch(e){T(D(e))}}},[i,J]),Fe=(0,a.useMemo)(()=>({render:e=>e.status===`ACTIVE`?[{name:`撤銷`,onClick:()=>void Pe(e.id)}]:[],variant:`destructive-secondary`,width:88}),[Pe]);async function Z(e){me(!0);try{he((await(0,c.searchMembers)(e)).map(ne))}catch(e){T(D(e))}finally{me(!1)}}async function Q(e,t=W){Ae(!0);try{let n=(await(0,d.listApprovalTemplates)()).map(re);q(oe(t,ae(n,e)))}catch(e){T(D(e))}finally{Ae(!1)}}function Ie(){_(null),x(``),P(null),I(`100`),we([]),De(h[0]),Oe(``),q([]),Q(``,[]),M(!0)}function $(){H||M(!1)}async function Le(){if(i){if(!N||!p)T(`請選擇原簽核人與代理人`);else if(X.id===`TEMPLATE_LIST`&&W.length<1)T(`請選擇至少一個簽核模板`);else if(fe(K,y))T(`結束時間必須晚於起始時間`);else{U(!0),T(null);try{await(0,c.createDelegationRule)({agentMemberId:p.id,createdByMemberId:i,endAt:y||null,principalMemberId:N.id,priority:Number(F)||100,requiresConfirmation:!1,scopeConditionCel:null,scopeConditionDialect:`cel-v2`,scopeTemplateIds:X.id===`TEMPLATE_LIST`?W.map(e=>e.id):[],scopeType:X.id,startAt:K||null}),M(!1),L===1?await J():R(1)}catch(e){T(D(e))}finally{U(!1)}}}}return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.PageHeader,{children:(0,s.jsx)(u.default,{description:`設定簽核代理規則,讓符合範圍的待簽任務自動改派給代理人。`,title:`代理設定`,children:(0,s.jsx)(o.Button,{icon:ee.PlusIcon,iconType:`leading`,onClick:Ie,variant:`base-primary`,children:`建立代理`})})}),(0,s.jsx)(o.SectionGroup,{children:(0,s.jsxs)(o.Section,{filterArea:(0,s.jsx)(o.FilterArea,{className:f.delegationFilterArea,children:(0,s.jsxs)(o.FilterLine,{children:[(0,s.jsx)(o.Filter,{span:2,children:(0,s.jsx)(v,{hideLabel:!0,label:`原簽核人`,loading:O,name:`principalFilterMemberId`,onChange:e=>{ge(e),R(1)},onSearch:Z,options:k,required:!1,layout:l.FormFieldLayout.VERTICAL,size:`sub`,value:A})}),(0,s.jsx)(o.Filter,{span:2,children:(0,s.jsx)(v,{hideLabel:!0,label:`代理人`,loading:O,name:`agentFilterMemberId`,onChange:e=>{_e(e),R(1)},onSearch:Z,options:k,required:!1,layout:l.FormFieldLayout.VERTICAL,size:`sub`,value:j})}),(0,s.jsx)(o.Filter,{span:2,children:(0,s.jsx)(o.FormField,{fullWidth:!0,layout:l.FormFieldLayout.VERTICAL,name:`scopeFilterType`,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>{Te(ce(e)),R(1)},options:[...g],placeholder:`代理範圍`,size:`sub`,value:G})})})]})}),tab:(0,s.jsx)(o.Tab,{activeKey:B,onChange:e=>{be(de(e)),R(1)},children:te.map(e=>(0,s.jsx)(o.TabItem,{children:e.label},e.key))}),children:[S?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:S}):null,(0,s.jsx)(o.Table,{actions:Fe,columns:Ne,dataSource:Me,fullWidth:!0,loading:pe,pagination:{current:L,onChange:e=>{R(e)},onChangePageSize:e=>{R(1),ye(e)},pageSize:z,pageSizeLabel:`每頁筆數`,pageSizeOptions:m,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:xe}})]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!N||!p},confirmText:`建立代理`,loading:H,modalType:`standard`,onCancel:$,onClose:$,onConfirm:()=>void Le(),open:ve,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`代理生效後,後續建立的待簽任務會依範圍自動指派。`,title:`建立代理`,children:(0,s.jsxs)(`div`,{className:f.delegationModalFields,children:[(0,s.jsx)(v,{label:`原簽核人`,loading:O,name:`principalMemberId`,onChange:P,onSearch:Z,options:k,value:N}),(0,s.jsx)(v,{label:`代理人`,loading:O,name:`agentMemberId`,onChange:_,onSearch:Z,options:k,value:p}),(0,s.jsx)(t.t,{label:`代理範圍`,name:`scopeType`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>De(se(e)),options:[...h],value:X})}),X.id===`TEMPLATE_LIST`?(0,s.jsx)(t.t,{label:`簽核模板`,name:`scopeTemplateIds`,required:!0,children:(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的模板`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`scopeTemplateIds`,spellCheck:!1},loading:ke,loadingText:`搜尋模板中...`,mode:`multiple`,onChange:e=>{let t=ie(e);we(t),q(e=>oe(t,e))},onSearch:Q,onVisibilityChange:e=>{e&&Q(``)},options:[...je],overflowStrategy:`wrap`,placeholder:`搜尋並選取簽核模板`,searchDebounceTime:300,value:[...W]})}):null,(0,s.jsx)(t.t,{hintText:`數字越大越優先。同一位被代理人同時命中多條規則時,採用優先序最高的那條;優先序相同時採用較早建立的。`,label:`優先序`,name:`priority`,children:(0,s.jsx)(o.Input,{fullWidth:!0,onChange:e=>I(e.target.value),value:F,variant:`base`})}),(0,s.jsx)(t.t,{label:`起始時間`,name:`startAt`,children:(0,s.jsx)(o.DateTimePicker,{formatDate:`YYYY-MM-DD`,formatTime:`HH:mm`,fullWidth:!0,hideSecond:!0,onChange:e=>Oe(w(e)),placeholderLeft:`留空立即生效`,placeholderRight:`選擇時間`,value:C(K)})}),(0,s.jsx)(t.t,{label:`結束時間`,name:`endAt`,children:(0,s.jsx)(o.DateTimePicker,{formatDate:`YYYY-MM-DD`,formatTime:`HH:mm`,fullWidth:!0,hideSecond:!0,onChange:e=>x(w(e)),placeholderLeft:`可留空`,placeholderRight:`選擇時間`,value:C(y)})})]})})]})}function v({hideLabel:e=!1,label:n,layout:r=p,loading:i,name:a,onChange:c,onSearch:l,options:u,required:d=!0,size:ee,value:f}){let m=(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:a,spellCheck:!1},loading:i,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>c(y(e)),onSearch:l,onSearchTextChange:e=>c(x(e,u)),onVisibilityChange:e=>{e&&l(``)},options:[...u],placeholder:e?n:`搜尋姓名或信箱`,searchDebounceTime:300,size:ee,value:f});return e?(0,s.jsx)(o.FormField,{fullWidth:!0,layout:r,name:a,children:m}):(0,s.jsx)(t.t,{label:n,layout:r,name:a,required:d,children:m})}function ne(e){return{displayName:e.name,email:e.email,id:e.memberId,name:i.t(e.name,e.email,`dot`)}}function y(e){if(!O(e))return null;let t=e.id,n=e.name,r=e.email,i=e.displayName;return typeof t==`string`&&typeof n==`string`?{displayName:typeof i==`string`?i:n,email:typeof r==`string`?r:null,id:t,name:n}:null}function b({email:e,name:t}){return e?(0,s.jsx)(o.Tooltip,{title:e,children:({ref:e,...n})=>(0,s.jsx)(`span`,{...n,className:f.memberNameWithTooltip,ref:e,children:t})}):(0,s.jsx)(`span`,{children:t})}function x(e,t){let n=e.trim().toLocaleLowerCase();if(!n)return null;let r=t.filter(e=>[e.id,e.name,e.email??``].some(e=>e.toLocaleLowerCase().includes(n)));return r.length===1?r[0]??null:null}function re(e){return{id:e.id,name:e.name}}function ie(e){return e.flatMap(e=>{if(!O(e))return[];let t=e.id,n=e.name;return typeof t==`string`&&typeof n==`string`?[{id:t,name:n}]:[]})}function ae(e,t){let n=t.trim().toLocaleLowerCase();return n?e.filter(e=>[e.id,e.name].some(e=>e.toLocaleLowerCase().includes(n))):e}function oe(e,t){return[...e,...t].reduce((e,t)=>e.some(e=>e.id===t.id)?e:[...e,t],[])}function se(e){return!O(e)||!S(e.id)?h[0]:h.find(t=>t.id===e.id)??h[0]}function ce(e){if(!O(e))return g[0];let t=e.id;return g.find(e=>e.id===t)??g[0]}function S(e){return e===`ALL`||e===`TEMPLATE_LIST`}function le(e){return e.scopeType===`ALL`?`全部簽核`:e.scopeType===`TEMPLATE_LIST`?`指定模板:${e.scopeTemplateIds.length}`:e.scopeConditionCel?`條件(${e.scopeConditionDialect}):${e.scopeConditionCel}`:`條件式`}function ue({status:e}){return e===`ACTIVE`?(0,s.jsx)(o.Badge,{size:`sub`,text:`啟用中`,variant:`dot-success`}):e===`REVOKED`?(0,s.jsx)(o.Badge,{size:`sub`,text:`已撤銷`,variant:`dot-inactive`}):e===`EXPIRED`?(0,s.jsx)(o.Badge,{size:`sub`,text:`已過期`,variant:`dot-warning`}):(0,s.jsx)(o.Badge,{size:`sub`,text:e,variant:`dot-info`})}function de(e){return e===`ACTIVE`||e===`REVOKED`||e===`EXPIRED`?e:`ALL`}function C(e){let t=e?T(e):null;return t?`${pe(t)}T${E(t.getHours())}:${E(t.getMinutes())}`:void 0}function w(e){let t=e?T(e):null;return t?t.toISOString():``}function fe(e,t){if(!e||!t)return!1;let n=T(e),r=T(t);return!!n&&!!r&&r.getTime()<=n.getTime()}function T(e){if(e.endsWith(`Z`)||/[+-]\d{2}:\d{2}$/.test(e)){let t=new Date(e);return Number.isNaN(t.getTime())?null:t}let[t=``,n=`00:00`]=e.split(`T`),[r=0,i=1,a=1]=t.split(`-`).map(Number),[o=0,s=0]=n.split(`:`).map(Number),c=new Date(r,i-1,a,o,s);return Number.isNaN(c.getTime())?null:c}function pe(e){return`${e.getFullYear()}-${E(e.getMonth()+1)}-${E(e.getDate())}`}function E(e){return String(e).padStart(2,`0`)}function D(e){return e instanceof Error?e.message:`發生未知錯誤`}function O(e){return typeof e==`object`&&!!e}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return _}});
|
|
2
|
+
//# sourceMappingURL=delegations-ClRCwD1I.cjs.map
|