feat(client): improve demo

This commit is contained in:
chenos 2022-02-08 19:51:30 +08:00
parent dd783f6554
commit 4baded4702
8 changed files with 390 additions and 34 deletions

View File

@ -0,0 +1,209 @@
import { ISchema, observer, Schema, useFieldSchema } from '@formily/react';
import { uid } from '@formily/shared';
import {
Form,
FormItem,
Grid,
Input,
Markdown,
SchemaComponent,
SchemaComponentProvider,
SchemaInitializer,
useDesignable
} from '@nocobase/client';
import { Switch } from 'antd';
import React from 'react';
const schema: ISchema = {
type: 'void',
name: 'grid1',
'x-decorator': 'Form',
'x-component': 'Grid',
'x-item-initializer': 'AddGridFormItem',
'x-uid': uid(),
properties: {
row1: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col11: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
name: {
type: 'string',
title: 'Name',
'x-decorator': 'FormItem',
'x-component': 'Input',
'x-collection-field': 'posts.name',
},
title: {
type: 'string',
title: 'Title',
'x-decorator': 'FormItem',
'x-component': 'Input',
'x-collection-field': 'posts.title',
},
},
},
col12: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
intro: {
type: 'string',
title: 'Intro',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
},
},
},
};
const useFormItemInitializerFields = () => {
return [
{
key: 'name',
title: 'Name',
component: InitializeFormItem,
schema: {
type: 'string',
title: 'Name',
'x-component': 'Input',
'x-decorator': 'FormItem',
'x-collection-field': 'posts.name',
},
},
{
key: 'title',
title: 'Title',
component: InitializeFormItem,
schema: {
type: 'string',
title: 'Title',
'x-component': 'Input',
'x-decorator': 'FormItem',
'x-collection-field': 'posts.title',
},
},
];
};
const gridRowColWrap = (schema: ISchema) => {
return {
type: 'void',
'x-component': 'Grid.Row',
properties: {
[uid()]: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
[schema.name || uid()]: schema,
},
},
},
};
};
const AddGridFormItem = observer((props: any) => {
return (
<SchemaInitializer.Button
wrap={gridRowColWrap}
insertPosition={'beforeEnd'}
items={[
{
title: 'Display fields',
children: useFormItemInitializerFields(),
},
{
type: 'divider',
},
{
title: 'Add text',
component: InitializeTextFormItem,
},
]}
>
Configure fields
</SchemaInitializer.Button>
);
});
const useCurrentFieldSchema = (path: string) => {
const fieldSchema = useFieldSchema();
const { remove } = useDesignable();
const findFieldSchema = (schema: Schema) => {
return schema.reduceProperties((buf, s) => {
if (s['x-collection-field'] === path) {
return s;
}
const child = findFieldSchema(s);
if (child) {
return child;
}
return buf;
});
};
const schema = findFieldSchema(fieldSchema);
return {
schema,
exists: !!schema,
remove() {
schema &&
remove(schema, {
removeEmptyParents: true,
});
},
};
};
const InitializeFormItem = (props) => {
const { title, schema, insert } = props;
const { exists, remove } = useCurrentFieldSchema(schema['x-collection-field']);
return (
<SchemaInitializer.Item
onClick={() => {
if (exists) {
return remove();
}
insert({
...schema,
});
}}
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
{title} <Switch size={'small'} checked={exists} />
</div>
</SchemaInitializer.Item>
);
};
const InitializeTextFormItem = (props) => {
const { title, insert } = props;
return (
<SchemaInitializer.Item
onClick={(info) => {
insert({
type: 'void',
'x-component': 'Markdown.Void',
'x-decorator': 'FormItem',
// 'x-editable': false,
});
}}
>
{title}
</SchemaInitializer.Item>
);
};
export default function App() {
return (
<SchemaComponentProvider components={{ AddGridFormItem, Markdown, Form, Grid, Input, FormItem }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
}

View File

@ -0,0 +1,149 @@
import { FormOutlined, TableOutlined } from '@ant-design/icons';
import { ISchema, observer } from '@formily/react';
import { uid } from '@formily/shared';
import {
CardItem,
Form,
Grid,
Markdown,
SchemaComponent,
SchemaComponentProvider,
SchemaInitializer,
VoidTable
} from '@nocobase/client';
import React from 'react';
const schema: ISchema = {
type: 'void',
name: 'grid1',
'x-component': 'Grid',
'x-item-initializer': 'AddGridBlockItem',
'x-uid': uid(),
properties: {
row1: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
},
},
};
const gridRowColWrap = (schema: ISchema) => {
return {
type: 'void',
'x-component': 'Grid.Row',
properties: {
[uid()]: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
[schema.name || uid()]: schema,
},
},
},
};
};
const AddGridBlockItem = observer((props: any) => {
return (
<SchemaInitializer.Button
wrap={gridRowColWrap}
insertPosition={'beforeEnd'}
items={[
{
title: 'Data blocks',
children: [
{
key: 'table',
title: 'Table',
component: TableBlockInitializerItem,
},
{
key: 'form',
title: 'Form',
component: FormBlockInitializerItem,
},
],
},
]}
>
Add block
</SchemaInitializer.Button>
);
});
const TableBlockInitializerItem = (props) => {
const { insert } = props;
return (
<SchemaInitializer.Item
icon={<TableOutlined />}
onClick={(info) => {
insert({
type: 'void',
'x-component': 'VoidTable',
'x-decorator': 'CardItem',
});
}}
items={[
{
type: 'itemGroup',
title: 'select a data source',
children: [
{
key: 'users',
title: 'Users',
},
{
key: 'posts',
title: 'Posts',
},
],
},
]}
>
Table
</SchemaInitializer.Item>
);
};
const FormBlockInitializerItem = (props) => {
const { insert } = props;
return (
<SchemaInitializer.Item
icon={<FormOutlined />}
onClick={(info) => {
insert({
type: 'void',
'x-component': 'Form',
'x-decorator': 'CardItem',
});
}}
items={[
{
type: 'itemGroup',
title: 'select a data source',
children: [
{
key: 'users',
title: 'Users',
},
{
key: 'posts',
title: 'Posts',
},
],
},
]}
>
Form
</SchemaInitializer.Item>
);
};
export default function App() {
return (
<SchemaComponentProvider components={{ AddGridBlockItem, Grid, CardItem, Markdown, Form, VoidTable }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
}

View File

@ -5,6 +5,10 @@ group:
path: /schema-components path: /schema-components
--- ---
# Grid <Badge>待定</Badge> # Grid
<code src="./demos/demo1.tsx" /> <code src="./demos/demo1.tsx" />
<code src="./demos/demo2.tsx" />
<code src="./demos/demo3.tsx" />

View File

@ -4,6 +4,7 @@ import { observer, RecursionField, Schema, useField, useFieldSchema } from '@for
import { uid } from '@formily/shared'; import { uid } from '@formily/shared';
import cls from 'classnames'; import cls from 'classnames';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useComponent } from '../..';
import { DndContext } from '../../common/dnd-context'; import { DndContext } from '../../common/dnd-context';
const ColDivider = (props) => { const ColDivider = (props) => {
@ -65,6 +66,7 @@ const RowDivider = (props) => {
export const Grid: any = observer((props) => { export const Grid: any = observer((props) => {
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const ItemInitializer = useComponent(fieldSchema['x-item-initializer']);
const addr = field.address.toString(); const addr = field.address.toString();
const wrapSchema = (schema: Schema) => { const wrapSchema = (schema: Schema) => {
const row = new Schema({ const row = new Schema({
@ -97,6 +99,7 @@ export const Grid: any = observer((props) => {
); );
})} })}
</DndContext> </DndContext>
<div>{ItemInitializer && <ItemInitializer />}</div>
</div> </div>
); );
}); });

View File

@ -13,7 +13,7 @@ const Hello = observer((props) => {
); );
}); });
const InitializerButton = observer((props: any) => { const AddBlockButton = observer((props: any) => {
return ( return (
<SchemaInitializer.Button <SchemaInitializer.Button
wrap={(schema) => schema} wrap={(schema) => schema}
@ -34,7 +34,7 @@ const InitializerButton = observer((props: any) => {
}, },
]} ]}
> >
Create block Add block
</SchemaInitializer.Button> </SchemaInitializer.Button>
); );
}); });
@ -94,7 +94,7 @@ const FormBlockInitializerItem = (props) => {
export default function App() { export default function App() {
return ( return (
<SchemaComponentProvider components={{ Hello, InitializerButton }}> <SchemaComponentProvider components={{ Hello, AddBlockButton }}>
<SchemaComponent <SchemaComponent
schema={{ schema={{
type: 'void', type: 'void',
@ -113,7 +113,7 @@ export default function App() {
}, },
initializer: { initializer: {
type: 'void', type: 'void',
'x-component': 'InitializerButton', 'x-component': 'AddBlockButton',
}, },
}, },
}} }}

View File

@ -10,7 +10,7 @@ import {
import { Switch } from 'antd'; import { Switch } from 'antd';
import React from 'react'; import React from 'react';
const ActionInitializerButton = observer((props: any) => { const AddActionButton = observer((props: any) => {
return ( return (
<SchemaInitializer.Button <SchemaInitializer.Button
insertPosition={'beforeEnd'} insertPosition={'beforeEnd'}
@ -22,7 +22,7 @@ const ActionInitializerButton = observer((props: any) => {
{ {
title: 'Create', title: 'Create',
key: 'create', key: 'create',
component: 'ActionInitializerItem', component: InitializeAction,
schema: { schema: {
title: 'Create', title: 'Create',
'x-action': 'posts:create', 'x-action': 'posts:create',
@ -36,7 +36,7 @@ const ActionInitializerButton = observer((props: any) => {
title: 'Update', title: 'Update',
'x-action': 'posts:update', 'x-action': 'posts:update',
}, },
component: 'ActionInitializerItem', component: InitializeAction,
}, },
], ],
}, },
@ -65,7 +65,7 @@ const useCurrentActionSchema = (action: string) => {
}; };
}; };
const ActionInitializerItem = (props) => { const InitializeAction = (props) => {
const { title, schema, insert } = props; const { title, schema, insert } = props;
const { exists, remove } = useCurrentActionSchema(schema['x-action']); const { exists, remove } = useCurrentActionSchema(schema['x-action']);
return ( return (
@ -90,13 +90,13 @@ const ActionInitializerItem = (props) => {
export default function App() { export default function App() {
return ( return (
<SchemaComponentProvider components={{ ActionBar, Action, ActionInitializerItem, ActionInitializerButton }}> <SchemaComponentProvider components={{ ActionBar, Action, AddActionButton }}>
<SchemaComponent <SchemaComponent
schema={{ schema={{
type: 'void', type: 'void',
name: 'page', name: 'page',
'x-component': 'ActionBar', 'x-component': 'ActionBar',
'x-action-initializer': 'ActionInitializerButton', 'x-action-initializer': 'AddActionButton',
properties: { properties: {
action1: { action1: {
type: 'void', type: 'void',
@ -104,13 +104,6 @@ export default function App() {
'x-action': 'posts:update', 'x-action': 'posts:update',
'x-component': 'Action', 'x-component': 'Action',
}, },
// action2: {
// type: 'void',
// title: 'Create',
// 'x-action': 'posts:create',
// 'x-align': 'left',
// 'x-component': 'Action',
// },
}, },
}} }}
/> />

View File

@ -16,7 +16,7 @@ const useFormItemInitializerFields = () => {
{ {
key: 'name', key: 'name',
title: 'Name', title: 'Name',
component: 'FormItemInitializer', component: InitializeFormItem,
schema: { schema: {
type: 'string', type: 'string',
title: 'Name', title: 'Name',
@ -28,7 +28,7 @@ const useFormItemInitializerFields = () => {
{ {
key: 'title', key: 'title',
title: 'Title', title: 'Title',
component: 'FormItemInitializer', component: InitializeFormItem,
schema: { schema: {
type: 'string', type: 'string',
title: 'Title', title: 'Title',
@ -40,7 +40,7 @@ const useFormItemInitializerFields = () => {
]; ];
}; };
const FormItemInitializerButton = observer((props: any) => { const AddFormItemButton = observer((props: any) => {
return ( return (
<SchemaInitializer.Button <SchemaInitializer.Button
wrap={(schema) => schema} wrap={(schema) => schema}
@ -55,7 +55,7 @@ const FormItemInitializerButton = observer((props: any) => {
}, },
{ {
title: 'Add text', title: 'Add text',
component: 'AddTextFormItemInitializer', component: InitializeTextFormItem,
}, },
]} ]}
> >
@ -89,7 +89,7 @@ const useCurrentFieldSchema = (path: string) => {
}; };
}; };
const FormItemInitializer = (props) => { const InitializeFormItem = (props) => {
const { title, schema, insert } = props; const { title, schema, insert } = props;
const { exists, remove } = useCurrentFieldSchema(schema['x-collection-field']); const { exists, remove } = useCurrentFieldSchema(schema['x-collection-field']);
return ( return (
@ -110,7 +110,7 @@ const FormItemInitializer = (props) => {
); );
}; };
const AddTextFormItemInitializer = (props) => { const InitializeTextFormItem = (props) => {
const { title, insert } = props; const { title, insert } = props;
return ( return (
<SchemaInitializer.Item <SchemaInitializer.Item
@ -132,16 +132,14 @@ const Page = (props) => {
return ( return (
<div> <div>
{props.children} {props.children}
<FormItemInitializerButton /> <AddFormItemButton />
</div> </div>
); );
}; };
export default function App() { export default function App() {
return ( return (
<SchemaComponentProvider <SchemaComponentProvider components={{ Page, Form, Input, FormItem, Markdown }}>
components={{ Page, Form, Input, FormItem, Markdown, FormItemInitializer, AddTextFormItemInitializer }}
>
<SchemaComponent <SchemaComponent
schema={{ schema={{
type: 'void', type: 'void',

View File

@ -21,7 +21,7 @@ const useTableColumnInitializerFields = () => {
'x-collection-field': 'posts.name', 'x-collection-field': 'posts.name',
'x-component': 'Input', 'x-component': 'Input',
}, },
component: ColumnInitializer, component: ColumnInitializerItem,
}, },
{ {
key: 'title', key: 'title',
@ -32,13 +32,13 @@ const useTableColumnInitializerFields = () => {
'x-collection-field': 'posts.title', 'x-collection-field': 'posts.title',
'x-component': 'Input', 'x-component': 'Input',
}, },
component: ColumnInitializer, component: ColumnInitializerItem,
}, },
]; ];
return fields; return fields;
}; };
export const InitializerButton = observer((props: any) => { export const AddTableColumn = observer((props: any) => {
return ( return (
<SchemaInitializer.Button <SchemaInitializer.Button
wrap={(schema) => schema} wrap={(schema) => schema}
@ -80,7 +80,7 @@ const useCurrentColumnSchema = (path: string) => {
}; };
}; };
export const ColumnInitializer = (props) => { export const ColumnInitializerItem = (props) => {
const { title, schema, insert } = props; const { title, schema, insert } = props;
const { exists, remove } = useCurrentColumnSchema(schema['x-collection-field']); const { exists, remove } = useCurrentColumnSchema(schema['x-collection-field']);
return ( return (
@ -120,7 +120,7 @@ const schema = {
{ id: 3, name: 'Name3' }, { id: 3, name: 'Name3' },
], ],
'x-component': 'ArrayTable', 'x-component': 'ArrayTable',
'x-column-initializer': 'InitializerButton', 'x-column-initializer': 'AddTableColumn',
'x-component-props': { 'x-component-props': {
rowKey: 'id', rowKey: 'id',
}, },
@ -145,7 +145,7 @@ const schema = {
export default function App() { export default function App() {
return ( return (
<SchemaComponentProvider components={{ InitializerButton, Input, ArrayTable }}> <SchemaComponentProvider components={{ AddTableColumn, Input, ArrayTable }}>
<SchemaComponent schema={schema} /> <SchemaComponent schema={schema} />
</SchemaComponentProvider> </SchemaComponentProvider>
); );