diff --git a/packages/core/database/src/database-utils/index.ts b/packages/core/database/src/database-utils/index.ts index 4790171ce..1c3245cb1 100644 --- a/packages/core/database/src/database-utils/index.ts +++ b/packages/core/database/src/database-utils/index.ts @@ -38,3 +38,5 @@ export default class DatabaseUtils { return this.db.options.schema || 'public'; } } + +export * from './traverseJSON'; diff --git a/packages/core/database/src/database-utils/traverseJSON.ts b/packages/core/database/src/database-utils/traverseJSON.ts new file mode 100644 index 000000000..4a3bea72e --- /dev/null +++ b/packages/core/database/src/database-utils/traverseJSON.ts @@ -0,0 +1,112 @@ +import { Collection } from '@tachybase/database'; + +type TraverseOptions = { + collection: Collection; + exclude?: string[]; + include?: string[]; + through?: string; + excludePk?: boolean; +}; + +const traverseHasMany = (arr: any[], { collection, exclude = [], include = [] }: TraverseOptions) => { + if (!arr) { + return arr; + } + return arr.map((item) => traverseJSON(item, { collection, exclude, include })); +}; + +const traverseBelongsToMany = (arr: any[], { collection, exclude = [], through }: TraverseOptions) => { + if (!arr) { + return arr; + } + const throughCollection = collection.db.getCollection(through); + return arr.map((item) => { + const data = traverseJSON(item[through], { collection: throughCollection, exclude }); + if (data && Object.keys(data).length) { + item[through] = data; + } else { + delete item[through]; + } + return traverseJSON(item, { + collection, + excludePk: false, + }); + }); +}; + +const parseInclude = (keys: string[]) => { + const map = {}; + for (const key of keys) { + const args = key.split('.'); + const field = args.shift(); + map[field] = map[field] || []; + if (args.length) { + map[field].push(args.join('.')); + } + } + return map; +}; + +export const traverseJSON = (data, options: TraverseOptions) => { + if (!data) { + return data; + } + const { collection, exclude = [], include = [], excludePk = true } = options; + const map = parseInclude(include); + const result = {}; + for (const key of Object.keys(data || {})) { + const subInclude = map[key]; + if (include.length > 0 && !subInclude) { + continue; + } + if (exclude.includes(key)) { + continue; + } + if (['createdAt', 'updatedAt', 'createdBy', 'createdById', 'updatedById', 'updatedBy'].includes(key)) { + continue; + } + const field = collection.getField(key); + if (!field) { + result[key] = data[key]; + continue; + } + if (field.options.primaryKey && excludePk) { + continue; + } + if (field.options.isForeignKey) { + continue; + } + if (['sort', 'password', 'sequence'].includes(field.type)) { + continue; + } + if (field.type === 'hasOne') { + result[key] = traverseJSON(data[key], { + collection: collection.db.getCollection(field.target), + exclude: [field.foreignKey], + include: subInclude, + }); + } else if (field.type === 'hasMany') { + result[key] = traverseHasMany(data[key], { + collection: collection.db.getCollection(field.target), + exclude: [field.foreignKey], + include: subInclude, + }); + } else if (field.type === 'belongsTo') { + result[key] = traverseJSON(data[key], { + collection: collection.db.getCollection(field.target), + // exclude: [field.foreignKey], + include: subInclude, + excludePk: false, + }); + } else if (field.type === 'belongsToMany') { + result[key] = traverseBelongsToMany(data[key], { + collection: collection.db.getCollection(field.target), + exclude: [field.foreignKey, field.otherKey], + through: field.through, + }); + } else { + result[key] = data[key]; + } + } + return result; +}; diff --git a/packages/core/database/src/index.ts b/packages/core/database/src/index.ts index 0d90bf81a..34c9f6f57 100644 --- a/packages/core/database/src/index.ts +++ b/packages/core/database/src/index.ts @@ -38,6 +38,7 @@ export * from './relation-repository/single-relation-repository'; export * from './repository'; export * from './update-associations'; export { snakeCase } from './utils'; +export * from './database-utils'; export * from './value-parsers'; export * from './view-collection'; export * from './view/view-inference'; diff --git a/packages/core/server/src/middlewares/data-template.ts b/packages/core/server/src/middlewares/data-template.ts index 80198d69b..bf40a5a67 100644 --- a/packages/core/server/src/middlewares/data-template.ts +++ b/packages/core/server/src/middlewares/data-template.ts @@ -1,5 +1,5 @@ import { Context } from '@tachybase/actions'; -import { Collection } from '@tachybase/database'; +import { traverseJSON } from '@tachybase/database'; export const dateTemplate = async (ctx: Context, next) => { const { resourceName, actionName } = ctx.action; @@ -14,114 +14,3 @@ export const dateTemplate = async (ctx: Context, next) => { }); } }; - -type TraverseOptions = { - collection: Collection; - exclude?: string[]; - include?: string[]; - through?: string; - excludePk?: boolean; -}; - -const traverseHasMany = (arr: any[], { collection, exclude = [], include = [] }: TraverseOptions) => { - if (!arr) { - return arr; - } - return arr.map((item) => traverseJSON(item, { collection, exclude, include })); -}; - -const traverseBelongsToMany = (arr: any[], { collection, exclude = [], through }: TraverseOptions) => { - if (!arr) { - return arr; - } - const throughCollection = collection.db.getCollection(through); - return arr.map((item) => { - const data = traverseJSON(item[through], { collection: throughCollection, exclude }); - if (data && Object.keys(data).length) { - item[through] = data; - } else { - delete item[through]; - } - return traverseJSON(item, { - collection, - excludePk: false, - }); - }); -}; - -const parseInclude = (keys: string[]) => { - const map = {}; - for (const key of keys) { - const args = key.split('.'); - const field = args.shift(); - map[field] = map[field] || []; - if (args.length) { - map[field].push(args.join('.')); - } - } - return map; -}; - -const traverseJSON = (data, options: TraverseOptions) => { - if (!data) { - return data; - } - const { collection, exclude = [], include = [], excludePk = true } = options; - const map = parseInclude(include); - const result = {}; - for (const key of Object.keys(data || {})) { - const subInclude = map[key]; - if (include.length > 0 && !subInclude) { - continue; - } - if (exclude.includes(key)) { - continue; - } - if (['createdAt', 'updatedAt', 'createdBy', 'createdById', 'updatedById', 'updatedBy'].includes(key)) { - continue; - } - const field = collection.getField(key); - if (!field) { - result[key] = data[key]; - continue; - } - if (field.options.primaryKey && excludePk) { - continue; - } - if (field.options.isForeignKey) { - continue; - } - if (['sort', 'password', 'sequence'].includes(field.type)) { - continue; - } - if (field.type === 'hasOne') { - result[key] = traverseJSON(data[key], { - collection: collection.db.getCollection(field.target), - exclude: [field.foreignKey], - include: subInclude, - }); - } else if (field.type === 'hasMany') { - result[key] = traverseHasMany(data[key], { - collection: collection.db.getCollection(field.target), - exclude: [field.foreignKey], - include: subInclude, - }); - } else if (field.type === 'belongsTo') { - result[key] = traverseJSON(data[key], { - collection: collection.db.getCollection(field.target), - // exclude: [field.foreignKey], - include: subInclude, - excludePk: false, - }); - } else if (field.type === 'belongsToMany') { - result[key] = traverseBelongsToMany(data[key], { - collection: collection.db.getCollection(field.target), - exclude: [field.foreignKey, field.otherKey], - through: field.through, - }); - } else { - result[key] = data[key]; - } - } - return result; -}; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/configuration/trigger/launcher-interface/SchemaAddBlock.component.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/configuration/trigger/launcher-interface/SchemaAddBlock.component.tsx index 5cca15777..76b96dfe4 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/configuration/trigger/launcher-interface/SchemaAddBlock.component.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/configuration/trigger/launcher-interface/SchemaAddBlock.component.tsx @@ -9,8 +9,6 @@ import { } from '@tachybase/client'; import { uid } from '@tachybase/utils/client'; -import { Spin } from 'antd'; - import { useFlowContext } from '../../../../../FlowContext'; // 发起人操作界面-创建区块 @@ -19,30 +17,26 @@ export const SchemaAddBlock = ({ value, onChange }) => { const { workflow } = useFlowContext(); const { components } = useContext(SchemaComponentContext); - // TODO: // 获取对应数据表的表单Schema - const { data, loading } = useRequest(() => - E(this, null, function* () { - let m; - if (value) { - const { data: h } = yield api.request({ url: `uiSchemas:getJsonSchema/${value}` }); - if (((m = h.data) == null ? void 0 : m['x-uid']) === value) return h.data; - } - const l = uid(), - d = { - type: 'void', - name: l, - 'x-uid': l, - 'x-component': 'Grid', - 'x-initializer': 'ApprovalApplyAddBlockButton', - properties: {}, - }; - return yield api.resource('uiSchemas').insert({ values: d }), onChange(l), d; - }), - ); + const { data, loading } = useRequest(async () => { + if (value) { + const { data } = await api.request({ url: `uiSchemas:getJsonSchema/${value}` }); + if (data.data?.['x-uid'] === value) return data.data; + } + const name = uid(); + const values = { + type: 'void', + name: name, + 'x-uid': name, + 'x-component': 'Grid', + 'x-initializer': 'ApprovalApplyAddBlockButton', + properties: {}, + }; + return await api.resource('uiSchemas').insert({ values }), onChange(name), values; + }); if (loading) { - return ; + return; } return ( @@ -61,7 +55,6 @@ export const SchemaAddBlock = ({ value, onChange }) => { useFormBlockProps, useActionResubmit, }} - // @ts-ignore ugly schema={data} /> @@ -89,24 +82,3 @@ function useActionResubmit() { function ProviderActionResubmit(props) { return props.children; } -// TODO: -const E = (f, o, p) => - // eslint-disable-next-line promise/param-names - new Promise((r, G) => { - const u = ($) => { - try { - A(p.next($)); - } catch (U) { - G(U); - } - }, - y = ($) => { - try { - A(p.throw($)); - } catch (U) { - G(U); - } - }, - A = ($) => ($.done ? r($.value) : Promise.resolve($.value).then(u, y)); - A((p = p.apply(f, o)).next()); - }); diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/ActionResubmit.provider.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/ActionResubmit.provider.tsx index 1a7e9b88e..f6f8ae640 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/ActionResubmit.provider.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/ActionResubmit.provider.tsx @@ -1,19 +1,17 @@ import { useCurrentUserContext } from '@tachybase/client'; -import { useFlowContext } from '../../../../../FlowContext'; import { APPROVAL_STATUS } from '../../../constants'; import { useApproval } from '../../approval-common/ApprovalData.provider'; +import { useResubmit } from '../../approval-common/Resubmit.provider'; export function ProviderActionResubmit(props) { const { data } = useCurrentUserContext(); + const { isResubmit } = useResubmit(); const { status, createdById } = useApproval(); - const { workflow } = useFlowContext(); const isSameId = data.data.id === createdById; - // const isEnabledWithdraw = workflow.enabled && workflow.config.withdrawable; - // const isNotDraft = status !== APPROVAL_STATUS.DRAFT; - - if (isSameId) { + const isDraft = status === APPROVAL_STATUS.DRAFT; + if (isSameId && !isResubmit && !isDraft) { return props.children; } diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ActionBar.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ActionBar.tsx index 3da567ac8..56a2ee7b6 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ActionBar.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ActionBar.tsx @@ -11,14 +11,8 @@ export function ActionBarProvider(props) { const isSameId = data.data.id === createdById; const isSameExcutionId = latestExecutionId === approvalExecution.id; - const isExcutionDid = [ - APPROVAL_STATUS.DRAFT, - APPROVAL_STATUS.RETURNED, - APPROVAL_STATUS.SUBMITTED, - APPROVAL_STATUS.RESUBMIT, - ].includes(status); - if (!isSameId || !isSameExcutionId || !isExcutionDid) { + if (!isSameId || !isSameExcutionId) { return null; } diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ApplyActionStatus.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ApplyActionStatus.tsx index 6427d8e7e..e57774b66 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ApplyActionStatus.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.ApplyActionStatus.tsx @@ -4,6 +4,7 @@ import { useCurrentUserContext } from '@tachybase/client'; import { useFlowContext } from '../../../../../FlowContext'; import { APPROVAL_STATUS } from '../../../constants'; import { useApproval } from '../../approval-common/ApprovalData.provider'; +import { useResubmit } from '../../approval-common/Resubmit.provider'; const ContextApprovalStatus = createContext(APPROVAL_STATUS.SUBMITTED); @@ -16,11 +17,16 @@ export function ApplyActionStatusProvider(props) { const { status, createdById } = useApproval(); const { workflow } = useFlowContext(); const { data } = useCurrentUserContext(); + const { isResubmit } = useResubmit(); const isSameId = data.data.id === createdById; - const isEnbled = workflow.enabled; + const isEnabled = workflow.enabled; const isStatusDid = [APPROVAL_STATUS.RESUBMIT, APPROVAL_STATUS.DRAFT, APPROVAL_STATUS.RETURNED].includes(status); - if (isSameId && isEnbled && isStatusDid) { + if (value === APPROVAL_STATUS.DRAFT && status === APPROVAL_STATUS.DRAFT) { + return null; + } + + if ((isSameId && isEnabled && isStatusDid) || (isSameId && isEnabled && isResubmit)) { return {children}; } diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.WithdrawAction.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.WithdrawAction.tsx index f4fbaaf66..fd0e14368 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.WithdrawAction.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/Pd.WithdrawAction.tsx @@ -3,17 +3,19 @@ import { useCurrentUserContext } from '@tachybase/client'; import { useFlowContext } from '../../../../../FlowContext'; import { APPROVAL_STATUS } from '../../../constants'; import { useApproval } from '../../approval-common/ApprovalData.provider'; +import { useResubmit } from '../../approval-common/Resubmit.provider'; export function WithdrawActionProvider({ children }) { const { data } = useCurrentUserContext(); const { status, createdById } = useApproval(); const { workflow } = useFlowContext(); + const { isResubmit } = useResubmit(); const isSameId = data.data.id === createdById; const isEnabledWithdraw = workflow.enabled && workflow.config.withdrawable; const isStatusSubmitted = APPROVAL_STATUS.SUBMITTED === status; - if (isSameId && isEnabledWithdraw && isStatusSubmitted) { + if (isSameId && isEnabledWithdraw && isStatusSubmitted && !isResubmit) { return children; } diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/VC.ViewActionLaunchContent.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/VC.ViewActionLaunchContent.tsx index 7c9976bdd..681504c43 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/VC.ViewActionLaunchContent.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/VC.ViewActionLaunchContent.tsx @@ -16,6 +16,7 @@ import { FormBlockProvider } from '../../../common/FormBlock.provider'; import { APPROVAL_STATUS } from '../../../constants'; import { NAMESPACE } from '../../../locale'; import { ApprovalContext } from '../../approval-common/ApprovalData.provider'; +import { ResubmitProvider } from '../../approval-common/Resubmit.provider'; import { ContextWithActionEnabled } from '../../approval-common/WithActionEnabled.provider'; import { ContextApprovalExecution } from '../common/ApprovalExecution.provider'; import { FlowContextProvider } from '../common/FlowContext.provider'; @@ -85,77 +86,79 @@ export const ViewActionLaunchContent = () => { > - + + }} + /> + diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/VC.ApplyButton.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/VC.ApplyButton.tsx index a171f51fd..342ad6e6a 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/VC.ApplyButton.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/VC.ApplyButton.tsx @@ -16,7 +16,7 @@ import { Button, Dropdown } from 'antd'; import { useTranslation } from '../../../../locale'; import { FlowContextProvider } from '../../common/FlowContext.provider'; import { useActionResubmit } from '../hooks/useActionResubmit'; -import { useSubmit } from './hooks/useSubmit'; +import { useCreateSubmit } from './hooks/useSubmit'; import { useWithdrawAction } from './hooks/useWithdrawAction'; import { ActionBarProvider } from './Pd.ActionBar'; import { ApplyActionStatusProvider } from './Pd.ActionStatus'; @@ -108,15 +108,16 @@ export const ApplyButton = () => { null, + WithdrawActionProvider, }} scope={{ - useSubmit: useSubmit, + useSubmit: useCreateSubmit, useWithdrawAction, useActionResubmit, }} diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/hooks/useSubmit.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/hooks/useSubmit.tsx index d8879d951..1b76a997d 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/hooks/useSubmit.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/apply-button/hooks/useSubmit.tsx @@ -7,21 +7,23 @@ import { } from '@tachybase/client'; import { useField, useForm } from '@tachybase/schema'; +import _ from 'lodash'; + import { useFlowContext } from '../../../../../../../FlowContext'; import { useContextApprovalStatus } from '../Pd.ActionStatus'; -export function useSubmit() { +export function useCreateSubmit() { const from = useForm(); const field = useField(); const { setVisible } = useActionContext(); const { __parent } = useBlockRequestContext(); const collection = useCollection_deprecated(); - const contextWe = useContextApprovalStatus(); + const status = useContextApprovalStatus(); const apiClient = useAPIClient(); const { workflow } = useFlowContext(); return { - async run() { + async run({ approvalStatus }) { try { from.submit(); field.data = field.data || {}; @@ -30,8 +32,8 @@ export function useSubmit() { await apiClient.resource('approvals').create({ values: { collectionName: joinCollectionName(collection.dataSource, collection.name), - data: from.values, - status: contextWe, + data: _.omit(from.values, [collection.getPrimaryKey()]), + status: typeof approvalStatus !== 'undefined' ? approvalStatus : status, workflowId: workflow.id, }, }); @@ -43,7 +45,7 @@ export function useSubmit() { if (service) { service.refresh(); } - } catch (h) { + } catch (error) { field.data && (field.data.loading = false); } }, diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useActionResubmit.ts b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useActionResubmit.ts index e34825438..7a10b70d7 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useActionResubmit.ts +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useActionResubmit.ts @@ -1,59 +1,14 @@ -import { useAPIClient } from '@tachybase/client'; -import { useFlowContext } from '@tachybase/plugin-workflow/client'; -import { useField } from '@tachybase/schema'; - import _ from 'lodash'; -import { APPROVAL_STATUS } from '../../../../constants'; -import { useApproval } from '../../../approval-common/ApprovalData.provider'; -import { useHandleRefresh } from '../../common/useHandleRefresh'; +import { useResubmit } from '../../../approval-common/Resubmit.provider'; // 重新发起 export function useActionResubmit() { - const { refreshTable } = useHandleRefresh(); - - const field = useField(); - const approval = useApproval(); - const api = useAPIClient(); - - const { workflow } = useFlowContext(); + const { setResubmit } = useResubmit(); return { async run() { - try { - field.data = field.data ?? {}; - - field.data.loading = true; - - const appendsConfigs = [...workflow.config.appends]; - const summaryConfigs = [...workflow.config.summary]; - const appends = _.intersection(appendsConfigs, summaryConfigs); - - const { data: approvalData } = await api.resource('approvals').get({ - filterByTk: approval.id, - }); - - const { collectionName, data, workflowId } = approvalData.data; - - const newData = _.omit(data, ['id', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy']); - - await api.resource('approvals').reSubmit({ - values: { - collectionName: collectionName, - data: newData, - status: APPROVAL_STATUS.RESUBMIT, - workflowId: workflowId, - collectionAppends: appends, - }, - }); - - field.data.loading = false; - refreshTable(); - } catch (v) { - if (field.data) { - field.data.loading = false; - } - } + setResubmit(true); }, }; } diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useFormBlockProps.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useFormBlockProps.tsx index 469117588..e446b7e1d 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useFormBlockProps.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useFormBlockProps.tsx @@ -5,6 +5,7 @@ import { useForm } from '@tachybase/schema'; import { useFlowContext } from '../../../../../../FlowContext'; import { ApprovalStatusEnumDict } from '../../../../constants'; import { useApproval } from '../../../approval-common/ApprovalData.provider'; +import { useResubmit } from '../../../approval-common/Resubmit.provider'; import { useContextApprovalExecution } from '../../common/ApprovalExecution.provider'; export function useFormBlockProps() { @@ -13,11 +14,12 @@ export function useFormBlockProps() { const { workflow } = useFlowContext(); const form = useForm(); const { data } = useCurrentUserContext(); + const { isResubmit } = useResubmit(); const { editable } = ApprovalStatusEnumDict[approval.status]; const needEditable = - editable && + (isResubmit || editable) && approval?.latestExecutionId === approvalExecution.id && approval?.createdById === data?.data.id && workflow.enabled; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useSubmit.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useSubmit.tsx index 2d6778fb5..207376c1f 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useSubmit.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-block/launch/hooks/useSubmit.tsx @@ -5,12 +5,17 @@ import _ from 'lodash'; import { useFlowContext } from '../../../../../../FlowContext'; import { useApproval } from '../../../approval-common/ApprovalData.provider'; +import { useResubmit } from '../../../approval-common/Resubmit.provider'; import { useHandleRefresh } from '../../common/useHandleRefresh'; +import { useCreateSubmit } from '../apply-button/hooks/useSubmit'; import { useContextApprovalStatus } from '../Pd.ApplyActionStatus'; export function useSubmit() { const { refreshTable } = useHandleRefresh(); const apiClient = useAPIClient(); + const { isResubmit } = useResubmit(); + const { run: create } = useCreateSubmit(); + const status = useContextApprovalStatus(); const form = useForm(); const field = useField(); @@ -20,7 +25,10 @@ export function useSubmit() { const contextApprovalStatus = useContextApprovalStatus(); return { - async run() { + async run(props) { + if (isResubmit) { + return await create({ approvalStatus: status }); + } try { form.submit(); _.set(field, ['data', 'loading'], true); diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-common/Resubmit.provider.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-common/Resubmit.provider.tsx new file mode 100644 index 000000000..efc75635b --- /dev/null +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/features/approval/usage/approval-common/Resubmit.provider.tsx @@ -0,0 +1,17 @@ +import React, { useContext, useState } from 'react'; + +interface ResubmitProps { + isResubmit?: boolean; + setResubmit?: any; +} + +const ResubmitContext = React.createContext({}); + +export const ResubmitProvider = ({ children }) => { + const [isResubmit, setResubmit] = useState(false); + return {children}; +}; + +export const useResubmit = () => { + return useContext(ResubmitContext); +}; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/server/features/approval/actions.ts b/packages/plugins/@tachybase/plugin-workflow/src/server/features/approval/actions.ts index 7de58554b..e9d5ae402 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/server/features/approval/actions.ts +++ b/packages/plugins/@tachybase/plugin-workflow/src/server/features/approval/actions.ts @@ -1,8 +1,8 @@ import actions, { utils } from '@tachybase/actions'; import { parseCollectionName } from '@tachybase/data-source-manager'; +import { traverseJSON } from '@tachybase/database'; import { EXECUTION_STATUS, JOB_STATUS, PluginWorkflow } from '../..'; -import { appends } from '../../../client/schemas/collection'; import { APPROVAL_ACTION_STATUS, APPROVAL_STATUS } from './constants'; import { getSummary } from './tools'; import { getAssociationName, jsonParse } from './utils'; @@ -47,7 +47,7 @@ const approvals = { const { repository, model } = collection; const values = await repository.create({ values: { - ...data, + ...traverseJSON(data, { collection }), createdBy: context.state.currentUser.id, updatedBy: context.state.currentUser.id, },