feat(client): add form disabled context (#1374)
* feat(client): add form disabled context * fix: improve code * fix: improve code * fix: form-v2 disabled Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
246ee04154
commit
00efb38438
@ -1,7 +1,7 @@
|
|||||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||||
import { ObjectField as ObjectFieldModel } from '@formily/core';
|
import { ObjectField as ObjectFieldModel } from '@formily/core';
|
||||||
import { ArrayField, connect, useField } from '@formily/react';
|
import { ArrayField, connect, useField } from '@formily/react';
|
||||||
import { Select, Space } from 'antd';
|
import { ConfigProvider, Select, Space } from 'antd';
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { FilterLogicContext, RemoveConditionContext } from './context';
|
import { FilterLogicContext, RemoveConditionContext } from './context';
|
||||||
@ -20,84 +20,89 @@ export const FilterGroup = connect((props) => {
|
|||||||
[value]: [...(obj[logic] || [])],
|
[value]: [...(obj[logic] || [])],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
const mergedDisabled = field.disabled;
|
||||||
return (
|
return (
|
||||||
<FilterLogicContext.Provider value={logic}>
|
<ConfigProvider componentDisabled={mergedDisabled}>
|
||||||
<div
|
<FilterLogicContext.Provider value={logic}>
|
||||||
style={
|
<div
|
||||||
bordered
|
style={
|
||||||
? {
|
bordered
|
||||||
position: 'relative',
|
? {
|
||||||
border: '1px dashed #dedede',
|
position: 'relative',
|
||||||
padding: 14,
|
border: '1px dashed #dedede',
|
||||||
marginBottom: 8,
|
padding: 14,
|
||||||
}
|
marginBottom: 8,
|
||||||
: {
|
}
|
||||||
position: 'relative',
|
: {
|
||||||
marginBottom: 8,
|
position: 'relative',
|
||||||
}
|
marginBottom: 8,
|
||||||
}
|
}
|
||||||
>
|
}
|
||||||
{remove && (
|
>
|
||||||
<a>
|
{remove && !mergedDisabled && (
|
||||||
<CloseCircleOutlined
|
<a>
|
||||||
style={{
|
<CloseCircleOutlined
|
||||||
position: 'absolute',
|
style={{
|
||||||
right: 10,
|
position: 'absolute',
|
||||||
top: 10,
|
right: 10,
|
||||||
color: '#bfbfbf',
|
top: 10,
|
||||||
}}
|
color: '#bfbfbf',
|
||||||
onClick={() => remove()}
|
}}
|
||||||
/>
|
onClick={() => remove()}
|
||||||
</a>
|
/>
|
||||||
)}
|
</a>
|
||||||
<div style={{ marginBottom: 8 }}>
|
)}
|
||||||
<Trans>
|
<div style={{ marginBottom: 8 }}>
|
||||||
{'Meet '}
|
<Trans>
|
||||||
<Select
|
{'Meet '}
|
||||||
style={{ width: 'auto' }}
|
<Select
|
||||||
value={logic}
|
style={{ width: 'auto' }}
|
||||||
onChange={(value) => {
|
value={logic}
|
||||||
setLogic(value);
|
onChange={(value) => {
|
||||||
}}
|
setLogic(value);
|
||||||
>
|
}}
|
||||||
<Select.Option value={'$and'}>All</Select.Option>
|
>
|
||||||
<Select.Option value={'$or'}>Any</Select.Option>
|
<Select.Option value={'$and'}>All</Select.Option>
|
||||||
</Select>
|
<Select.Option value={'$or'}>Any</Select.Option>
|
||||||
{' conditions in the group'}
|
</Select>
|
||||||
</Trans>
|
{' conditions in the group'}
|
||||||
|
</Trans>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ArrayField name={logic} component={[FilterItems]} disabled={mergedDisabled} />
|
||||||
|
</div>
|
||||||
|
{!mergedDisabled && (
|
||||||
|
<Space size={16} style={{ marginTop: 8, marginBottom: 8 }}>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const value = field.value || {};
|
||||||
|
const items = value[logic] || [];
|
||||||
|
items.push({});
|
||||||
|
field.value = {
|
||||||
|
[logic]: items,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('Add condition')}
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
const value = field.value || {};
|
||||||
|
const items = value[logic] || [];
|
||||||
|
items.push({
|
||||||
|
$and: [{}],
|
||||||
|
});
|
||||||
|
field.value = {
|
||||||
|
[logic]: items,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('Add condition group')}
|
||||||
|
</a>
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</FilterLogicContext.Provider>
|
||||||
<ArrayField name={logic} component={[FilterItems]} />
|
</ConfigProvider>
|
||||||
</div>
|
|
||||||
<Space size={16} style={{ marginTop: 8, marginBottom: 8 }}>
|
|
||||||
<a
|
|
||||||
onClick={() => {
|
|
||||||
const value = field.value || {};
|
|
||||||
const items = value[logic] || [];
|
|
||||||
items.push({});
|
|
||||||
field.value = {
|
|
||||||
[logic]: items,
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('Add condition')}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
onClick={() => {
|
|
||||||
const value = field.value || {};
|
|
||||||
const items = value[logic] || [];
|
|
||||||
items.push({
|
|
||||||
$and: [{}],
|
|
||||||
});
|
|
||||||
field.value = {
|
|
||||||
[logic]: items,
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('Add condition group')}
|
|
||||||
</a>
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
</FilterLogicContext.Provider>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -50,9 +50,11 @@ export const FilterItem = observer((props: any) => {
|
|||||||
setValue(value);
|
setValue(value);
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
<a>
|
{!props.disabled && (
|
||||||
<CloseCircleOutlined onClick={() => remove()} style={{ color: '#bfbfbf' }} />
|
<a>
|
||||||
</a>
|
<CloseCircleOutlined onClick={() => remove()} style={{ color: '#bfbfbf' }} />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import { FormLayout } from '@formily/antd';
|
|||||||
import { createForm, Field, onFormInputChange } from '@formily/core';
|
import { createForm, Field, onFormInputChange } from '@formily/core';
|
||||||
import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import { Spin } from 'antd';
|
import { ConfigProvider, Spin } from 'antd';
|
||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { useActionContext } from '..';
|
import { useActionContext } from '..';
|
||||||
import { useAttach, useComponent } from '../..';
|
import { useAttach, useComponent } from '../..';
|
||||||
@ -32,7 +32,7 @@ const FormComponent: React.FC<FormProps> = (props) => {
|
|||||||
const Def = (props: any) => props.children;
|
const Def = (props: any) => props.children;
|
||||||
|
|
||||||
const FormDecorator: React.FC<FormProps> = (props) => {
|
const FormDecorator: React.FC<FormProps> = (props) => {
|
||||||
const { form, children, ...others } = props;
|
const { form, children, disabled, ...others } = props;
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
// TODO: component 里 useField 会与当前 field 存在偏差
|
// TODO: component 里 useField 会与当前 field 存在偏差
|
||||||
@ -65,6 +65,7 @@ const WithForm = (props) => {
|
|||||||
setFormValueChanged?.(true);
|
setFormValueChanged?.(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
form.disabled = props.disabled;
|
||||||
return () => {
|
return () => {
|
||||||
form.removeEffects(id);
|
form.removeEffects(id);
|
||||||
};
|
};
|
||||||
@ -78,6 +79,7 @@ const WithoutForm = (props) => {
|
|||||||
const form = useMemo(
|
const form = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createForm({
|
createForm({
|
||||||
|
disabled: props.disabled,
|
||||||
effects() {
|
effects() {
|
||||||
onFormInputChange((form) => {
|
onFormInputChange((form) => {
|
||||||
setFormValueChanged?.(true);
|
setFormValueChanged?.(true);
|
||||||
@ -95,12 +97,19 @@ const WithoutForm = (props) => {
|
|||||||
|
|
||||||
export const Form: React.FC<FormProps> & { Designer?: any; ReadPrettyDesigner?: any } = observer((props) => {
|
export const Form: React.FC<FormProps> & { Designer?: any; ReadPrettyDesigner?: any } = observer((props) => {
|
||||||
const field = useField<Field>();
|
const field = useField<Field>();
|
||||||
const { form, ...others } = useProps(props);
|
const { form, disabled, ...others } = useProps(props);
|
||||||
|
const formDisabled = disabled || field.disabled;
|
||||||
return (
|
return (
|
||||||
<form>
|
<ConfigProvider componentDisabled={formDisabled}>
|
||||||
<Spin spinning={field.loading || false}>
|
<form>
|
||||||
{form ? <WithForm form={form} {...others} /> : <WithoutForm {...others} />}
|
<Spin spinning={field.loading || false}>
|
||||||
</Spin>
|
{form ? (
|
||||||
</form>
|
<WithForm form={form} {...others} disabled={formDisabled} />
|
||||||
|
) : (
|
||||||
|
<WithoutForm {...others} disabled={formDisabled} />
|
||||||
|
)}
|
||||||
|
</Spin>
|
||||||
|
</form>
|
||||||
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -2,8 +2,8 @@ import { FormLayout } from '@formily/antd';
|
|||||||
import { createForm } from '@formily/core';
|
import { createForm } from '@formily/core';
|
||||||
import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||||
import { Options, Result } from 'ahooks/lib/useRequest/src/types';
|
import { Options, Result } from 'ahooks/lib/useRequest/src/types';
|
||||||
import { Spin } from 'antd';
|
import { ConfigProvider, Spin } from 'antd';
|
||||||
import React, { createContext, useContext, useMemo } from 'react';
|
import React, { createContext, useContext, useEffect, useMemo } from 'react';
|
||||||
import { useAttach, useComponent } from '../..';
|
import { useAttach, useComponent } from '../..';
|
||||||
import { useRequest } from '../../../api-client';
|
import { useRequest } from '../../../api-client';
|
||||||
import { useCollection } from '../../../collection-manager';
|
import { useCollection } from '../../../collection-manager';
|
||||||
@ -38,25 +38,30 @@ const FormComponent: React.FC<FormProps> = (props) => {
|
|||||||
const Def = (props: any) => props.children;
|
const Def = (props: any) => props.children;
|
||||||
|
|
||||||
const FormDecorator: React.FC<FormProps> = (props) => {
|
const FormDecorator: React.FC<FormProps> = (props) => {
|
||||||
const { form, children, ...others } = props;
|
const { form, children, disabled, ...others } = props;
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
// TODO: component 里 useField 会与当前 field 存在偏差
|
// TODO: component 里 useField 会与当前 field 存在偏差
|
||||||
const f = useAttach(form.createVoidField({ ...field.props, basePath: '' }));
|
const f = useAttach(form.createVoidField({ ...field.props, basePath: '' }));
|
||||||
const Component = useComponent(fieldSchema['x-component'], Def);
|
const Component = useComponent(fieldSchema['x-component'], Def);
|
||||||
|
useEffect(() => {
|
||||||
|
form.disabled = disabled || field.disabled;
|
||||||
|
}, [disabled, field.disabled]);
|
||||||
return (
|
return (
|
||||||
<FieldContext.Provider value={undefined}>
|
<ConfigProvider componentDisabled={disabled}>
|
||||||
<FormContext.Provider value={form}>
|
<FieldContext.Provider value={undefined}>
|
||||||
<FormLayout layout={'vertical'} {...others}>
|
<FormContext.Provider value={form}>
|
||||||
<FieldContext.Provider value={f}>
|
<FormLayout layout={'vertical'} {...others}>
|
||||||
<Component {...field.componentProps}>
|
<FieldContext.Provider value={f}>
|
||||||
<RecursionField basePath={f.address} schema={fieldSchema} onlyRenderProperties />
|
<Component {...field.componentProps}>
|
||||||
</Component>
|
<RecursionField basePath={f.address} schema={fieldSchema} onlyRenderProperties />
|
||||||
</FieldContext.Provider>
|
</Component>
|
||||||
{/* <FieldContext.Provider value={f}>{children}</FieldContext.Provider> */}
|
</FieldContext.Provider>
|
||||||
</FormLayout>
|
{/* <FieldContext.Provider value={f}>{children}</FieldContext.Provider> */}
|
||||||
</FormContext.Provider>
|
</FormLayout>
|
||||||
</FieldContext.Provider>
|
</FormContext.Provider>
|
||||||
|
</FieldContext.Provider>
|
||||||
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { ISchema, useForm } from '@formily/react';
|
import { ISchema, useForm } from '@formily/react';
|
||||||
import { Button, message, Modal, Tag } from 'antd';
|
import { Button, message, Modal, Tag, Alert } from 'antd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import parse from 'json-templates';
|
import parse from 'json-templates';
|
||||||
|
|
||||||
@ -334,6 +334,7 @@ export function NodeDefaultView(props) {
|
|||||||
'x-component': 'Action.Drawer',
|
'x-component': 'Action.Drawer',
|
||||||
'x-decorator': 'Form',
|
'x-decorator': 'Form',
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
|
disabled: workflow.executed,
|
||||||
useValues(options) {
|
useValues(options) {
|
||||||
const d = useNodeContext();
|
const d = useNodeContext();
|
||||||
return useRequest(() => {
|
return useRequest(() => {
|
||||||
@ -354,7 +355,6 @@ export function NodeDefaultView(props) {
|
|||||||
name: 'config',
|
name: 'config',
|
||||||
'x-component': 'fieldset',
|
'x-component': 'fieldset',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
disabled: workflow.executed,
|
|
||||||
className: css`
|
className: css`
|
||||||
.ant-select,
|
.ant-select,
|
||||||
.ant-cascader-picker,
|
.ant-cascader-picker,
|
||||||
@ -373,11 +373,16 @@ export function NodeDefaultView(props) {
|
|||||||
'x-component': 'Action.Drawer.Footer',
|
'x-component': 'Action.Drawer.Footer',
|
||||||
properties: workflow.executed
|
properties: workflow.executed
|
||||||
? {
|
? {
|
||||||
close: {
|
alert: {
|
||||||
title: '{{t("Close")}}',
|
'x-component': Alert,
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
useAction: '{{ cm.useCancelAction }}',
|
type: 'warning',
|
||||||
|
showIcon: true,
|
||||||
|
message: `{{t("Node in executed workflow cannot be modified", { ns: "${NAMESPACE}" })}}`,
|
||||||
|
className: css`
|
||||||
|
width: 100%;
|
||||||
|
font-size: 85%;
|
||||||
|
`
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { css, cx } from "@emotion/css";
|
import { css, cx } from "@emotion/css";
|
||||||
import { ISchema, useForm } from "@formily/react";
|
import { ISchema, useForm } from "@formily/react";
|
||||||
import { Registry } from "@nocobase/utils/client";
|
import { Registry } from "@nocobase/utils/client";
|
||||||
import { message, Tag } from "antd";
|
import { message, Tag, Alert } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { InfoOutlined } from '@ant-design/icons';
|
import { InfoOutlined } from '@ant-design/icons';
|
||||||
@ -159,6 +159,7 @@ export const TriggerConfig = () => {
|
|||||||
'x-component': 'Action.Drawer',
|
'x-component': 'Action.Drawer',
|
||||||
'x-decorator': 'Form',
|
'x-decorator': 'Form',
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
|
disabled: workflow.executed,
|
||||||
useValues(options) {
|
useValues(options) {
|
||||||
return useRequest(() => Promise.resolve({
|
return useRequest(() => Promise.resolve({
|
||||||
data: { config },
|
data: { config },
|
||||||
@ -185,11 +186,16 @@ export const TriggerConfig = () => {
|
|||||||
'x-component': 'Action.Drawer.Footer',
|
'x-component': 'Action.Drawer.Footer',
|
||||||
properties: executed
|
properties: executed
|
||||||
? {
|
? {
|
||||||
close: {
|
alert: {
|
||||||
title: '{{t("Close")}}',
|
'x-component': Alert,
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
useAction: '{{ cm.useCancelAction }}',
|
type: 'warning',
|
||||||
|
showIcon: true,
|
||||||
|
message: `{{t("Trigger in executed workflow cannot be modified", { ns: "${NAMESPACE}" })}}`,
|
||||||
|
className: css`
|
||||||
|
width: 100%;
|
||||||
|
font-size: 85%;
|
||||||
|
`
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user