feat: refactor resubmit (#1290)
Co-authored-by: sealday <sealday@gmail.com> Reviewed-on: https://git.daoyoucloud.com:8443/daoyoucloud/tachybase/pulls/1290
This commit is contained in:
parent
0b958cf528
commit
1d5306d427
@ -38,3 +38,5 @@ export default class DatabaseUtils {
|
||||
return this.db.options.schema || 'public';
|
||||
}
|
||||
}
|
||||
|
||||
export * from './traverseJSON';
|
||||
|
112
packages/core/database/src/database-utils/traverseJSON.ts
Normal file
112
packages/core/database/src/database-utils/traverseJSON.ts
Normal file
@ -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;
|
||||
};
|
@ -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';
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 <Spin />;
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -61,7 +55,6 @@ export const SchemaAddBlock = ({ value, onChange }) => {
|
||||
useFormBlockProps,
|
||||
useActionResubmit,
|
||||
}}
|
||||
// @ts-ignore ugly
|
||||
schema={data}
|
||||
/>
|
||||
</SchemaComponentProvider>
|
||||
@ -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());
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 <ContextApprovalStatus.Provider value={value}>{children}</ContextApprovalStatus.Provider>;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 = () => {
|
||||
>
|
||||
<ApprovalContext.Provider value={approval}>
|
||||
<ContextApprovalExecution.Provider value={approvalValue}>
|
||||
<SchemaComponent
|
||||
components={{
|
||||
SchemaComponentProvider: SchemaComponentProvider,
|
||||
RemoteSchemaComponent: RemoteSchemaComponent,
|
||||
SchemaComponentContextProvider,
|
||||
FormBlockProvider,
|
||||
ActionBarProvider,
|
||||
ApplyActionStatusProvider,
|
||||
WithdrawActionProvider,
|
||||
DetailsBlockProvider,
|
||||
ProviderActionResubmit,
|
||||
}}
|
||||
scope={{
|
||||
useForm,
|
||||
useSubmit: useSubmit,
|
||||
useFormBlockProps,
|
||||
useDetailsBlockProps: useFormBlockContext,
|
||||
useWithdrawAction,
|
||||
useDestroyAction,
|
||||
useActionResubmit,
|
||||
}}
|
||||
schema={{
|
||||
name: `view-${approval == null ? void 0 : approval.id}`,
|
||||
type: 'void',
|
||||
properties: {
|
||||
tabs: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
properties: Object.assign(
|
||||
{
|
||||
detail: {
|
||||
type: 'void',
|
||||
title: `{{t('Application content', { ns: '${NAMESPACE}' })}}`,
|
||||
'x-component': 'Tabs.TabPane',
|
||||
properties: {
|
||||
detail: {
|
||||
type: 'void',
|
||||
'x-decorator': 'SchemaComponentContextProvider',
|
||||
'x-decorator-props': {
|
||||
designable: false,
|
||||
},
|
||||
'x-component': 'RemoteSchemaComponent',
|
||||
'x-component-props': {
|
||||
uid: workflow?.config.applyForm,
|
||||
noForm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
needHideProcess
|
||||
? {}
|
||||
: {
|
||||
process: {
|
||||
type: 'void',
|
||||
title: `{{t('Approval process', { ns: '${NAMESPACE}' })}}`,
|
||||
'x-component': 'Tabs.TabPane',
|
||||
properties: {
|
||||
process: {
|
||||
type: 'void',
|
||||
'x-decorator': 'CardItem',
|
||||
'x-component': 'ApprovalCommon.ViewComponent.ApprovalProcess',
|
||||
<ResubmitProvider>
|
||||
<SchemaComponent
|
||||
components={{
|
||||
SchemaComponentProvider,
|
||||
RemoteSchemaComponent,
|
||||
SchemaComponentContextProvider,
|
||||
FormBlockProvider,
|
||||
ActionBarProvider,
|
||||
ApplyActionStatusProvider,
|
||||
WithdrawActionProvider,
|
||||
DetailsBlockProvider,
|
||||
ProviderActionResubmit,
|
||||
}}
|
||||
scope={{
|
||||
useForm,
|
||||
useSubmit,
|
||||
useFormBlockProps,
|
||||
useDetailsBlockProps: useFormBlockContext,
|
||||
useWithdrawAction,
|
||||
useDestroyAction,
|
||||
useActionResubmit,
|
||||
}}
|
||||
schema={{
|
||||
name: `view-${approval == null ? void 0 : approval.id}`,
|
||||
type: 'void',
|
||||
properties: {
|
||||
tabs: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
properties: Object.assign(
|
||||
{
|
||||
detail: {
|
||||
type: 'void',
|
||||
title: `{{t('Application content', { ns: '${NAMESPACE}' })}}`,
|
||||
'x-component': 'Tabs.TabPane',
|
||||
properties: {
|
||||
detail: {
|
||||
type: 'void',
|
||||
'x-decorator': 'SchemaComponentContextProvider',
|
||||
'x-decorator-props': {
|
||||
designable: false,
|
||||
},
|
||||
'x-component': 'RemoteSchemaComponent',
|
||||
'x-component-props': {
|
||||
uid: workflow?.config.applyForm,
|
||||
noForm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
needHideProcess
|
||||
? {}
|
||||
: {
|
||||
process: {
|
||||
type: 'void',
|
||||
title: `{{t('Approval process', { ns: '${NAMESPACE}' })}}`,
|
||||
'x-component': 'Tabs.TabPane',
|
||||
properties: {
|
||||
process: {
|
||||
type: 'void',
|
||||
'x-decorator': 'CardItem',
|
||||
'x-component': 'ApprovalCommon.ViewComponent.ApprovalProcess',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}}
|
||||
/>
|
||||
</ResubmitProvider>
|
||||
</ContextApprovalExecution.Provider>
|
||||
</ApprovalContext.Provider>
|
||||
</FlowContextProvider>
|
||||
|
@ -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 = () => {
|
||||
<SchemaComponent
|
||||
schema={schema}
|
||||
components={{
|
||||
RemoteSchemaComponent: RemoteSchemaComponent,
|
||||
CollectionProvider_deprecated: CollectionProvider_deprecated,
|
||||
FlowContextProvider: FlowContextProvider,
|
||||
ApplyActionStatusProvider: ApplyActionStatusProvider,
|
||||
RemoteSchemaComponent,
|
||||
CollectionProvider_deprecated,
|
||||
FlowContextProvider,
|
||||
ApplyActionStatusProvider,
|
||||
ActionBarProvider,
|
||||
WithdrawActionProvider: WithdrawActionProvider,
|
||||
ProviderActionResubmit: () => null,
|
||||
WithdrawActionProvider,
|
||||
}}
|
||||
scope={{
|
||||
useSubmit: useSubmit,
|
||||
useSubmit: useCreateSubmit,
|
||||
useWithdrawAction,
|
||||
useActionResubmit,
|
||||
}}
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
@ -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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -0,0 +1,17 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
|
||||
interface ResubmitProps {
|
||||
isResubmit?: boolean;
|
||||
setResubmit?: any;
|
||||
}
|
||||
|
||||
const ResubmitContext = React.createContext<ResubmitProps>({});
|
||||
|
||||
export const ResubmitProvider = ({ children }) => {
|
||||
const [isResubmit, setResubmit] = useState(false);
|
||||
return <ResubmitContext.Provider value={{ isResubmit, setResubmit }}>{children}</ResubmitContext.Provider>;
|
||||
};
|
||||
|
||||
export const useResubmit = () => {
|
||||
return useContext(ResubmitContext);
|
||||
};
|
@ -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,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user