field switch

This commit is contained in:
chenos 2021-07-27 18:38:54 +08:00
parent a9177116aa
commit 428beabd5a
5 changed files with 143 additions and 61 deletions

View File

@ -51,6 +51,7 @@ import {
createCollectionField,
createOrUpdateCollection,
createSchema,
removeSchema,
request,
useCollectionContext,
useDesignable,
@ -58,7 +59,7 @@ import {
} from '../';
import { uid } from '@formily/shared';
import { useRequest } from 'ahooks';
import { SchemaField } from '../../components/schema-renderer';
import { getSchemaPath, SchemaField } from '../../components/schema-renderer';
import { useResourceContext } from '../';
import { cloneDeep } from 'lodash';
import { options } from '../database-field/interfaces';
@ -67,6 +68,7 @@ import { useDisplayFieldsContext } from '../form';
import './style.less';
import IconPicker from '../../components/icon-picker';
import { barChartConfig, columnChartConfig } from './chart';
import { isGridRowOrCol } from '../grid';
const generateGridBlock = (schema: ISchema) => {
const name = schema.name || uid();
@ -659,9 +661,12 @@ AddNew.BlockItem = observer((props: any) => {
);
});
function FieldSwitch({ field, onChange, defaultChecked }) {
const [checked, setChecked] = useState(defaultChecked);
const form = useForm();
function SwitchField(props) {
const { field, onChange } = props;
const [checked, setChecked] = useState(props.checked);
useEffect(() => {
setChecked(props.checked);
}, [props.checked]);
return (
<div
style={{
@ -669,35 +674,32 @@ function FieldSwitch({ field, onChange, defaultChecked }) {
alignItems: 'center',
justifyContent: 'space-between',
}}
onClick={(e) => {
setChecked((value) => {
onChange && onChange(!value);
return !value;
onClick={async () => {
setChecked((checked) => {
onChange(!checked);
return !checked;
});
console.log('FieldSwitch', form);
}}
>
<span>{field?.uiSchema?.title || '未命名'}</span>
<Switch
onChange={(checked, e) => {
e.stopPropagation();
setChecked(checked);
onChange && onChange(checked);
}}
size={'small'}
checked={checked}
/>
<span>{field.uiSchema.title}</span>
<Switch checked={checked} size={'small'} />
</div>
);
}
AddNew.FormItem = observer((props: any) => {
const { ghost, defaultAction } = props;
const { schema, insertBefore, insertAfter, appendChild } = useDesignable();
const { schema, insertBefore, insertAfter, appendChild, deepRemove } =
useDesignable();
const path = useSchemaPath();
const { resource = {}, refresh } = useResourceContext();
const [visible, setVisible] = useState(false);
const { displayFields = [] } = useDisplayFieldsContext();
const {
displayFields,
hasDisplayField,
getDisplayField,
removeDisplayField,
} = useDisplayFieldsContext();
console.log({ displayFields });
return (
<Dropdown
@ -713,11 +715,23 @@ AddNew.FormItem = observer((props: any) => {
<Menu.ItemGroup className={'display-fields'} title={`要展示的字段`}>
{resource?.fields?.map((field) => (
<Menu.Item key={field.key}>
<FieldSwitch
<SwitchField
field={field}
defaultChecked={displayFields.includes(field.name)}
checked={hasDisplayField(field.name)}
onChange={async (checked) => {
if (!checked) {
const s: any = getDisplayField(field.name);
const p = getSchemaPath(s);
const removed = deepRemove(p);
if (!removed) {
console.log('getSchemaPath', p, removed);
return;
}
const last = removed.pop();
removeDisplayField(field.name);
if (isGridRowOrCol(last)) {
await removeSchema(last);
}
return;
}
let data: ISchema = {
@ -869,7 +883,7 @@ AddNew.PaneItem = observer((props: any) => {
const path = useSchemaPath();
const { resource = {}, refresh } = useResourceContext();
const [visible, setVisible] = useState(false);
const { displayFields = [] } = useDisplayFieldsContext();
const { displayFields } = useDisplayFieldsContext();
console.log({ displayFields });
return (
<Dropdown
@ -978,8 +992,15 @@ AddNew.PaneItem = observer((props: any) => {
</Menu.Item>
</Menu.ItemGroup>
<Menu.ItemGroup title={'相关数据区块'}>
<Menu.Item style={{ minWidth: 150 }} icon={<IconPicker type={'HistoryOutlined'} />}></Menu.Item>
<Menu.Item icon={<IconPicker type={'CommentOutlined'} />}></Menu.Item>
<Menu.Item
style={{ minWidth: 150 }}
icon={<IconPicker type={'HistoryOutlined'} />}
>
</Menu.Item>
<Menu.Item icon={<IconPicker type={'CommentOutlined'} />}>
</Menu.Item>
</Menu.ItemGroup>
<Menu.ItemGroup title={'多媒体区块'}>
<Menu.Item

View File

@ -8,3 +8,4 @@ group:
title: Schemas
path: /client/schemas
---

View File

@ -33,7 +33,7 @@ import constate from 'constate';
import { useEffect } from 'react';
import { uid } from '@formily/shared';
import { getSchemaPath } from '../../components/schema-renderer';
import { FormFieldUIDContext } from '.';
import { FormFieldUIDContext, useDisplayFieldsContext } from '.';
export const FieldDesignableBar = observer((props) => {
const field = useField();
@ -42,6 +42,7 @@ export const FieldDesignableBar = observer((props) => {
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
const fieldUid = useContext(FormFieldUIDContext);
const { removeDisplayField } = useDisplayFieldsContext();
const fieldName = schema['x-component-props']?.['fieldName'];
if (!designable) {
return null;
@ -93,8 +94,11 @@ export const FieldDesignableBar = observer((props) => {
key={'delete'}
onClick={async () => {
const removed = deepRemove();
console.log({ schema, removed });
const fieldName =
schema['x-component-props']?.['fieldName'];
console.log({ schema, removed, fieldName });
const last = removed.pop();
removeDisplayField(fieldName);
if (isGridRowOrCol(last)) {
await removeSchema(last);
}

View File

@ -39,15 +39,24 @@ import { FieldDesignableBar } from './Field.DesignableBar';
import { createContext } from 'react';
import { BlockItem } from '../block-item';
import { Resource } from '../../resource';
import { useMap } from 'ahooks';
const [DisplayFieldsContextProvider, useDisplayFieldsContext] = constate(() => {
const [displayFields, setDisplayFields] = useState([]);
const [displayFields, { set, remove, get }] = useMap([]);
return {
displayFields,
setDisplayFields,
addDisplayField(fieldName) {
setDisplayFields((fields) => fields.concat(fieldName));
hasDisplayField(fieldName) {
return !!get(fieldName);
},
addDisplayField(fieldName, schema) {
set(fieldName, schema);
},
getDisplayField(fieldName) {
return get(fieldName);
},
removeDisplayField(fieldName) {
remove(fieldName);
},
};
});
@ -65,7 +74,10 @@ export const Form: any = observer((props: any) => {
const initialValues = useValues();
const form = useMemo(() => {
console.log('Form.useMemo', initialValues);
return createForm({ initialValues, readPretty: schema['x-read-pretty'] });
return createForm({
initialValues,
readPretty: schema['x-read-pretty'],
});
}, []);
const path = useSchemaPath();
const scope = useContext(SchemaExpressionScopeContext);
@ -128,7 +140,7 @@ export const Form: any = observer((props: any) => {
<DisplayFieldsContextProvider>{content}</DisplayFieldsContextProvider>
</ResourceContextProvider>
) : (
content
<DisplayFieldsContextProvider>{content}</DisplayFieldsContextProvider>
);
});
@ -143,9 +155,9 @@ Form.Field = observer((props: any) => {
const { resource = {} } = useResourceContext();
useEffect(() => {
if (fieldName) {
addDisplayField && addDisplayField(fieldName);
addDisplayField && addDisplayField(fieldName, schema);
}
}, [fieldName]);
}, [fieldName, schema]);
if (!fieldName) {
return null;
}

View File

@ -62,7 +62,7 @@ import AddNew from '../add-new';
import { isGridRowOrCol } from '../grid';
import { options } from '../database-field/interfaces';
import { Resource } from '../../resource';
import { useDisplayFieldsContext } from '../form';
import { DisplayFieldsContextProvider, useDisplayFieldsContext } from '../form';
interface TableRowProps {
index: number;
@ -223,10 +223,39 @@ function useTableColumns(props?: any) {
return columns;
}
function SwitchField(props) {
const { field, onChange } = props;
const [checked, setChecked] = useState(props.checked);
useEffect(() => {
setChecked(props.checked);
}, [props.checked]);
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}
onClick={async () => {
setChecked((checked) => {
onChange(!checked);
return !checked;
});
}}
>
<span>{field.uiSchema.title}</span>
<Switch checked={checked} size={'small'} />
</div>
);
}
function AddColumn() {
const [visible, setVisible] = useState(false);
const { appendChild } = useDesignable();
const { appendChild, remove } = useDesignable();
const { resource = {}, refresh } = useResourceContext();
const { hasDisplayField, removeDisplayField, getDisplayField } =
useDisplayFieldsContext();
return (
<Dropdown
trigger={['click']}
@ -237,13 +266,11 @@ function AddColumn() {
<Menu.ItemGroup className={'display-fields'} title={'要展示的字段'}>
{resource?.fields?.map((field) => (
<Menu.Item style={{ minWidth: 150 }}>
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}
onClick={async () => {
<SwitchField
checked={hasDisplayField(field.name)}
field={field}
onChange={async (checked) => {
if (checked) {
const data = appendChild({
type: 'void',
'x-component': 'Table.Column',
@ -253,11 +280,15 @@ function AddColumn() {
'x-designable-bar': 'Table.Column.DesignableBar',
});
await createSchema(data);
} else {
const s: any = getDisplayField(field.name);
const p = getSchemaPath(s);
const removed = remove(p);
await removeSchema(removed);
removeDisplayField(field.name);
}
}}
>
<span>{field.uiSchema.title}</span>
<Switch size={'small'} />
</div>
/>
</Menu.Item>
))}
</Menu.ItemGroup>
@ -611,12 +642,16 @@ export const Table: any = observer((props: any) => {
// @ts-ignore
<ResourceContextProvider resourceName={resourceName}>
<TableContextProvider>
<DisplayFieldsContextProvider>
<TableContainer />
</DisplayFieldsContextProvider>
</TableContextProvider>
</ResourceContextProvider>
) : (
<TableContextProvider>
<DisplayFieldsContextProvider>
<TableContainer />
</DisplayFieldsContextProvider>
</TableContextProvider>
);
});
@ -710,8 +745,14 @@ Table.Cell = observer((props: any) => {
});
Table.Column = observer((props: any) => {
const resourceField = useContext(ResourceFieldContext) || {};
const resourceField = useContext(ResourceFieldContext);
const { schema, DesignableBar } = useDesignable();
const { addDisplayField } = useDisplayFieldsContext();
useEffect(() => {
if (resourceField?.name) {
addDisplayField(resourceField.name, schema);
}
}, [resourceField, schema]);
return (
<div className={'nb-table-column'}>
{schema.title || resourceField?.uiSchema?.title}
@ -725,6 +766,7 @@ Table.Column.DesignableBar = () => {
// const fieldSchema = useFieldSchema();
const { schema, remove, refresh, insertAfter } = useDesignable();
const [visible, setVisible] = useState(false);
const { removeDisplayField } = useDisplayFieldsContext();
return (
<div className={cls('designable-bar', { active: visible })}>
<span
@ -759,6 +801,8 @@ Table.Column.DesignableBar = () => {
<Menu.Item
onClick={async () => {
const s = remove();
const fieldName = schema['x-component-props']?.['fieldName'];
removeDisplayField(fieldName);
await removeSchema(s);
}}
>