diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts index eda790bf0e..208de1b7a7 100644 --- a/packages/core/client/src/block-provider/hooks/index.ts +++ b/packages/core/client/src/block-provider/hooks/index.ts @@ -4,7 +4,7 @@ import { App, message } from 'antd'; import _, { cloneDeep } from 'lodash'; import get from 'lodash/get'; import omit from 'lodash/omit'; -import { ChangeEvent, useContext, useEffect } from 'react'; +import { ChangeEvent, useCallback, useContext, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { useReactToPrint } from 'react-to-print'; @@ -97,85 +97,109 @@ export function getFormValues({ return form.values; } +export function useCollectValuesToSubmit() { + const form = useForm(); + const filterByTk = useFilterByTk(); + const { field, resource } = useBlockRequestContext(); + const { fields, getField, getTreeParentField, name } = useCollection(); + const fieldNames = fields.map((field) => field.name); + const { fieldSchema } = useActionContext(); + const { getActiveFieldsName } = useFormActiveFields() || {}; + const variables = useVariables(); + const localVariables = useLocalVariables({ currentForm: form }); + const actionSchema = useFieldSchema(); + const currentRecord = useRecord(); + + return useCallback(async () => { + const { assignedValues: originalAssignedValues = {}, overwriteValues } = actionSchema?.['x-action-settings'] ?? {}; + const values = getFormValues({ + filterByTk, + field, + form, + fieldNames, + getField, + resource, + actionFields: getActiveFieldsName?.('form') || [], + }); + + const assignedValues = {}; + const waitList = Object.keys(originalAssignedValues).map(async (key) => { + const value = originalAssignedValues[key]; + const collectionField = getField(key); + + if (process.env.NODE_ENV !== 'production') { + if (!collectionField) { + throw new Error(`useCreateActionProps: field "${key}" not found in collection "${name}"`); + } + } + + if (isVariable(value)) { + const result = await variables?.parseVariable(value, localVariables); + if (result) { + assignedValues[key] = transformVariableValue(result, { targetCollectionField: collectionField }); + } + } else if (value != null && value !== '') { + assignedValues[key] = value; + } + }); + await Promise.all(waitList); + // const values = omitBy(formValues, (value) => isEqual(JSON.stringify(value), '[{}]')); + const addChild = fieldSchema?.['x-component-props']?.addChild; + if (addChild) { + const treeParentField = getTreeParentField(); + values[treeParentField?.name ?? 'parent'] = omit(currentRecord?.__parent, ['children']); + values[treeParentField?.foreignKey ?? 'parentId'] = currentRecord?.__parent?.id; + } + + return { + ...values, + ...overwriteValues, + ...assignedValues, + }; + }, [ + actionSchema, + currentRecord?.__parent, + field, + fieldNames, + fieldSchema, + filterByTk, + form, + getActiveFieldsName, + getField, + getTreeParentField, + localVariables, + name, + resource, + variables, + ]); +} + export const useCreateActionProps = () => { const form = useForm(); const { field, resource, __parent } = useBlockRequestContext(); - const { setVisible, fieldSchema } = useActionContext(); + const { setVisible } = useActionContext(); const navigate = useNavigate(); const actionSchema = useFieldSchema(); const actionField = useField(); - const { fields, getField, getTreeParentField, name } = useCollection(); const compile = useCompile(); - const filterByTk = useFilterByTk(); - const currentRecord = useRecord(); const { modal } = App.useApp(); - const variables = useVariables(); - const localVariables = useLocalVariables({ currentForm: form }); - const { getActiveFieldsName } = useFormActiveFields() || {}; const { t } = useTranslation(); + const collectValues = useCollectValuesToSubmit(); const action = actionField.componentProps.saveMode || 'create'; const filterKeys = actionField.componentProps.filterKeys?.checked || []; return { async onClick() { - const fieldNames = fields.map((field) => field.name); - const { - assignedValues: originalAssignedValues = {}, - onSuccess, - overwriteValues, - skipValidator, - triggerWorkflows, - } = actionSchema?.['x-action-settings'] ?? {}; - const addChild = fieldSchema?.['x-component-props']?.addChild; - - const assignedValues = {}; - const waitList = Object.keys(originalAssignedValues).map(async (key) => { - const value = originalAssignedValues[key]; - const collectionField = getField(key); - - if (process.env.NODE_ENV !== 'production') { - if (!collectionField) { - throw new Error(`useCreateActionProps: field "${key}" not found in collection "${name}"`); - } - } - - if (isVariable(value)) { - const result = await variables?.parseVariable(value, localVariables); - if (result) { - assignedValues[key] = transformVariableValue(result, { targetCollectionField: collectionField }); - } - } else if (value != null && value !== '') { - assignedValues[key] = value; - } - }); - await Promise.all(waitList); + const { onSuccess, skipValidator, triggerWorkflows } = actionSchema?.['x-action-settings'] ?? {}; if (!skipValidator) { await form.submit(); } - const values = getFormValues({ - filterByTk, - field, - form, - fieldNames, - getField, - resource, - actionFields: getActiveFieldsName?.('form') || [], - }); - // const values = omitBy(formValues, (value) => isEqual(JSON.stringify(value), '[{}]')); - if (addChild) { - const treeParentField = getTreeParentField(); - values[treeParentField?.name ?? 'parent'] = omit(currentRecord?.__parent, ['children']); - values[treeParentField?.foreignKey ?? 'parentId'] = currentRecord?.__parent?.id; - } + const values = await collectValues(); actionField.data = field.data || {}; actionField.data.loading = true; try { const data = await resource[action]({ - values: { - ...values, - ...overwriteValues, - ...assignedValues, - }, + values, filterKeys: filterKeys, // TODO(refactor): should change to inject by plugin triggerWorkflows: triggerWorkflows?.length diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/form.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/form.tsx index 36ea965037..2ba09abb65 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/form.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/form.tsx @@ -4,14 +4,10 @@ import { useAPIClient, useActionContext, useBlockRequestContext, - useCollection, + useCollectValuesToSubmit, useCollectionDataSource, useCollectionManager, useCompile, - useCurrentUserContext, - useFilterByTk, - useFormActiveFields, - useRecord, } from '@nocobase/client'; import { isURL, parse } from '@nocobase/utils/client'; import { App, message } from 'antd'; @@ -104,92 +100,32 @@ export default { useActionTriggerable: true, }; -function getFormValues({ - filterByTk, - form, - getField, - actionFields, -}: { - filterByTk; - form; - getField; - actionFields: any[]; -}) { - if (filterByTk) { - if (actionFields) { - const keys = Object.keys(form.values).filter((key) => { - const f = getField(key); - return !actionFields.includes(key) && ['hasOne', 'hasMany', 'belongsTo', 'belongsToMany'].includes(f?.type); - }); - return omit({ ...form.values }, keys); - } - } - - return form.values; -} - export function useTriggerWorkflowsActionProps() { const api = useAPIClient(); const form = useForm(); - const { field, resource, __parent } = useBlockRequestContext(); - const { setVisible, fieldSchema } = useActionContext(); + const { field, __parent } = useBlockRequestContext(); + const { setVisible } = useActionContext(); const navigate = useNavigate(); const actionSchema = useFieldSchema(); const actionField = useField(); - const { fields, getField, getTreeParentField } = useCollection(); const compile = useCompile(); - const filterByTk = useFilterByTk(); - const currentRecord = useRecord(); - const currentUserContext = useCurrentUserContext(); const { modal } = App.useApp(); - const { getActiveFieldsName } = useFormActiveFields() || {}; + const collectValues = useCollectValuesToSubmit(); - const currentUser = currentUserContext?.data?.data; const filterKeys = actionField.componentProps.filterKeys || []; return { async onClick() { - const { - assignedValues: originalAssignedValues = {}, - onSuccess, - overwriteValues, - skipValidator, - triggerWorkflows, - } = actionSchema?.['x-action-settings'] ?? {}; - const addChild = fieldSchema?.['x-component-props']?.addChild; - const assignedValues = parse(originalAssignedValues)({ - // @deprecated - currentTime: new Date(), - // @deprecated - currentRecord, - // @deprecated - currentUser, - $user: currentUser, - $nRecord: currentRecord, - $nForm: form.values, - $nDate: { - now: new Date(), - }, - }); + const { onSuccess, skipValidator, triggerWorkflows } = actionSchema?.['x-action-settings'] ?? {}; if (!skipValidator) { await form.submit(); } - const values = getFormValues({ filterByTk, form, getField, actionFields: getActiveFieldsName?.('form') || [] }); - // const values = omitBy(formValues, (value) => isEqual(JSON.stringify(value), '[{}]')); - if (addChild) { - const treeParentField = getTreeParentField(); - values[treeParentField?.name ?? 'parent'] = currentRecord; - values[treeParentField?.foreignKey ?? 'parentId'] = currentRecord.id; - } + const values = await collectValues(); actionField.data = field.data || {}; actionField.data.loading = true; try { const data = await api.resource('workflows').trigger({ - values: { - ...values, - ...overwriteValues, - ...assignedValues, - }, + values, filterKeys: filterKeys, // TODO(refactor): should change to inject by plugin triggerWorkflows: triggerWorkflows?.length