feat: plugin workflow collection field (#934)

* feat(plugin-workflow): support association constant simple input

* fix(plugin-workflow): remove useless code
# Conflicts:
#	packages/plugins/workflow/src/client/components/CollectionFieldset.tsx
This commit is contained in:
Junyi 2022-10-19 12:36:45 +08:00 committed by chenos
parent 42dbaf3582
commit 26c428a15b
2 changed files with 157 additions and 1 deletions

View File

@ -46,7 +46,6 @@ export const useValues = () => {
field.data.operator = operator;
field.data.schema = merge(option?.schema, operator?.schema);
field.data.value = get(field.value, `${fieldPath}.$${operatorValue}`);
console.log('option', operator, field.data.value);
};
useEffect(() => {
value2data();

View File

@ -0,0 +1,157 @@
import React from "react";
import { observer, useForm, useField } from "@formily/react";
import { Input, Button, Dropdown, Menu, Form } from "antd";
import { PlusOutlined, CloseCircleOutlined } from '@ant-design/icons';
import { useTranslation } from "react-i18next";
import { css } from "@emotion/css";
import { CollectionField, CollectionProvider, SchemaComponent, useCollectionManager, useCompile } from "@nocobase/client";
import { Operand, parseStringValue, VariableTypes, VariableTypesContext } from "../calculators";
function AssociationInput(props) {
const { getCollectionFields } = useCollectionManager();
const { path } = useField();
const fieldName = path.segments[path.segments.length - 1] as string;
const { values: data } = useForm();
const fields = getCollectionFields(data?.config?.collection);
const { type } = fields.find(item => item.name === fieldName);
const value = Array.isArray(props.value) ? props.value.join(',') : props.value;
function onChange(ev) {
const trimed = ev.target.value.trim();
props.onChange(['belongsTo', 'hasOne'].includes(type) ? trimed : trimed.split(/[,\s]+/));
}
return (
<Input {...props} value={value} onChange={onChange} />
);
}
// NOTE: observer for watching useProps
export default observer(({ value, onChange }: any) => {
const { t } = useTranslation();
const compile = useCompile();
const { getCollection, getCollectionFields } = useCollectionManager();
const { values: data } = useForm();
const collectionName = data?.config?.collection;
const fields = getCollectionFields(collectionName)
.filter(field => (
!field.hidden
&& (field.uiSchema ? !field.uiSchema['x-read-pretty'] : false)
// && (!['linkTo', 'hasMany', 'hasOne', 'belongsToMany'].includes(field.type))
));
return (
<fieldset className={css`
margin-top: .5em;
> .ant-formily-item{
flex-direction: column;
> .ant-formily-item-label{
line-height: 32px;
}
}
`}>
{fields.length
? (
<CollectionProvider collection={getCollection(collectionName)}>
{fields
.filter(field => field.name in value)
.map(field => {
const VTypes = {
...(['linkTo', 'hasMany', 'belongsToMany'].includes(field.type) ? {} : VariableTypes),
constant: {
title: '{{t("Constant")}}',
value: 'constant',
options: undefined
}
};
const operand = typeof value[field.name] === 'string'
? parseStringValue(value[field.name], VTypes)
: { type: 'constant', value: value[field.name] };
// constant for associations to use Input, others to use CollectionField
// dynamic values only support belongsTo/hasOne association, other association type should disable
// TODO: try to use <ObjectField> to replace this map
return (
<Form.Item key={field.name} label={compile(field.uiSchema?.title ?? field.name)} labelAlign="left" className={css`
.ant-form-item-control-input-content{
display: flex;
}
`}>
<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={{
type: 'void',
properties: {
[field.name]: {
'x-component': ['linkTo', 'belongsTo', 'hasOne', 'hasMany', 'belongsToMany'].includes(field.type)
? 'AssociationInput'
: 'CollectionField'
}
}
}}
components={{
CollectionField,
AssociationInput
}}
/>
)
// ? <SchemaComponent schema={{ ...field.uiSchema, name: field.name }} />
: null
}
</Operand>
<Button
type="link"
icon={<CloseCircleOutlined />}
onClick={() => {
const { [field.name]: _, ...rest } = value;
onChange(rest);
}}
/>
</VariableTypesContext.Provider>
</Form.Item>
);
})
}
{Object.keys(value).length < fields.length
? (
<Dropdown overlay={
<Menu onClick={({ key }) => onChange({ ...value, [key]: null })} className={css`
max-height: 300px;
overflow-y: auto;
`}>
{fields
.filter(field => !(field.name in value))
.map(field => (
<Menu.Item key={field.name}>{compile(field.uiSchema?.title ?? field.name)}</Menu.Item>
))}
</Menu>
}>
<Button icon={<PlusOutlined />}>{t('Add field')}</Button>
</Dropdown>
)
: null
}
</CollectionProvider>
)
: <p>{t('Please select collection first')}</p>
}
</fieldset>
);
});