mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 13:37:37 +00:00
feat(plugin-workflow): add create node component (#292)
This commit is contained in:
parent
5039896b16
commit
e002777b63
@ -65,7 +65,7 @@ export function parseStringValue(value: string, Types) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type,
|
type,
|
||||||
options: paths.length ? (Types || VariableTypes)[type].parse(paths) : {}
|
options: paths.length ? (Types || VariableTypes)[type]?.parse(paths) : {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ export function Operand({
|
|||||||
|
|
||||||
const { type } = operand;
|
const { type } = operand;
|
||||||
|
|
||||||
const { component, appendTypeValue } = Types[type];
|
const { component, appendTypeValue } = Types[type] || {};
|
||||||
const VariableComponent = typeof component === 'function' ? component(operand) : NullRender;
|
const VariableComponent = typeof component === 'function' ? component(operand) : NullRender;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
156
packages/client/src/workflow/nodes/create.tsx
Normal file
156
packages/client/src/workflow/nodes/create.tsx
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { observer, useForm } from '@formily/react';
|
||||||
|
import { action } from '@formily/reactive';
|
||||||
|
import { Select } from 'antd';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
|
import { SchemaComponent, useCollectionManager } from '../..';
|
||||||
|
import { useCollectionFilterOptions } from '../../collection-manager/action-hooks';
|
||||||
|
import { useFlowContext } from '../WorkflowCanvas';
|
||||||
|
import { Operand, parseStringValue, VariableTypes, VariableTypesContext, BaseTypeSet } from '../calculators';
|
||||||
|
import { FormItem } from '@formily/antd';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: '新增',
|
||||||
|
type: 'create',
|
||||||
|
group: 'model',
|
||||||
|
fieldset: {
|
||||||
|
collection: {
|
||||||
|
type: 'string',
|
||||||
|
title: '数据表',
|
||||||
|
name: 'collection',
|
||||||
|
required: true,
|
||||||
|
'x-reactions': ['{{useCollectionDataSource()}}'],
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
},
|
||||||
|
// multiple: {
|
||||||
|
// type: 'boolean',
|
||||||
|
// title: '多条数据',
|
||||||
|
// name: 'multiple',
|
||||||
|
// 'x-decorator': 'FormItem',
|
||||||
|
// 'x-component': 'Checkbox',
|
||||||
|
// 'x-component-props': {
|
||||||
|
// disabled: true
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
params: {
|
||||||
|
type: 'object',
|
||||||
|
name: 'params',
|
||||||
|
title: '数据',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
properties: {
|
||||||
|
values: {
|
||||||
|
type: 'object',
|
||||||
|
title: '',
|
||||||
|
name: 'values',
|
||||||
|
'x-component': 'DynamicFieldset',
|
||||||
|
'x-component-props': {
|
||||||
|
useProps() {
|
||||||
|
const { values } = useForm();
|
||||||
|
return { fields: useCollectionFilterOptions(values.collection) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
view: {
|
||||||
|
|
||||||
|
},
|
||||||
|
scope: {
|
||||||
|
useCollectionDataSource() {
|
||||||
|
return (field: any) => {
|
||||||
|
const { collections = [] } = useCollectionManager();
|
||||||
|
action.bound((data: any) => {
|
||||||
|
field.dataSource = data.map(item => ({
|
||||||
|
label: t(item.title),
|
||||||
|
value: item.name
|
||||||
|
}));
|
||||||
|
})(collections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
// NOTE: observer for watching useProps
|
||||||
|
DynamicFieldset: observer(({ value, onChange, useProps }: any) => {
|
||||||
|
const { fields } = useProps();
|
||||||
|
|
||||||
|
const VTypes = { ...VariableTypes,
|
||||||
|
constant: {
|
||||||
|
title: '常量',
|
||||||
|
value: 'constant',
|
||||||
|
options: undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<fieldset className={css`
|
||||||
|
margin-top: .5em;
|
||||||
|
|
||||||
|
.ant-formily-item{
|
||||||
|
.ant-formily-item-label{
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select,
|
||||||
|
.ant-cascader-picker,
|
||||||
|
.ant-picker,
|
||||||
|
.ant-input-number,
|
||||||
|
.ant-input-affix-wrapper{
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}>
|
||||||
|
{fields.map(field => {
|
||||||
|
const operand = typeof value[field.name] === 'string'
|
||||||
|
? parseStringValue(value[field.name], VTypes)
|
||||||
|
: { type: 'constant', value: value[field.name] };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItem label={field.title}>
|
||||||
|
<VariableTypesContext.Provider value={VTypes}>
|
||||||
|
<Operand
|
||||||
|
value={operand}
|
||||||
|
onChange={(next) => {
|
||||||
|
if (next.type !== operand.type && next.type === 'constant') {
|
||||||
|
onChange({ ...value, [field.name]: null });
|
||||||
|
} else {
|
||||||
|
const { stringify } = VTypes[next.type];
|
||||||
|
onChange({ ...value, [field.name]: stringify(next) });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{operand.type === 'constant'
|
||||||
|
? <SchemaComponent schema={field.schema} />
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</Operand>
|
||||||
|
</VariableTypesContext.Provider>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</fieldset>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getter({ type, options, onChange }) {
|
||||||
|
const { collections = [] } = useCollectionManager();
|
||||||
|
const { nodes } = useFlowContext();
|
||||||
|
const { config } = nodes.find(n => n.id == options.nodeId);
|
||||||
|
const collection = collections.find(item => item.name === config.collection) ?? { fields: [] };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select value={options.path} placeholder="选择字段" onChange={path => {
|
||||||
|
onChange({ type, options: { ...options, path } });
|
||||||
|
}}>
|
||||||
|
{collection.fields
|
||||||
|
.filter(field => BaseTypeSet.has(field.uiSchema.type))
|
||||||
|
.map(field => (
|
||||||
|
<Select.Option key={field.name} value={field.name}>{t(field.uiSchema.title)}</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
@ -12,6 +12,7 @@ import { AddButton, useFlowContext } from '../WorkflowCanvas';
|
|||||||
import { nodeClass, nodeCardClass, nodeHeaderClass, nodeTitleClass, nodeBlockClass } from '../style';
|
import { nodeClass, nodeCardClass, nodeHeaderClass, nodeTitleClass, nodeBlockClass } from '../style';
|
||||||
|
|
||||||
import query from './query';
|
import query from './query';
|
||||||
|
import create from './create';
|
||||||
import condition from './condition';
|
import condition from './condition';
|
||||||
import parallel from './parallel';
|
import parallel from './parallel';
|
||||||
import calculation from './calculation';
|
import calculation from './calculation';
|
||||||
@ -59,6 +60,7 @@ export interface Instruction {
|
|||||||
export const instructions = new Registry<Instruction>();
|
export const instructions = new Registry<Instruction>();
|
||||||
|
|
||||||
instructions.register('query', query);
|
instructions.register('query', query);
|
||||||
|
instructions.register('create', create);
|
||||||
instructions.register('condition', condition);
|
instructions.register('condition', condition);
|
||||||
instructions.register('parallel', parallel);
|
instructions.register('parallel', parallel);
|
||||||
instructions.register('calculation', calculation);
|
instructions.register('calculation', calculation);
|
||||||
@ -159,6 +161,8 @@ export function NodeDefaultView(props) {
|
|||||||
type: 'void',
|
type: 'void',
|
||||||
properties: {
|
properties: {
|
||||||
view: instruction.view,
|
view: instruction.view,
|
||||||
|
...(Object.keys(instruction.fieldset).length
|
||||||
|
? {
|
||||||
config: {
|
config: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
title: '配置节点',
|
title: '配置节点',
|
||||||
@ -208,6 +212,8 @@ export function NodeDefaultView(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
: {})
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@ import { useFlowContext } from '../WorkflowCanvas';
|
|||||||
import { Operand, parseStringValue, VariableTypes, VariableTypesContext, BaseTypeSet } from '../calculators';
|
import { Operand, parseStringValue, VariableTypes, VariableTypesContext, BaseTypeSet } from '../calculators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: '数据查询',
|
title: '查询',
|
||||||
type: 'query',
|
type: 'query',
|
||||||
group: 'model',
|
group: 'model',
|
||||||
fieldset: {
|
fieldset: {
|
||||||
|
@ -72,11 +72,15 @@ export default {
|
|||||||
const collection = collections.find(item => item.name === workflow.config.collection) ?? { fields: [] };
|
const collection = collections.find(item => item.name === workflow.config.collection) ?? { fields: [] };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select value={options?.path.replace(/^data\./, '')} placeholder="选择字段" onChange={path => {
|
<Select
|
||||||
|
placeholder="选择字段"
|
||||||
|
value={options?.path?.replace(/^data\./, '')}
|
||||||
|
onChange={(path) => {
|
||||||
onChange({ type, options: { ...options, path: `data.${path}` } });
|
onChange({ type, options: { ...options, path: `data.${path}` } });
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{collection.fields
|
{collection.fields
|
||||||
.filter(field => BaseTypeSet.has(field.uiSchema.type))
|
.filter(field => BaseTypeSet.has(field?.uiSchema?.type))
|
||||||
.map(field => (
|
.map(field => (
|
||||||
<Select.Option key={field.name} value={field.name}>{t(field.uiSchema.title)}</Select.Option>
|
<Select.Option key={field.name} value={field.name}>{t(field.uiSchema.title)}</Select.Option>
|
||||||
))}
|
))}
|
||||||
|
Loading…
Reference in New Issue
Block a user