Fix(plugin workflow): UX issues (#329)

* fix(plugin-workflow): typo

* fix(plugin-workflow): text and style

* fix(plugin-workflow): fix trigger form validation

* fix(plugin-workflow): try to fix config field

* fix: config

* fix(plugin-workflow): node config value

Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
Junyi 2022-04-27 10:31:16 +08:00 committed by GitHub
parent 72d32be2b0
commit 2e80e0c2c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 207 additions and 130 deletions

View File

@ -32,7 +32,7 @@ export const calculators = [
children: [
{ value: 'add', name: '+' },
{ value: 'minus', name: '-' },
{ value: 'multipe', name: '*' },
{ value: 'multiple', name: '*' },
{ value: 'divide', name: '/' },
{ value: 'mod', name: '%' },
]
@ -396,7 +396,10 @@ export const CollectionFieldset = observer(({ value, onChange, useProps }: any)
`}>
{fields.length
? fields
.filter(field => !field.hidden)
.filter(field => (
!field.hidden
&& (field.uiSchema ? !field.uiSchema['x-read-pretty'] : true)
))
.map(field => {
const operand = typeof value[field.name] === 'string'
? parseStringValue(value[field.name], VTypes)

View File

@ -1,3 +1,4 @@
import { css } from '@emotion/css';
import React from 'react';
import { Calculation } from '../calculators';
@ -6,10 +7,10 @@ export default {
type: 'calculation',
group: 'control',
fieldset: {
calculation: {
'config.calculation': {
type: 'object',
title: '配置计算',
name: 'calculation',
name: 'config.calculation',
required: true,
'x-decorator': 'FormItem',
'x-component': 'CalculationConfig',
@ -26,6 +27,6 @@ export default {
}
},
getter() {
return <div></div>;
return <div className={css`flex-shrink: 0`}></div>;
}
};

View File

@ -1,7 +1,7 @@
import React from "react";
import { css, cx } from "@emotion/css";
import { Button, Select } from "antd";
import { CloseCircleOutlined } from '@ant-design/icons';
import { Button, Select, Tooltip } from "antd";
import { CloseCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Trans } from "react-i18next";
import { NodeDefaultView } from ".";
@ -66,17 +66,20 @@ function CalculationGroup({ value, onChange }) {
}
return (
<div className={css`
<div className={cx('node-type-condition-group', css`
position: relative;
width: 100%;
padding: .5em 1em;
border: 1px dashed #ddd;
.node-type-condition-group{
padding: .5em 1em;
border: 1px dashed #ddd;
}
+ button{
position: absolute;
right: 0;
}
`}>
`)}>
<div className={css`
display: flex;
align-items: center;
@ -131,9 +134,9 @@ export default {
type: 'condition',
group: 'control',
fieldset: {
rejectOnFalse: {
'config.rejectOnFalse': {
type: 'boolean',
name: 'rejectOnFalse',
name: 'config.rejectOnFalse',
title: '模式',
'x-decorator': 'FormItem',
'x-component': 'Radio.Group',
@ -141,13 +144,33 @@ export default {
disabled: true,
},
enum: [
{ value: true, label: '通行模式' },
{ value: false, label: '分支模式' },
{
value: true,
label: (
<Tooltip
title="判断为“是”时继续"
placement="bottom"
>
<QuestionCircleOutlined style={{ color: '#999' }} />
</Tooltip>
)
},
{
value: false,
label: (
<Tooltip
title="判断结果分为“是”和“否”两个分支,分别继续"
placement="bottom"
>
<QuestionCircleOutlined style={{ color: '#999' }} />
</Tooltip>
)
}
],
},
calculation: {
'config.calculation': {
type: 'string',
name: 'calculation',
name: 'config.calculation',
title: '条件配置',
'x-decorator': 'FormItem',
'x-component': 'CalculationConfig',

View File

@ -1,17 +1,20 @@
import React from 'react';
import { Select } from 'antd';
import React from 'react';
import { useCollectionDataSource, useCollectionManager, useCompile } from '../..';
import { useFlowContext } from '../WorkflowCanvas';
import { collection, values } from '../schemas/collection';
import { BaseTypeSet, CollectionFieldset } from '../calculators';
import { collection, values } from '../schemas/collection';
import { useFlowContext } from '../WorkflowCanvas';
export default {
title: '新增数据',
type: 'create',
group: 'model',
fieldset: {
collection,
'config.collection': {
name: 'config.collection',
...collection,
},
// multiple: {
// type: 'boolean',
// title: '多条数据',
@ -22,9 +25,9 @@ export default {
// disabled: true
// }
// },
params: {
'config.params': {
type: 'object',
name: 'params',
name: 'config.params',
title: '',
'x-decorator': 'FormItem',
properties: {

View File

@ -8,10 +8,10 @@ export default {
type: 'destroy',
group: 'model',
fieldset: {
collection,
params: {
'config.collection': collection,
'config.params': {
type: 'object',
name: 'params',
name: 'config.params',
title: '',
'x-decorator': 'FormItem',
properties: {

View File

@ -1,23 +1,24 @@
import React, { useContext } from 'react';
import { CloseOutlined, DeleteOutlined } from '@ant-design/icons';
import { css, cx } from '@emotion/css';
import { Button, Modal, Tag } from 'antd';
import { DeleteOutlined, CloseOutlined } from '@ant-design/icons';
import { ISchema, useForm } from '@formily/react';
import { Field } from '@formily/core';
import { ISchema, RecursionField, useField, useForm } from '@formily/react';
import { Registry } from '@nocobase/utils';
import { Button, Modal, Tag } from 'antd';
import React, { useContext } from 'react';
import { SchemaComponent, useActionContext, useAPIClient, useCollection, useRequest, useResourceActionContext } from '../..';
import { nodeBlockClass, nodeCardClass, nodeClass, nodeHeaderClass, nodeTitleClass } from '../style';
import { AddButton, useFlowContext } from '../WorkflowCanvas';
import { nodeClass, nodeCardClass, nodeHeaderClass, nodeTitleClass, nodeBlockClass } from '../style';
import query from './query';
import create from './create';
import update from './update';
import destroy from './destroy';
import condition from './condition';
import parallel from './parallel';
import calculation from './calculation';
import condition from './condition';
import create from './create';
import destroy from './destroy';
import parallel from './parallel';
import query from './query';
import update from './update';
@ -45,7 +46,7 @@ instructions.register('condition', condition);
instructions.register('parallel', parallel);
instructions.register('calculation', calculation);
function useUpdateConfigAction() {
function useUpdateAction() {
const form = useForm();
const api = useAPIClient();
const ctx = useActionContext();
@ -53,14 +54,13 @@ function useUpdateConfigAction() {
const data = useNodeContext();
return {
async run() {
await form.submit();
await api.resource('flow_nodes', data.id).update({
filterByTk: data.id,
values: {
config: {
...data.config,
...form.values
}
},
title: form.values.title,
config: form.values.config
}
});
ctx.setVisible(false);
refresh();
@ -148,6 +148,14 @@ export function RemoveButton() {
);
}
function Fieldset({ schema }) {
const field = useField<Field>();
return (
<RecursionField basePath={field.address} schema={schema} />
);
}
export function NodeDefaultView(props) {
const { data, children } = props;
const instruction = instructions.get(data.type);
@ -166,63 +174,75 @@ export function NodeDefaultView(props) {
</div>
<SchemaComponent
scope={instruction.scope}
components={instruction.components}
components={{
...instruction.components,
Fieldset
}}
schema={{
type: 'void',
properties: {
view: instruction.view,
...(Object.keys(instruction.fieldset).length
? {
config: {
config: {
type: 'void',
title: '配置节点',
'x-component': 'Action.Link',
'x-component-props': {
type: 'primary',
},
properties: {
drawer: {
type: 'void',
title: '配置节点',
'x-component': 'Action.Link',
'x-component-props': {
type: 'primary',
'x-component': 'Action.Drawer',
'x-decorator': 'Form',
'x-decorator-props': {
useValues(options) {
const data = useNodeContext();
return useRequest(() => {
return Promise.resolve({ data });
}, options);
}
},
properties: {
drawer: {
title: {
type: 'string',
name: 'title',
title: '节点名称',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
config: {
type: 'void',
title: '配置节点',
'x-component': 'Action.Drawer',
'x-decorator': 'Form',
'x-decorator-props': {
useValues(options) {
const node = useNodeContext();
return useRequest(() => {
return Promise.resolve({ data: node.config });
}, options);
}
},
name: 'config',
'x-component': 'fieldset',
'x-component-props': {},
properties: instruction.fieldset
},
actions: {
type: 'void',
'x-component': 'Action.Drawer.Footer',
properties: {
...instruction.fieldset,
actions: {
type: 'void',
'x-component': 'Action.Drawer.Footer',
properties: {
cancel: {
title: '{{t("Cancel")}}',
'x-component': 'Action',
'x-component-props': {
useAction: '{{ cm.useCancelAction }}',
},
},
submit: {
title: '{{t("Submit")}}',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
useAction: useUpdateConfigAction,
},
},
cancel: {
title: '{{t("Cancel")}}',
'x-component': 'Action',
'x-component-props': {
useAction: '{{ cm.useCancelAction }}',
},
} as ISchema
}
}
},
submit: {
title: '{{t("Submit")}}',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
useAction: useUpdateAction,
},
},
},
} as ISchema
}
}
}
: {})
}
}
}}
/>

View File

@ -1,6 +1,6 @@
import React, { useState } from "react";
import { css, cx } from "@emotion/css";
import { PlusOutlined } from '@ant-design/icons';
import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { NodeDefaultView } from ".";
import { Branch, useFlowContext } from "../WorkflowCanvas";
@ -13,17 +13,37 @@ export default {
type: 'parallel',
group: 'control',
fieldset: {
mode: {
'config.mode': {
type: 'string',
name: 'mode',
name: 'config.mode',
title: '模式',
'x-decorator': 'FormItem',
'x-component': 'Radio.Group',
'x-component-props': {
},
enum: [
{ value: 'all', label: '全部成功' },
{ value: 'any', label: '任意成功' },
{
value: 'all',
label: (
<Tooltip
title="全部分支都成功后才能继续"
placement="bottom"
>
<QuestionCircleOutlined style={{ color: '#999' }} />
</Tooltip>
)
},
{
value: 'any',
label: (
<Tooltip
title="任意分支成功后就继续"
placement="bottom"
>
<QuestionCircleOutlined style={{ color: '#999' }} />
</Tooltip>
)
},
// { value: 'race', label: '任意退出' },
],
default: 'all'

View File

@ -12,20 +12,20 @@ export default {
type: 'query',
group: 'model',
fieldset: {
collection,
multiple: {
'config.collection': collection,
'config.multiple': {
type: 'boolean',
title: '多条数据',
name: 'multiple',
name: 'config.multiple',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
'x-component-props': {
disabled: true
}
},
params: {
'config.params': {
type: 'object',
name: 'params',
name: 'config.params',
title: '',
'x-decorator': 'FormItem',
properties: {

View File

@ -7,10 +7,10 @@ export default {
type: 'update',
group: 'model',
fieldset: {
collection,
params: {
'config.collection': collection,
'config.params': {
type: 'object',
name: 'params',
name: 'config.params',
title: '',
'x-decorator': 'FormItem',
properties: {

View File

@ -6,7 +6,7 @@ import { useCollectionFilterOptions } from "../../collection-manager/action-hook
export const collection = {
type: 'string',
title: '数据表',
name: 'collection',
name: 'config.collection',
required: true,
'x-reactions': ['{{useCollectionDataSource()}}'],
'x-decorator': 'FormItem',
@ -16,7 +16,7 @@ export const collection = {
export const values = {
type: 'object',
title: '数据内容',
name: 'values',
name: 'config.params.values',
'x-decorator': 'FormItem',
'x-decorator-props': {
labelAlign: 'left',
@ -29,7 +29,7 @@ export const values = {
useProps() {
const { getCollectionFields } = useCollectionManager();
const { values: form } = useForm();
const fields = getCollectionFields(form.collection);
const fields = getCollectionFields(form?.config?.collection);
return { fields };
}
}
@ -38,7 +38,7 @@ export const values = {
export const filter = {
type: 'object',
title: '筛选条件',
name: 'filter',
name: 'config.params.filter',
'x-decorator': 'FormItem',
'x-decorator-props': {
labelAlign: 'left',
@ -50,14 +50,12 @@ export const filter = {
'x-component-props': {
useProps() {
const { values } = useForm();
const options = useCollectionFilterOptions(values.collection);
const options = useCollectionFilterOptions(values.config.collection);
return {
options,
className: css`
position: relative;
width: 100%;
padding: .5em 1em;
border: 1px dashed #ddd;
`
};
},

View File

@ -15,16 +15,6 @@ const collection = {
required: true,
} as ISchema,
},
// {
// type: 'string',
// name: 'description',
// interface: 'textarea',
// uiSchema: {
// title: '描述',
// type: 'string',
// 'x-component': 'TextArea',
// } as ISchema,
// },
{
type: 'string',
name: 'type',
@ -37,6 +27,17 @@ const collection = {
enum: [
{ value: 'model', label: '数据变动' }
],
required: true,
} as ISchema,
},
{
type: 'string',
name: 'description',
interface: 'textarea',
uiSchema: {
title: '描述',
type: 'string',
'x-component': 'Input.TextArea',
} as ISchema,
},
{
@ -95,6 +96,13 @@ export const workflowSchema: ISchema = {
type: 'void',
title: '删除',
'x-component': 'Action',
'x-component-props': {
useAction: '{{ cm.useBulkDestroyAction }}',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
},
},
create: {
type: 'void',
@ -114,11 +122,11 @@ export const workflowSchema: ISchema = {
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
},
description: {
type: {
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
},
type: {
description: {
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
},

View File

@ -16,6 +16,7 @@ function useUpdateConfigAction() {
const { refresh } = useResourceActionContext();
return {
async run() {
await form.submit();
await api.resource('workflows', record.id).update({
filterByTk: record.id,
values: {

View File

@ -21,10 +21,10 @@ export default {
'x-component': 'Select',
'x-component-props': {
options: [
{ value: 1, label: '新增数据' },
{ value: 2, label: '更新数据' },
{ value: 3, label: '新增或更新数据' },
{ value: 4, label: '删除数据' }
{ value: 1, label: '新增数据' },
{ value: 2, label: '更新数据' },
{ value: 3, label: '新增或更新数据' },
{ value: 4, label: '删除数据' }
]
}
},

View File

@ -148,7 +148,7 @@ function minus(a, b) {
return a - b;
}
function multipe(...args) {
function multiple(...args) {
return args.reduce((result, a) => result * a, 1);
}
@ -162,13 +162,13 @@ function mod(a, b) {
calculators.register('add', add);
calculators.register('minus', minus);
calculators.register('multipe', multipe);
calculators.register('multiple', multiple);
calculators.register('divide', divide);
calculators.register('mod', mod);
calculators.register('+', add);
calculators.register('-', minus);
calculators.register('*', multipe);
calculators.register('*', multiple);
calculators.register('/', divide);
calculators.register('%', mod);