@rytass/bpm-core-react 0.21.0 → 0.21.2
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 +57 -0
- package/dist/chunks/{FormBuilderView-WtC2iW5f.js → FormBuilderView-6KdApi-D.js} +8 -8
- package/dist/chunks/{FormBuilderView-WtC2iW5f.js.map → FormBuilderView-6KdApi-D.js.map} +1 -1
- package/dist/chunks/{FormBuilderView-DjPGrOJ2.cjs → FormBuilderView-CGKkuVFi.cjs} +3 -3
- package/dist/chunks/{FormBuilderView-DjPGrOJ2.cjs.map → FormBuilderView-CGKkuVFi.cjs.map} +1 -1
- package/dist/chunks/{approval-instance-list-page-Bth7Raya.js → approval-instance-list-page-BI5fIXc-.js} +26 -26
- package/dist/chunks/{approval-instance-list-page-Bth7Raya.js.map → approval-instance-list-page-BI5fIXc-.js.map} +1 -1
- package/dist/chunks/{approval-instance-list-page-Dcvo6TrT.cjs → approval-instance-list-page-Cv5I1YPX.cjs} +2 -2
- package/dist/chunks/{approval-instance-list-page-Dcvo6TrT.cjs.map → approval-instance-list-page-Cv5I1YPX.cjs.map} +1 -1
- package/dist/chunks/compose-CtWuunwB.cjs +2 -0
- package/dist/chunks/compose-CtWuunwB.cjs.map +1 -0
- package/dist/chunks/{compose-DZvIspW3.js → compose-M-GR6smM.js} +4 -4
- package/dist/chunks/{compose-DZvIspW3.js.map → compose-M-GR6smM.js.map} +1 -1
- package/dist/chunks/{designer-CWubIE69.js → designer-BnMeiMVe.js} +2192 -1609
- package/dist/chunks/designer-BnMeiMVe.js.map +1 -0
- package/dist/chunks/designer-D6fCDq_q.cjs +69 -0
- package/dist/chunks/designer-D6fCDq_q.cjs.map +1 -0
- package/dist/chunks/detail-C5KrUC7s.cjs +5 -0
- package/dist/chunks/detail-C5KrUC7s.cjs.map +1 -0
- package/dist/chunks/{detail-Bv90gvy0.js → detail-Dnc4PPWO.js} +768 -742
- package/dist/chunks/detail-Dnc4PPWO.js.map +1 -0
- package/dist/chunks/{instance-error-message-CAP1vJhX.js → instance-error-message-BEM4O_Kj.js} +6 -2
- 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/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/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/views/cc/index.cjs +1 -1
- package/dist/views/cc/index.js +1 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -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.js +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/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.js +1 -1
- 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/package.json +3 -3
- package/dist/chunks/compose-BKUTsB2W.cjs +0 -2
- package/dist/chunks/compose-BKUTsB2W.cjs.map +0 -1
- package/dist/chunks/designer-CWubIE69.js.map +0 -1
- package/dist/chunks/designer-C_m8DmMl.cjs +0 -69
- package/dist/chunks/designer-C_m8DmMl.cjs.map +0 -1
- package/dist/chunks/detail-Bv90gvy0.js.map +0 -1
- package/dist/chunks/detail-DNzqesdI.cjs +0 -5
- package/dist/chunks/detail-DNzqesdI.cjs.map +0 -1
- package/dist/chunks/instance-error-message-BW464LRQ.cjs +0 -2
- package/dist/chunks/instance-error-message-BW464LRQ.cjs.map +0 -1
- package/dist/chunks/instance-error-message-CAP1vJhX.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":"approval-instance-list-page-Dcvo6TrT.cjs","names":["APPROVAL_INSTANCE_SORT_TIME_FIELDS","isFilterableFieldSortable","Input","Filter","FormField","ControlFieldSlotLayout","FormFieldLayout","Select","DateRangePicker","formatDatePickerValue","DateTimeRangePicker","formatDateTimePickerValue","useRouterAdapter","useBPMRoutes","useState","useRef","useMemo","readFilterableFieldPaths","useCallback","listApprovalInstancesPage","listApprovalTemplates","readApprovalTemplateCurrentFormSchema","resolveMembers","Typography","formatDateTime","FilterLine","Filter","FormField","ControlFieldSlotLayout","FormFieldLayout","Input","Select","RadioGroup","_Fragment","PageHeader","ContentHeader","SectionGroup","Section","FilterArea","styles","Table","readApprovalInstanceCaseTitle","require_rolldown_runtime","require_router_adapter","require_routes_config","require_format_date_time","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_rytass_bpm_core_client_template","_rytass_bpm_core_shared","_rytass_bpm_core_client_form","readFieldFilterControl","item","EMPTY_FIELD_FILTER_DRAFT","DECIMAL_PATTERN","isDecimalText","readDecimal","value","plain","readIdList","text","toApprovalInstanceFieldFilter","draft","ids","from","to","buildApprovalInstanceFieldFilters","paths","filter","drafts","DEFAULT_SORT_DRAFT","DEFAULT_SORT_OPTION","SORT_TIME_LABELS","readSortFieldOptions","timeOptions","field","fieldOptions","templateSelected","isSortFieldAvailable","toApprovalInstanceSort","BOOLEAN_CHOICES","readFieldFilterElements","change","onDraftChange","next","control","renderFilter","event","readNumberHint","renderControl","readIdNoun","key","choices","option","selected","label","choice","target","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","FIELD_FILTERS_PER_LINE","STATE_FILTER_OPTIONS","SORT_DIRECTION_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","templates","setTemplates","templateId","setTemplateId","templateSchema","setTemplateSchema","schemaLoading","setSchemaLoading","schemaError","setSchemaError","fieldDrafts","setFieldDrafts","sortDraft","setSortDraft","refreshRequestIdRef","fieldPaths","fieldFilters","sort","sortOptions","refreshInstances","requestId","result","readApprovalInstanceRow","requestError","readErrorMessage","view","cancelled","loaded","schema","schemaLoadError","initiatorMemberIds","row","profiles","profile","handleTemplateChange","previous","handleFilterReset","handleFilterSubmit","handleFieldDraftChange","path","columns","readInstanceStateColor","record","readInitiatorLabel","tableActions","templateOptions","template","selectedTemplate","fieldFilterLines","chunkElements","elements","index","sortFieldChoices","selectedSortField","searchFilterLine","searchPlaceholder","readSelectedStateFilterOption","readStateFilterLabel","sortFilterLine","readSortDirection","emptyMessage","page","pageSize","total","items","last","lines","size","instance","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-field-filters.ts","../../src/components/approval-instance-field-filter-controls.tsx","../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":["import {\n APPROVAL_INSTANCE_SORT_TIME_FIELDS,\n isFilterableFieldSortable,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormFieldOption,\n} from '@rytass/bpm-core-shared';\n\n/**\n * Pure logic behind the list page's field filters (ADR 25 §7). Turns the\n * filterable fields of a template's schema into controls, and the control\n * values into `fieldFilters` and `sort` for `listApprovalInstancesPage`. The\n * operator for each control is one `readFilterOperatorsForFieldType` allows.\n */\n\n/** Which control a filterable field gets on the list page. */\nexport type FieldFilterControl =\n /** Text, textarea and dynamic (data-source) options: CONTAINS on a text input. */\n | { readonly kind: 'contains' }\n /** Static options: IN on a multi-select. */\n | { readonly kind: 'option-in'; readonly options: readonly FormFieldOption[] }\n /** Member and org unit: IN on comma-separated ids (no picker yet). */\n | { readonly kind: 'id-in' }\n /** Number and money: RANGE with two number inputs. */\n | { readonly kind: 'number-range' }\n /** Date: RANGE with a date range picker. */\n | { readonly kind: 'date-range' }\n /** Datetime: RANGE with a datetime range picker. */\n | { readonly kind: 'datetime-range' }\n /** Boolean: EQUALS with a yes / no select. */\n | { readonly kind: 'boolean' };\n\nexport function readFieldFilterControl(\n item: FilterableFieldPath,\n): FieldFilterControl {\n switch (item.kind) {\n case 'number':\n return { kind: 'number-range' };\n case 'date':\n return { kind: 'date-range' };\n case 'datetime':\n return { kind: 'datetime-range' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'member':\n case 'org_unit':\n return { kind: 'id-in' };\n case 'option':\n return item.staticOptions\n ? { kind: 'option-in', options: item.staticOptions }\n : { kind: 'contains' };\n case 'text':\n return { kind: 'contains' };\n }\n}\n\n/**\n * One field's entered condition. `from` and `to` hold canonical values\n * (decimal string, `YYYY-MM-DD`, or ISO 8601) as the controls produce them.\n */\nexport interface FieldFilterDraft {\n readonly from: string;\n readonly to: string;\n /** CONTAINS text, or comma-separated ids for IN on member and org unit. */\n readonly text: string;\n /** Selected option values (IN), or `['true']` / `['false']` for boolean. */\n readonly values: readonly string[];\n}\n\nexport const EMPTY_FIELD_FILTER_DRAFT: FieldFilterDraft = {\n from: '',\n text: '',\n to: '',\n values: [],\n};\n\n/** Drafts keyed by the field path, so a path can be looked up directly. */\nexport type FieldFilterDrafts = Readonly<Record<string, FieldFilterDraft>>;\n\nconst DECIMAL_PATTERN = /^-?\\d+(\\.\\d+)?$/u;\n\n/**\n * Whether a number control's text is a decimal. Surrounding spaces and\n * thousands separators (`1,000`) are accepted and dropped before sending.\n */\nexport function isDecimalText(value: string): boolean {\n return readDecimal(value) !== null;\n}\n\nfunction readDecimal(value: string): string | null {\n const plain = value.trim().replace(/,/gu, '');\n\n return DECIMAL_PATTERN.test(plain) ? plain : null;\n}\n\nfunction readIdList(text: string): readonly string[] {\n return text\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\n/**\n * The condition one draft asks for, or `null` when it is empty. Empty means\n * no condition, so it must not reach the server as a filter.\n */\nexport function toApprovalInstanceFieldFilter(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n): ApprovalInstanceFieldFilter | null {\n const control = readFieldFilterControl(item);\n\n switch (control.kind) {\n case 'contains': {\n const text = draft.text.trim();\n\n return text\n ? { fieldKey: item.path, operator: 'CONTAINS', values: [text] }\n : null;\n }\n case 'option-in':\n return draft.values.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: [...draft.values] }\n : null;\n case 'id-in': {\n const ids = readIdList(draft.text);\n\n return ids.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: ids }\n : null;\n }\n case 'number-range': {\n const from = readDecimal(draft.from);\n const to = readDecimal(draft.to);\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'date-range':\n case 'datetime-range': {\n const from = draft.from.trim();\n const to = draft.to.trim();\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'boolean': {\n const value = draft.values[0];\n\n return value === 'true' || value === 'false'\n ? { fieldKey: item.path, operator: 'EQUALS', values: [value] }\n : null;\n }\n }\n}\n\n/** Every non-empty condition, in schema order. */\nexport function buildApprovalInstanceFieldFilters(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n): readonly ApprovalInstanceFieldFilter[] {\n return paths.flatMap((item): readonly ApprovalInstanceFieldFilter[] => {\n const filter = toApprovalInstanceFieldFilter(\n item,\n drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT,\n );\n\n return filter ? [filter] : [];\n });\n}\n\n/** The sort the user picked. An empty `field` keeps the server default. */\nexport interface SortDraft {\n readonly direction: ApprovalInstanceSortDirection;\n readonly field: string;\n}\n\nexport const DEFAULT_SORT_DRAFT: SortDraft = { direction: 'DESC', field: '' };\n\nexport interface SortFieldOption {\n readonly id: string;\n readonly label: string;\n}\n\nexport const DEFAULT_SORT_OPTION: SortFieldOption = {\n id: '',\n label: '預設(建立時間,新到舊)',\n};\n\nconst SORT_TIME_LABELS: Readonly<\n Record<(typeof APPROVAL_INSTANCE_SORT_TIME_FIELDS)[number], string>\n> = {\n completedAt: '完成時間',\n submittedAt: '送出時間',\n updatedAt: '最後更新',\n};\n\n/**\n * Sort choices. Time fields are always offered. Form fields are offered only\n * with a template selected, because the server needs a template to sort by a\n * form field.\n */\nexport function readSortFieldOptions(\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): readonly SortFieldOption[] {\n const timeOptions = APPROVAL_INSTANCE_SORT_TIME_FIELDS.map(\n (field): SortFieldOption => ({ id: field, label: SORT_TIME_LABELS[field] }),\n );\n const fieldOptions = templateSelected\n ? paths\n .filter(isFilterableFieldSortable)\n .map((item): SortFieldOption => ({ id: item.path, label: item.label }))\n : [];\n\n return [DEFAULT_SORT_OPTION, ...timeOptions, ...fieldOptions];\n}\n\n/** Whether a sort on `field` is valid for the current template selection. */\nexport function isSortFieldAvailable(\n field: string,\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): boolean {\n if (field === '') {\n return true;\n }\n\n if (\n (APPROVAL_INSTANCE_SORT_TIME_FIELDS as readonly string[]).includes(field)\n ) {\n return true;\n }\n\n return templateSelected && paths.some((item) => item.path === field);\n}\n\nexport function toApprovalInstanceSort(\n draft: SortDraft,\n): readonly ApprovalInstanceSort[] | undefined {\n return draft.field === ''\n ? undefined\n : [{ direction: draft.direction, field: draft.field }];\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n DateRangePicker,\n DateTimeRangePicker,\n Filter,\n FormField,\n Input,\n Select,\n type FilterProps,\n} from '@mezzanine-ui/react';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport {\n formatDatePickerValue,\n formatDateTimePickerValue,\n} from '@rytass/bpm-core-client/form';\nimport type { FilterableFieldPath } from '@rytass/bpm-core-shared';\nimport {\n EMPTY_FIELD_FILTER_DRAFT,\n isDecimalText,\n readFieldFilterControl,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n} from './approval-instance-field-filters';\n\nexport type FieldFilterDraftChange = (\n path: string,\n draft: FieldFilterDraft,\n) => void;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst BOOLEAN_CHOICES: readonly SelectChoice[] = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\n/**\n * One list-page `Filter` per condition the template's filterable fields need.\n * A number field yields two (lower and upper bound) because Mezzanine has no\n * number range control. Returned as elements so the caller can place them\n * directly inside `FilterLine`, which only accepts `Filter` children.\n */\nexport function readFieldFilterElements(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n onDraftChange: FieldFilterDraftChange,\n): readonly ReactElement<FilterProps>[] {\n return paths.flatMap((item): readonly ReactElement<FilterProps>[] => {\n const draft = drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT;\n const change = (next: FieldFilterDraft): void => {\n onDraftChange(item.path, next);\n };\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'number-range') {\n return [\n renderFilter(\n `${item.path}:from`,\n `${item.label}(下限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, from: event.target.value });\n }}\n placeholder={`${item.label}:下限`}\n size=\"sub\"\n value={draft.from}\n variant=\"base\"\n />,\n readNumberHint(draft.from),\n ),\n renderFilter(\n `${item.path}:to`,\n `${item.label}(上限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, to: event.target.value });\n }}\n placeholder={`${item.label}:上限`}\n size=\"sub\"\n value={draft.to}\n variant=\"base\"\n />,\n readNumberHint(draft.to),\n ),\n ];\n }\n\n return [\n renderFilter(\n item.path,\n item.label,\n renderControl(item, draft, change, item.label),\n control.kind === 'id-in'\n ? `多個${readIdNoun(item)}以逗號分隔`\n : undefined,\n ),\n ];\n });\n}\n\nfunction renderFilter(\n key: string,\n label: string,\n control: ReactElement,\n hintText?: string,\n): ReactElement<FilterProps> {\n return (\n <Filter key={key} span={2}>\n <FormField\n fullWidth\n hintText={hintText}\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label={label}\n name={`fieldFilter-${key}`}\n >\n {control}\n </FormField>\n </Filter>\n );\n}\n\n/** What an id-in field holds: members, or org units for an `org_unit` field. */\nfunction readIdNoun(item: FilterableFieldPath): string {\n return item.kind === 'org_unit' ? '組織' : '成員';\n}\n\nfunction readNumberHint(value: string): string | undefined {\n return !value || isDecimalText(value) ? undefined : '請輸入數字';\n}\n\nfunction renderControl(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n change: (next: FieldFilterDraft) => void,\n label: string,\n): ReactElement {\n // The list page hides FormField labels to keep its filter rows compact, so\n // each control names its field in the placeholder, as the state filter does.\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'option-in') {\n const choices = control.options.map((option): SelectChoice => ({\n id: option.value,\n name: option.label,\n }));\n\n return (\n <Select\n clearable\n fullWidth\n mode=\"multiple\"\n onChange={(selected: readonly SelectChoice[]): void => {\n change({ ...draft, values: selected.map((option) => option.id) });\n }}\n options={[...choices]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={choices.filter((choice) => draft.values.includes(choice.id))}\n />\n );\n }\n\n if (control.kind === 'boolean') {\n const selected = BOOLEAN_CHOICES.find((choice) =>\n draft.values.includes(choice.id),\n );\n\n return (\n <Select\n clearable\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n change({ ...draft, values: option ? [option.id] : [] });\n }}\n options={[...BOOLEAN_CHOICES]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={selected ?? null}\n />\n );\n }\n\n if (control.kind === 'date-range') {\n return (\n <DateRangePicker\n clearable\n fullWidth\n inputFromPlaceholder={`${label}:起`}\n inputToPlaceholder=\"迄\"\n onChange={(target?: readonly (string | undefined)[]): void => {\n change({\n ...draft,\n from: formatDatePickerValue(target?.[0]) ?? '',\n to: formatDatePickerValue(target?.[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={draft.from && draft.to ? [draft.from, draft.to] : []}\n />\n );\n }\n\n if (control.kind === 'datetime-range') {\n return (\n <DateTimeRangePicker\n clearable\n fullWidth\n onChange={(value): void => {\n change({\n ...draft,\n from: formatDateTimePickerValue(value[0]) ?? '',\n to: formatDateTimePickerValue(value[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={[draft.from || undefined, draft.to || undefined]}\n />\n );\n }\n\n if (control.kind === 'id-in') {\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:${readIdNoun(item)} ID`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n }\n\n // contains (text, textarea and data-source options)\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:包含`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n}\n",".instanceFilterArea {\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","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n RadioGroup,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n type FilterLineProps,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalTemplates,\n type ApprovalTemplateRecord,\n} from '@rytass/bpm-core-client/template';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n readApprovalTemplateCurrentFormSchema,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readFilterableFieldPaths,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormDefinitionSchema,\n} from '@rytass/bpm-core-shared';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport {\n buildApprovalInstanceFieldFilters,\n DEFAULT_SORT_DRAFT,\n DEFAULT_SORT_OPTION,\n isSortFieldAvailable,\n readSortFieldOptions,\n toApprovalInstanceSort,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n type SortDraft,\n type SortFieldOption,\n} from './approval-instance-field-filters';\nimport { readFieldFilterElements } from './approval-instance-field-filter-controls';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst FIELD_FILTERS_PER_LINE = 3;\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\nconst SORT_DIRECTION_OPTIONS: readonly (SelectChoice & {\n id: ApprovalInstanceSortDirection;\n})[] = [\n { id: 'DESC', name: '新到舊' },\n { id: 'ASC', name: '舊到新' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n *\n * With a template selected, the filter bar also carries one control per\n * filterable field of that template's current form (ADR 25 §7), and the sort\n * may use those fields. Without a template only time fields can sort.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [templateId, setTemplateId] = useState<string | null>(null);\n const [templateSchema, setTemplateSchema] =\n useState<FormDefinitionSchema | null>(null);\n const [schemaLoading, setSchemaLoading] = useState(false);\n const [schemaError, setSchemaError] = useState<string | null>(null);\n const [fieldDrafts, setFieldDrafts] = useState<FieldFilterDrafts>({});\n const [sortDraft, setSortDraft] = useState<SortDraft>(DEFAULT_SORT_DRAFT);\n const refreshRequestIdRef = useRef(0);\n\n const fieldPaths = useMemo(\n (): readonly FilterableFieldPath[] =>\n templateSchema ? readFilterableFieldPaths(templateSchema) : [],\n [templateSchema],\n );\n const fieldFilters = useMemo(\n (): readonly ApprovalInstanceFieldFilter[] | undefined =>\n templateId === null\n ? undefined\n : buildApprovalInstanceFieldFilters(fieldPaths, fieldDrafts),\n [fieldDrafts, fieldPaths, templateId],\n );\n const sort = useMemo(\n (): readonly ApprovalInstanceSort[] | undefined =>\n toApprovalInstanceSort(sortDraft),\n [sortDraft],\n );\n const sortOptions = useMemo(\n (): readonly SortFieldOption[] =>\n readSortFieldOptions(fieldPaths, templateId !== null),\n [fieldPaths, templateId],\n );\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n fieldFilters,\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n sort,\n state: stateFilter.state,\n templateId,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [\n fieldFilters,\n instancePage,\n instancePageSize,\n searchText,\n sort,\n stateFilter,\n templateId,\n view,\n ]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const loaded = await listApprovalTemplates();\n\n if (!cancelled) {\n setTemplates(loaded);\n }\n } catch {\n if (!cancelled) {\n setTemplates([]);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, []);\n\n // Race guard: a schema response for a previously picked template is dropped\n // when the template changes again (cleanup flips `cancelled`).\n useEffect((): (() => void) | void => {\n if (templateId === null) {\n setTemplateSchema(null);\n setSchemaLoading(false);\n setSchemaError(null);\n\n return;\n }\n\n let cancelled = false;\n setSchemaLoading(true);\n setSchemaError(null);\n\n void (async (): Promise<void> => {\n try {\n const schema = await readApprovalTemplateCurrentFormSchema(templateId);\n\n if (!cancelled) {\n setTemplateSchema(schema);\n }\n } catch (schemaLoadError: unknown) {\n if (!cancelled) {\n setTemplateSchema(null);\n setSchemaError(readErrorMessage(schemaLoadError));\n }\n } finally {\n if (!cancelled) {\n setSchemaLoading(false);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [templateId]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const handleTemplateChange = useCallback(\n (option: SelectChoice | null): void => {\n setTemplateId(option?.id ?? null);\n // Drop the previous template's fields at once, so nothing is built from\n // them while the new schema loads.\n setTemplateSchema(null);\n setFieldDrafts({});\n setInstancePage(1);\n // A form-field sort belongs to one template. Time-field sorts survive.\n setSortDraft((previous): SortDraft =>\n isSortFieldAvailable(previous.field, [], false)\n ? previous\n : { ...previous, field: DEFAULT_SORT_DRAFT.field },\n );\n },\n [],\n );\n\n const handleFilterReset = useCallback((): void => {\n setSearchText('');\n setStateFilter(readStateFilterOption(defaultState));\n setTemplateId(null);\n setTemplateSchema(null);\n setFieldDrafts({});\n setSortDraft(DEFAULT_SORT_DRAFT);\n setInstancePage(1);\n }, [defaultState]);\n const handleFilterSubmit = useCallback((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n const handleFieldDraftChange = useCallback(\n (path: string, draft: FieldFilterDraft): void => {\n setFieldDrafts((previous): FieldFilterDrafts => ({\n ...previous,\n [path]: draft,\n }));\n setInstancePage(1);\n },\n [],\n );\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n const templateOptions = useMemo(\n (): readonly SelectChoice[] =>\n templates.map((template) => ({ id: template.id, name: template.name })),\n [templates],\n );\n const selectedTemplate = templateOptions.find(\n (option) => option.id === templateId,\n );\n const fieldFilterLines = useMemo(\n (): readonly ReactElement<FilterLineProps>[] =>\n chunkElements(\n readFieldFilterElements(\n fieldPaths,\n fieldDrafts,\n handleFieldDraftChange,\n ),\n FIELD_FILTERS_PER_LINE,\n ).map((elements, index): ReactElement<FilterLineProps> => (\n <FilterLine key={`field-filter-line-${index}`}>\n {[...elements]}\n </FilterLine>\n )),\n [fieldDrafts, fieldPaths, handleFieldDraftChange],\n );\n const sortFieldChoices = useMemo(\n (): readonly SelectChoice[] =>\n sortOptions.map((option) => ({ id: option.id, name: option.label })),\n [sortOptions],\n );\n const selectedSortField =\n sortFieldChoices.find((option) => option.id === sortDraft.field) ??\n sortFieldChoices.find((option) => option.id === DEFAULT_SORT_OPTION.id);\n\n const searchFilterLine = (\n <FilterLine key=\"search\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"範本\"\n name=\"instanceTemplate\"\n >\n <Select\n clearable\n fullWidth\n onChange={handleTemplateChange}\n options={[...templateOptions]}\n placeholder=\"全部範本\"\n size=\"sub\"\n value={selectedTemplate ?? null}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n const sortFilterLine = (\n <FilterLine key=\"sort\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序欄位\"\n name=\"instanceSortField\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n field: option?.id ?? DEFAULT_SORT_DRAFT.field,\n }));\n setInstancePage(1);\n }}\n options={[...sortFieldChoices]}\n placeholder=\"排序欄位\"\n size=\"sub\"\n value={selectedSortField ?? null}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序方向\"\n name=\"instanceSortDirection\"\n >\n <RadioGroup\n name=\"instanceSortDirection\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n direction: readSortDirection(event.target.value),\n }));\n setInstancePage(1);\n }}\n options={[...SORT_DIRECTION_OPTIONS]}\n size=\"sub\"\n type=\"segment\"\n value={sortDraft.direction}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea\n className={styles.instanceFilterArea}\n onReset={handleFilterReset}\n onSubmit={handleFilterSubmit}\n resetText=\"清除條件\"\n rowAlign=\"end\"\n size=\"sub\"\n submitText=\"重新查詢\"\n >\n {[searchFilterLine, ...fieldFilterLines, sortFilterLine]}\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {schemaError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {schemaError}\n </Typography>\n ) : null}\n {templateId !== null &&\n !schemaLoading &&\n !schemaError &&\n templateSchema &&\n fieldPaths.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此範本沒有可篩選的欄位。\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction chunkElements<T>(\n items: readonly T[],\n size: number,\n): readonly (readonly T[])[] {\n return items.reduce<readonly (readonly T[])[]>(\n (lines, item): readonly (readonly T[])[] => {\n const last = lines[lines.length - 1];\n\n return last && last.length < size\n ? [...lines.slice(0, -1), [...last, item]]\n : [...lines, [item]];\n },\n [],\n );\n}\n\nfunction readSortDirection(value: string): ApprovalInstanceSortDirection {\n return value === 'ASC' ? 'ASC' : 'DESC';\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\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":"approval-instance-list-page-Cv5I1YPX.cjs","names":["APPROVAL_INSTANCE_SORT_TIME_FIELDS","isFilterableFieldSortable","Input","Filter","FormField","ControlFieldSlotLayout","FormFieldLayout","Select","DateRangePicker","formatDatePickerValue","DateTimeRangePicker","formatDateTimePickerValue","useRouterAdapter","useBPMRoutes","useState","useRef","useMemo","readFilterableFieldPaths","useCallback","listApprovalInstancesPage","listApprovalTemplates","readApprovalTemplateCurrentFormSchema","resolveMembers","Typography","formatDateTime","FilterLine","Filter","FormField","ControlFieldSlotLayout","FormFieldLayout","Input","Select","RadioGroup","_Fragment","PageHeader","ContentHeader","SectionGroup","Section","FilterArea","styles","Table","readApprovalInstanceCaseTitle","require_rolldown_runtime","require_router_adapter","require_routes_config","require_format_date_time","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","_rytass_bpm_core_client_workflow","_rytass_bpm_core_shared","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_rytass_bpm_core_client_template","_rytass_bpm_core_client_form","readFieldFilterControl","item","EMPTY_FIELD_FILTER_DRAFT","DECIMAL_PATTERN","isDecimalText","readDecimal","value","plain","readIdList","text","toApprovalInstanceFieldFilter","draft","ids","from","to","buildApprovalInstanceFieldFilters","paths","filter","drafts","DEFAULT_SORT_DRAFT","DEFAULT_SORT_OPTION","SORT_TIME_LABELS","readSortFieldOptions","timeOptions","field","fieldOptions","templateSelected","isSortFieldAvailable","toApprovalInstanceSort","BOOLEAN_CHOICES","readFieldFilterElements","change","onDraftChange","next","control","renderFilter","event","readNumberHint","renderControl","readIdNoun","key","choices","option","selected","label","choice","target","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","FIELD_FILTERS_PER_LINE","STATE_FILTER_OPTIONS","SORT_DIRECTION_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","templates","setTemplates","templateId","setTemplateId","templateSchema","setTemplateSchema","schemaLoading","setSchemaLoading","schemaError","setSchemaError","fieldDrafts","setFieldDrafts","sortDraft","setSortDraft","refreshRequestIdRef","fieldPaths","fieldFilters","sort","sortOptions","refreshInstances","requestId","result","readApprovalInstanceRow","requestError","readErrorMessage","view","cancelled","loaded","schema","schemaLoadError","initiatorMemberIds","row","profiles","profile","handleTemplateChange","previous","handleFilterReset","handleFilterSubmit","handleFieldDraftChange","path","columns","readInstanceStateColor","record","readInitiatorLabel","tableActions","templateOptions","template","selectedTemplate","fieldFilterLines","chunkElements","elements","index","sortFieldChoices","selectedSortField","searchFilterLine","searchPlaceholder","readSelectedStateFilterOption","readStateFilterLabel","sortFilterLine","readSortDirection","emptyMessage","page","pageSize","total","items","last","lines","size","instance","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-field-filters.ts","../../src/components/approval-instance-field-filter-controls.tsx","../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":["import {\n APPROVAL_INSTANCE_SORT_TIME_FIELDS,\n isFilterableFieldSortable,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormFieldOption,\n} from '@rytass/bpm-core-shared';\n\n/**\n * Pure logic behind the list page's field filters (ADR 25 §7). Turns the\n * filterable fields of a template's schema into controls, and the control\n * values into `fieldFilters` and `sort` for `listApprovalInstancesPage`. The\n * operator for each control is one `readFilterOperatorsForFieldType` allows.\n */\n\n/** Which control a filterable field gets on the list page. */\nexport type FieldFilterControl =\n /** Text, textarea and dynamic (data-source) options: CONTAINS on a text input. */\n | { readonly kind: 'contains' }\n /** Static options: IN on a multi-select. */\n | { readonly kind: 'option-in'; readonly options: readonly FormFieldOption[] }\n /** Member and org unit: IN on comma-separated ids (no picker yet). */\n | { readonly kind: 'id-in' }\n /** Number and money: RANGE with two number inputs. */\n | { readonly kind: 'number-range' }\n /** Date: RANGE with a date range picker. */\n | { readonly kind: 'date-range' }\n /** Datetime: RANGE with a datetime range picker. */\n | { readonly kind: 'datetime-range' }\n /** Boolean: EQUALS with a yes / no select. */\n | { readonly kind: 'boolean' };\n\nexport function readFieldFilterControl(\n item: FilterableFieldPath,\n): FieldFilterControl {\n switch (item.kind) {\n case 'number':\n return { kind: 'number-range' };\n case 'date':\n return { kind: 'date-range' };\n case 'datetime':\n return { kind: 'datetime-range' };\n case 'boolean':\n return { kind: 'boolean' };\n case 'member':\n case 'org_unit':\n return { kind: 'id-in' };\n case 'option':\n return item.staticOptions\n ? { kind: 'option-in', options: item.staticOptions }\n : { kind: 'contains' };\n case 'text':\n return { kind: 'contains' };\n }\n}\n\n/**\n * One field's entered condition. `from` and `to` hold canonical values\n * (decimal string, `YYYY-MM-DD`, or ISO 8601) as the controls produce them.\n */\nexport interface FieldFilterDraft {\n readonly from: string;\n readonly to: string;\n /** CONTAINS text, or comma-separated ids for IN on member and org unit. */\n readonly text: string;\n /** Selected option values (IN), or `['true']` / `['false']` for boolean. */\n readonly values: readonly string[];\n}\n\nexport const EMPTY_FIELD_FILTER_DRAFT: FieldFilterDraft = {\n from: '',\n text: '',\n to: '',\n values: [],\n};\n\n/** Drafts keyed by the field path, so a path can be looked up directly. */\nexport type FieldFilterDrafts = Readonly<Record<string, FieldFilterDraft>>;\n\nconst DECIMAL_PATTERN = /^-?\\d+(\\.\\d+)?$/u;\n\n/**\n * Whether a number control's text is a decimal. Surrounding spaces and\n * thousands separators (`1,000`) are accepted and dropped before sending.\n */\nexport function isDecimalText(value: string): boolean {\n return readDecimal(value) !== null;\n}\n\nfunction readDecimal(value: string): string | null {\n const plain = value.trim().replace(/,/gu, '');\n\n return DECIMAL_PATTERN.test(plain) ? plain : null;\n}\n\nfunction readIdList(text: string): readonly string[] {\n return text\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\n/**\n * The condition one draft asks for, or `null` when it is empty. Empty means\n * no condition, so it must not reach the server as a filter.\n */\nexport function toApprovalInstanceFieldFilter(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n): ApprovalInstanceFieldFilter | null {\n const control = readFieldFilterControl(item);\n\n switch (control.kind) {\n case 'contains': {\n const text = draft.text.trim();\n\n return text\n ? { fieldKey: item.path, operator: 'CONTAINS', values: [text] }\n : null;\n }\n case 'option-in':\n return draft.values.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: [...draft.values] }\n : null;\n case 'id-in': {\n const ids = readIdList(draft.text);\n\n return ids.length > 0\n ? { fieldKey: item.path, operator: 'IN', values: ids }\n : null;\n }\n case 'number-range': {\n const from = readDecimal(draft.from);\n const to = readDecimal(draft.to);\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'date-range':\n case 'datetime-range': {\n const from = draft.from.trim();\n const to = draft.to.trim();\n\n return from || to\n ? {\n fieldKey: item.path,\n operator: 'RANGE',\n ...(from ? { from } : {}),\n ...(to ? { to } : {}),\n }\n : null;\n }\n case 'boolean': {\n const value = draft.values[0];\n\n return value === 'true' || value === 'false'\n ? { fieldKey: item.path, operator: 'EQUALS', values: [value] }\n : null;\n }\n }\n}\n\n/** Every non-empty condition, in schema order. */\nexport function buildApprovalInstanceFieldFilters(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n): readonly ApprovalInstanceFieldFilter[] {\n return paths.flatMap((item): readonly ApprovalInstanceFieldFilter[] => {\n const filter = toApprovalInstanceFieldFilter(\n item,\n drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT,\n );\n\n return filter ? [filter] : [];\n });\n}\n\n/** The sort the user picked. An empty `field` keeps the server default. */\nexport interface SortDraft {\n readonly direction: ApprovalInstanceSortDirection;\n readonly field: string;\n}\n\nexport const DEFAULT_SORT_DRAFT: SortDraft = { direction: 'DESC', field: '' };\n\nexport interface SortFieldOption {\n readonly id: string;\n readonly label: string;\n}\n\nexport const DEFAULT_SORT_OPTION: SortFieldOption = {\n id: '',\n label: '預設(建立時間,新到舊)',\n};\n\nconst SORT_TIME_LABELS: Readonly<\n Record<(typeof APPROVAL_INSTANCE_SORT_TIME_FIELDS)[number], string>\n> = {\n completedAt: '完成時間',\n submittedAt: '送出時間',\n updatedAt: '最後更新',\n};\n\n/**\n * Sort choices. Time fields are always offered. Form fields are offered only\n * with a template selected, because the server needs a template to sort by a\n * form field.\n */\nexport function readSortFieldOptions(\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): readonly SortFieldOption[] {\n const timeOptions = APPROVAL_INSTANCE_SORT_TIME_FIELDS.map(\n (field): SortFieldOption => ({ id: field, label: SORT_TIME_LABELS[field] }),\n );\n const fieldOptions = templateSelected\n ? paths\n .filter(isFilterableFieldSortable)\n .map((item): SortFieldOption => ({ id: item.path, label: item.label }))\n : [];\n\n return [DEFAULT_SORT_OPTION, ...timeOptions, ...fieldOptions];\n}\n\n/** Whether a sort on `field` is valid for the current template selection. */\nexport function isSortFieldAvailable(\n field: string,\n paths: readonly FilterableFieldPath[],\n templateSelected: boolean,\n): boolean {\n if (field === '') {\n return true;\n }\n\n if (\n (APPROVAL_INSTANCE_SORT_TIME_FIELDS as readonly string[]).includes(field)\n ) {\n return true;\n }\n\n return templateSelected && paths.some((item) => item.path === field);\n}\n\nexport function toApprovalInstanceSort(\n draft: SortDraft,\n): readonly ApprovalInstanceSort[] | undefined {\n return draft.field === ''\n ? undefined\n : [{ direction: draft.direction, field: draft.field }];\n}\n","'use client';\n\nimport type { ReactElement } from 'react';\nimport {\n DateRangePicker,\n DateTimeRangePicker,\n Filter,\n FormField,\n Input,\n Select,\n type FilterProps,\n} from '@mezzanine-ui/react';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport {\n formatDatePickerValue,\n formatDateTimePickerValue,\n} from '@rytass/bpm-core-client/form';\nimport type { FilterableFieldPath } from '@rytass/bpm-core-shared';\nimport {\n EMPTY_FIELD_FILTER_DRAFT,\n isDecimalText,\n readFieldFilterControl,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n} from './approval-instance-field-filters';\n\nexport type FieldFilterDraftChange = (\n path: string,\n draft: FieldFilterDraft,\n) => void;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst BOOLEAN_CHOICES: readonly SelectChoice[] = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\n/**\n * One list-page `Filter` per condition the template's filterable fields need.\n * A number field yields two (lower and upper bound) because Mezzanine has no\n * number range control. Returned as elements so the caller can place them\n * directly inside `FilterLine`, which only accepts `Filter` children.\n */\nexport function readFieldFilterElements(\n paths: readonly FilterableFieldPath[],\n drafts: FieldFilterDrafts,\n onDraftChange: FieldFilterDraftChange,\n): readonly ReactElement<FilterProps>[] {\n return paths.flatMap((item): readonly ReactElement<FilterProps>[] => {\n const draft = drafts[item.path] ?? EMPTY_FIELD_FILTER_DRAFT;\n const change = (next: FieldFilterDraft): void => {\n onDraftChange(item.path, next);\n };\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'number-range') {\n return [\n renderFilter(\n `${item.path}:from`,\n `${item.label}(下限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, from: event.target.value });\n }}\n placeholder={`${item.label}:下限`}\n size=\"sub\"\n value={draft.from}\n variant=\"base\"\n />,\n readNumberHint(draft.from),\n ),\n renderFilter(\n `${item.path}:to`,\n `${item.label}(上限)`,\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, to: event.target.value });\n }}\n placeholder={`${item.label}:上限`}\n size=\"sub\"\n value={draft.to}\n variant=\"base\"\n />,\n readNumberHint(draft.to),\n ),\n ];\n }\n\n return [\n renderFilter(\n item.path,\n item.label,\n renderControl(item, draft, change, item.label),\n control.kind === 'id-in'\n ? `多個${readIdNoun(item)}以逗號分隔`\n : undefined,\n ),\n ];\n });\n}\n\nfunction renderFilter(\n key: string,\n label: string,\n control: ReactElement,\n hintText?: string,\n): ReactElement<FilterProps> {\n return (\n <Filter key={key} span={2}>\n <FormField\n fullWidth\n hintText={hintText}\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label={label}\n name={`fieldFilter-${key}`}\n >\n {control}\n </FormField>\n </Filter>\n );\n}\n\n/** What an id-in field holds: members, or org units for an `org_unit` field. */\nfunction readIdNoun(item: FilterableFieldPath): string {\n return item.kind === 'org_unit' ? '組織' : '成員';\n}\n\nfunction readNumberHint(value: string): string | undefined {\n return !value || isDecimalText(value) ? undefined : '請輸入數字';\n}\n\nfunction renderControl(\n item: FilterableFieldPath,\n draft: FieldFilterDraft,\n change: (next: FieldFilterDraft) => void,\n label: string,\n): ReactElement {\n // The list page hides FormField labels to keep its filter rows compact, so\n // each control names its field in the placeholder, as the state filter does.\n const control = readFieldFilterControl(item);\n\n if (control.kind === 'option-in') {\n const choices = control.options.map((option): SelectChoice => ({\n id: option.value,\n name: option.label,\n }));\n\n return (\n <Select\n clearable\n fullWidth\n mode=\"multiple\"\n onChange={(selected: readonly SelectChoice[]): void => {\n change({ ...draft, values: selected.map((option) => option.id) });\n }}\n options={[...choices]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={choices.filter((choice) => draft.values.includes(choice.id))}\n />\n );\n }\n\n if (control.kind === 'boolean') {\n const selected = BOOLEAN_CHOICES.find((choice) =>\n draft.values.includes(choice.id),\n );\n\n return (\n <Select\n clearable\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n change({ ...draft, values: option ? [option.id] : [] });\n }}\n options={[...BOOLEAN_CHOICES]}\n placeholder={`${label}:全部`}\n size=\"sub\"\n value={selected ?? null}\n />\n );\n }\n\n if (control.kind === 'date-range') {\n return (\n <DateRangePicker\n clearable\n fullWidth\n inputFromPlaceholder={`${label}:起`}\n inputToPlaceholder=\"迄\"\n onChange={(target?: readonly (string | undefined)[]): void => {\n change({\n ...draft,\n from: formatDatePickerValue(target?.[0]) ?? '',\n to: formatDatePickerValue(target?.[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={draft.from && draft.to ? [draft.from, draft.to] : []}\n />\n );\n }\n\n if (control.kind === 'datetime-range') {\n return (\n <DateTimeRangePicker\n clearable\n fullWidth\n onChange={(value): void => {\n change({\n ...draft,\n from: formatDateTimePickerValue(value[0]) ?? '',\n to: formatDateTimePickerValue(value[1]) ?? '',\n });\n }}\n size=\"sub\"\n value={[draft.from || undefined, draft.to || undefined]}\n />\n );\n }\n\n if (control.kind === 'id-in') {\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:${readIdNoun(item)} ID`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n }\n\n // contains (text, textarea and data-source options)\n return (\n <Input\n fullWidth\n onChange={(event): void => {\n change({ ...draft, text: event.target.value });\n }}\n placeholder={`${label}:包含`}\n size=\"sub\"\n value={draft.text}\n variant=\"base\"\n />\n );\n}\n",".instanceFilterArea {\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","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n RadioGroup,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n type FilterLineProps,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n ControlFieldSlotLayout,\n FormFieldLayout,\n} from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalTemplates,\n type ApprovalTemplateRecord,\n} from '@rytass/bpm-core-client/template';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n readApprovalTemplateCurrentFormSchema,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readFilterableFieldPaths,\n type ApprovalInstanceFieldFilter,\n type ApprovalInstanceSort,\n type ApprovalInstanceSortDirection,\n type FilterableFieldPath,\n type FormDefinitionSchema,\n} from '@rytass/bpm-core-shared';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport {\n buildApprovalInstanceFieldFilters,\n DEFAULT_SORT_DRAFT,\n DEFAULT_SORT_OPTION,\n isSortFieldAvailable,\n readSortFieldOptions,\n toApprovalInstanceSort,\n type FieldFilterDraft,\n type FieldFilterDrafts,\n type SortDraft,\n type SortFieldOption,\n} from './approval-instance-field-filters';\nimport { readFieldFilterElements } from './approval-instance-field-filter-controls';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\ntype SelectChoice = Readonly<{ id: string; name: string }>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst FIELD_FILTERS_PER_LINE = 3;\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\nconst SORT_DIRECTION_OPTIONS: readonly (SelectChoice & {\n id: ApprovalInstanceSortDirection;\n})[] = [\n { id: 'DESC', name: '新到舊' },\n { id: 'ASC', name: '舊到新' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n *\n * With a template selected, the filter bar also carries one control per\n * filterable field of that template's current form (ADR 25 §7), and the sort\n * may use those fields. Without a template only time fields can sort.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [templateId, setTemplateId] = useState<string | null>(null);\n const [templateSchema, setTemplateSchema] =\n useState<FormDefinitionSchema | null>(null);\n const [schemaLoading, setSchemaLoading] = useState(false);\n const [schemaError, setSchemaError] = useState<string | null>(null);\n const [fieldDrafts, setFieldDrafts] = useState<FieldFilterDrafts>({});\n const [sortDraft, setSortDraft] = useState<SortDraft>(DEFAULT_SORT_DRAFT);\n const refreshRequestIdRef = useRef(0);\n\n const fieldPaths = useMemo(\n (): readonly FilterableFieldPath[] =>\n templateSchema ? readFilterableFieldPaths(templateSchema) : [],\n [templateSchema],\n );\n const fieldFilters = useMemo(\n (): readonly ApprovalInstanceFieldFilter[] | undefined =>\n templateId === null\n ? undefined\n : buildApprovalInstanceFieldFilters(fieldPaths, fieldDrafts),\n [fieldDrafts, fieldPaths, templateId],\n );\n const sort = useMemo(\n (): readonly ApprovalInstanceSort[] | undefined =>\n toApprovalInstanceSort(sortDraft),\n [sortDraft],\n );\n const sortOptions = useMemo(\n (): readonly SortFieldOption[] =>\n readSortFieldOptions(fieldPaths, templateId !== null),\n [fieldPaths, templateId],\n );\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n fieldFilters,\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n sort,\n state: stateFilter.state,\n templateId,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [\n fieldFilters,\n instancePage,\n instancePageSize,\n searchText,\n sort,\n stateFilter,\n templateId,\n view,\n ]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const loaded = await listApprovalTemplates();\n\n if (!cancelled) {\n setTemplates(loaded);\n }\n } catch {\n if (!cancelled) {\n setTemplates([]);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, []);\n\n // Race guard: a schema response for a previously picked template is dropped\n // when the template changes again (cleanup flips `cancelled`).\n useEffect((): (() => void) | void => {\n if (templateId === null) {\n setTemplateSchema(null);\n setSchemaLoading(false);\n setSchemaError(null);\n\n return;\n }\n\n let cancelled = false;\n setSchemaLoading(true);\n setSchemaError(null);\n\n void (async (): Promise<void> => {\n try {\n const schema = await readApprovalTemplateCurrentFormSchema(templateId);\n\n if (!cancelled) {\n setTemplateSchema(schema);\n }\n } catch (schemaLoadError: unknown) {\n if (!cancelled) {\n setTemplateSchema(null);\n setSchemaError(readErrorMessage(schemaLoadError));\n }\n } finally {\n if (!cancelled) {\n setSchemaLoading(false);\n }\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [templateId]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const handleTemplateChange = useCallback(\n (option: SelectChoice | null): void => {\n setTemplateId(option?.id ?? null);\n // Drop the previous template's fields at once, so nothing is built from\n // them while the new schema loads.\n setTemplateSchema(null);\n setFieldDrafts({});\n setInstancePage(1);\n // A form-field sort belongs to one template. Time-field sorts survive.\n setSortDraft((previous): SortDraft =>\n isSortFieldAvailable(previous.field, [], false)\n ? previous\n : { ...previous, field: DEFAULT_SORT_DRAFT.field },\n );\n },\n [],\n );\n\n const handleFilterReset = useCallback((): void => {\n setSearchText('');\n setStateFilter(readStateFilterOption(defaultState));\n setTemplateId(null);\n setTemplateSchema(null);\n setFieldDrafts({});\n setSortDraft(DEFAULT_SORT_DRAFT);\n setInstancePage(1);\n }, [defaultState]);\n const handleFilterSubmit = useCallback((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n const handleFieldDraftChange = useCallback(\n (path: string, draft: FieldFilterDraft): void => {\n setFieldDrafts((previous): FieldFilterDrafts => ({\n ...previous,\n [path]: draft,\n }));\n setInstancePage(1);\n },\n [],\n );\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n const templateOptions = useMemo(\n (): readonly SelectChoice[] =>\n templates.map((template) => ({ id: template.id, name: template.name })),\n [templates],\n );\n const selectedTemplate = templateOptions.find(\n (option) => option.id === templateId,\n );\n const fieldFilterLines = useMemo(\n (): readonly ReactElement<FilterLineProps>[] =>\n chunkElements(\n readFieldFilterElements(\n fieldPaths,\n fieldDrafts,\n handleFieldDraftChange,\n ),\n FIELD_FILTERS_PER_LINE,\n ).map((elements, index): ReactElement<FilterLineProps> => (\n <FilterLine key={`field-filter-line-${index}`}>\n {[...elements]}\n </FilterLine>\n )),\n [fieldDrafts, fieldPaths, handleFieldDraftChange],\n );\n const sortFieldChoices = useMemo(\n (): readonly SelectChoice[] =>\n sortOptions.map((option) => ({ id: option.id, name: option.label })),\n [sortOptions],\n );\n const selectedSortField =\n sortFieldChoices.find((option) => option.id === sortDraft.field) ??\n sortFieldChoices.find((option) => option.id === DEFAULT_SORT_OPTION.id);\n\n const searchFilterLine = (\n <FilterLine key=\"search\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"範本\"\n name=\"instanceTemplate\"\n >\n <Select\n clearable\n fullWidth\n onChange={handleTemplateChange}\n options={[...templateOptions]}\n placeholder=\"全部範本\"\n size=\"sub\"\n value={selectedTemplate ?? null}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n const sortFilterLine = (\n <FilterLine key=\"sort\">\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序欄位\"\n name=\"instanceSortField\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option: SelectChoice | null): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n field: option?.id ?? DEFAULT_SORT_DRAFT.field,\n }));\n setInstancePage(1);\n }}\n options={[...sortFieldChoices]}\n placeholder=\"排序欄位\"\n size=\"sub\"\n value={selectedSortField ?? null}\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n controlFieldSlotLayout={ControlFieldSlotLayout.SUB}\n layout={FormFieldLayout.VERTICAL}\n label=\"排序方向\"\n name=\"instanceSortDirection\"\n >\n <RadioGroup\n name=\"instanceSortDirection\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortDraft((previous): SortDraft => ({\n ...previous,\n direction: readSortDirection(event.target.value),\n }));\n setInstancePage(1);\n }}\n options={[...SORT_DIRECTION_OPTIONS]}\n size=\"sub\"\n type=\"segment\"\n value={sortDraft.direction}\n />\n </FormField>\n </Filter>\n </FilterLine>\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea\n className={styles.instanceFilterArea}\n onReset={handleFilterReset}\n onSubmit={handleFilterSubmit}\n resetText=\"清除條件\"\n rowAlign=\"end\"\n size=\"sub\"\n submitText=\"重新查詢\"\n >\n {[searchFilterLine, ...fieldFilterLines, sortFilterLine]}\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {schemaError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {schemaError}\n </Typography>\n ) : null}\n {templateId !== null &&\n !schemaLoading &&\n !schemaError &&\n templateSchema &&\n fieldPaths.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此範本沒有可篩選的欄位。\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction chunkElements<T>(\n items: readonly T[],\n size: number,\n): readonly (readonly T[])[] {\n return items.reduce<readonly (readonly T[])[]>(\n (lines, item): readonly (readonly T[])[] => {\n const last = lines[lines.length - 1];\n\n return last && last.length < size\n ? [...lines.slice(0, -1), [...last, item]]\n : [...lines, [item]];\n },\n [],\n );\n}\n\nfunction readSortDirection(value: string): ApprovalInstanceSortDirection {\n return value === 'ASC' ? 'ASC' : 'DESC';\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取簽核案件失敗。';\n}\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-D6fCDq_q.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-CtWuunwB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-CtWuunwB.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,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-
|
|
4
|
+
import { t as n } from "./FormBuilderView-6KdApi-D.js";
|
|
5
5
|
import { t as r } from "./FormRendererView-BcQKUi1A.js";
|
|
6
|
-
import { n as i, r as a, t as o } from "./designer-
|
|
7
|
-
import {
|
|
6
|
+
import { n as i, r as a, t as o } from "./designer-BnMeiMVe.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-M-GR6smM.js.map
|