feat(client): x-designer

This commit is contained in:
chenos 2022-02-18 20:29:24 +08:00
parent 992befe89e
commit 2c38b63f18
18 changed files with 159 additions and 125 deletions

View File

@ -1,18 +1,12 @@
import React from 'react';
import { useDesignable } from '../..';
import { SortableItem } from '../../common';
import { useDesigner } from '../../hooks';
export const BlockItem: React.FC<any> = (props) => {
const { remove } = useDesignable();
const Designer = useDesigner();
return (
<SortableItem className={'nb-block-item'} style={{ position: 'relative' }}>
<a
onClick={() => {
remove();
}}
>
</a>
<Designer />
{props.children}
</SortableItem>
);

View File

@ -0,0 +1,19 @@
import React from 'react';
import { DragHandler } from '../../common';
import { useDesignable } from '../../hooks';
export const TestDesigner = () => {
const { remove } = useDesignable();
return (
<div>
<a
onClick={() => {
remove();
}}
>
</a>
<DragHandler/>
</div>
);
};

View File

@ -1,2 +1,3 @@
export * from './BlockItem';
export * from './TestDesigner';

View File

@ -2,6 +2,7 @@ export * from './useAttach';
export * from './useCompile';
export * from './useComponent';
export * from './useDesignable';
export * from './useDesigner';
export * from './useFieldProps';
export * from './useSchemaComponentContext';

View File

@ -93,6 +93,18 @@ export class Designable {
});
}
});
this.on('patch', async ({ schema }) => {
refresh();
if (schema?.['x-uid']) {
await api.request({
url: `/uiSchemas:patch`,
method: 'post',
data: {
...schema,
},
});
}
});
this.on('remove', async ({ removed }) => {
refresh();
if (removed?.['x-uid']) {
@ -121,14 +133,14 @@ export class Designable {
generateUid(schema);
}
on(name: 'insertAdjacent' | 'remove' | 'error', listener: any) {
on(name: 'insertAdjacent' | 'remove' | 'error' | 'patch', listener: any) {
if (!this.events[name]) {
this.events[name] = [];
}
this.events[name].push(listener);
}
emit(name: 'insertAdjacent' | 'remove' | 'error', ...args) {
emit(name: 'insertAdjacent' | 'remove' | 'error' | 'patch', ...args) {
if (!this.events[name]) {
return;
}
@ -435,6 +447,7 @@ export function useDesignable() {
const dn = createDesignable({ api, refresh, current: fieldSchema });
dn.loadAPIClientEvents();
return {
dn,
designable,
reset,
refresh,

View File

@ -0,0 +1,9 @@
import { useFieldSchema } from '@formily/react';
import { useComponent } from '.';
const Def = () => null;
export const useDesigner = () => {
const fieldSchema = useFieldSchema();
return useComponent(fieldSchema['x-designer'], Def);
};

View File

@ -18,6 +18,7 @@ const createSchema = (collectionName) => {
params: {},
},
},
'x-designer': 'TestDesigner',
'x-component': 'CardItem',
properties: {
form: {
@ -33,8 +34,14 @@ const createSchema = (collectionName) => {
},
actions: {
type: 'void',
'x-component': 'ActionBar',
'x-action-initializer': 'FormActionInitializer',
'x-component': 'ActionBar',
'x-component-props': {
layout: 'one-column',
style: {
marginTop: 24,
},
},
properties: {},
},
},

View File

@ -0,0 +1,29 @@
import { FormOutlined } from '@ant-design/icons';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaInitializer } from '../..';
const itemWrap = SchemaInitializer.itemWrap;
export const MarkdownBlock = itemWrap((props) => {
const { insert } = props;
const { t } = useTranslation();
return (
<SchemaInitializer.Item
{...props}
icon={<FormOutlined />}
onClick={() => {
insert({
type: 'void',
'x-designer': 'Markdown.Void.Designer',
'x-decorator': 'CardItem',
'x-component': 'Markdown.Void',
'x-editable': false,
'x-component-props': {
content: '# Markdown content',
},
});
}}
/>
);
});

View File

@ -16,7 +16,6 @@ const createSchema = (collectionName) => {
resource: collectionName,
action: 'list',
params: {
perPage: 20,
pageSize: 20,
filter: {},
// sort: ['sort'],
@ -24,15 +23,21 @@ const createSchema = (collectionName) => {
},
},
},
'x-designer': 'TestDesigner',
'x-component': 'CardItem',
properties: {
actions: {
type: 'void',
'x-component': 'ActionBar',
'x-action-initializer': 'TableActionInitializer',
'x-component': 'ActionBar',
'x-component-props': {
style: {
marginBottom: 16,
},
},
properties: {},
},
table1: {
table: {
type: 'void',
'x-component': 'VoidTable',
'x-component-props': {
@ -47,9 +52,10 @@ const createSchema = (collectionName) => {
actions: {
type: 'void',
title: 'Actions',
'x-designer': 'TestDesigner',
'x-decorator': 'TableColumnActionBar',
'x-component': 'VoidTable.Column',
'x-action-initializer': 'TableColumnActionInitializer',
'x-action-initializer': 'TableRecordActionInitializer',
properties: {
actions: {
type: 'void',

View File

@ -4,6 +4,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaInitializer } from '../..';
import { FormBlock } from './FormBlock';
import { MarkdownBlock } from './MarkdownBlock';
import { TableBlock } from './TableBlock';
const gridRowColWrap = (schema: ISchema) => {
@ -45,6 +46,17 @@ export const BlockInitializer = observer((props: any) => {
},
],
},
{
type: 'itemGroup',
title: t('Media'),
children: [
{
type: 'item',
title: t('Markdown'),
component: MarkdownBlock,
},
],
},
]}
>
{t('Add block')}

View File

@ -33,6 +33,7 @@ const InitializeAction = SchemaInitializer.itemWrap((props) => {
}
insert({
type: 'void',
'x-designer': 'TestDesigner',
'x-component': 'Action',
...item.schema,
});

View File

@ -34,6 +34,7 @@ const InitializeAction = SchemaInitializer.itemWrap((props) => {
}
insert({
type: 'void',
'x-designer': 'TestDesigner',
'x-component': 'Action',
...item.schema,
});
@ -52,7 +53,6 @@ export const FormActionInitializer = observer((props: any) => {
return (
<SchemaInitializer.Button
insertPosition={'beforeEnd'}
style={{ marginLeft: 8 }}
items={[
{
type: 'itemGroup',

View File

@ -2,11 +2,12 @@ import { ISchema, observer, Schema, useFieldSchema } from '@formily/react';
import { uid } from '@formily/shared';
import { Switch } from 'antd';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaInitializer, SchemaInitializerItemOptions } from '../..';
import { useCollection } from '../../../collection-manager';
import { useDesignable } from '../../../schema-component';
const useFormItemInitializerFields = () => {
const useFormItems = () => {
const { name, fields } = useCollection();
return fields?.map((field) => {
return {
@ -15,6 +16,7 @@ const useFormItemInitializerFields = () => {
component: InitializeFormItem,
schema: {
name: field.name,
'x-designer': 'TestDesigner',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
'x-collection-field': `${name}.${field.name}`,
@ -100,9 +102,13 @@ const InitializeTextFormItem = itemWrap((props) => {
onClick={() => {
insert({
type: 'void',
'x-component': 'Markdown.Void',
'x-editable': false,
'x-decorator': 'FormItem',
// 'x-editable': false,
'x-designer': 'Markdown.Void.Designer',
'x-component': 'Markdown.Void',
'x-component-props': {
content: '# Markdown content',
},
});
}}
/>
@ -110,6 +116,7 @@ const InitializeTextFormItem = itemWrap((props) => {
});
export const FormItemInitializer = observer((props: any) => {
const { t } = useTranslation();
return (
<SchemaInitializer.Button
wrap={gridRowColWrap}
@ -117,20 +124,20 @@ export const FormItemInitializer = observer((props: any) => {
items={[
{
type: 'itemGroup',
title: 'Display fields',
children: useFormItemInitializerFields(),
title: t('Display fields'),
children: useFormItems(),
},
{
type: 'divider',
},
{
type: 'item',
title: 'Add text',
title: t('Add text'),
component: InitializeTextFormItem,
},
]}
>
Configure fields
{t('Configure fields')}
</SchemaInitializer.Button>
);
});

View File

@ -22,93 +22,15 @@ const gridRowColWrap = (schema: ISchema) => {
const itemWrap = SchemaInitializer.itemWrap;
const TestInitializerItem = itemWrap((props) => {
const FormBlock = itemWrap((props) => {
const { insert } = props;
return (
<SchemaInitializer.Item
icon={<FormOutlined />}
onClick={() => {
insert({
type: 'void',
name: uid(),
'x-decorator': 'CardItem',
'x-component': 'Grid',
'x-uid': uid(),
properties: {
row1: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col11: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block1: {
type: 'void',
title: '1',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
block2: {
type: 'void',
title: '2',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
col12: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block3: {
type: 'void',
title: '3',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
},
},
row2: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col21: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block4: {
type: 'void',
title: '4',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
col22: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block5: {
type: 'void',
title: '5',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
},
},
},
});
insert({});
}}
>
Test
</SchemaInitializer.Item>
/>
);
});
@ -125,12 +47,12 @@ export const RecordBlockInitializer = observer((props: any) => {
{
type: 'item',
title: 'Form',
component: TestInitializerItem,
component: FormBlock,
},
{
type: 'item',
title: 'Details',
component: TestInitializerItem,
component: FormBlock,
},
],
},

View File

@ -34,6 +34,7 @@ const InitializeAction = SchemaInitializer.itemWrap((props) => {
}
insert({
type: 'void',
'x-designer': 'TestDesigner',
'x-component': 'Action',
...item.schema,
});
@ -79,12 +80,14 @@ export const TableActionInitializer = observer((props: any) => {
'x-component': 'Action',
'x-component-props': {
type: 'primary',
openMode: 'drawer',
},
properties: {
drawer: {
type: 'void',
title: '{{ t("Add new record") }}',
'x-component': 'Action.Drawer',
'x-component': 'Action.Container',
'x-component-props': {},
'x-decorator': 'Form',
properties: {
grid: {
@ -95,7 +98,7 @@ export const TableActionInitializer = observer((props: any) => {
},
footer: {
type: 'void',
'x-component': 'Action.Drawer.Footer',
'x-component': 'Action.Container.Footer',
properties: {
action1: {
title: '{{ t("Cancel") }}',
@ -126,6 +129,9 @@ export const TableActionInitializer = observer((props: any) => {
schema: {
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component-props': {
useAction: '{{ useBulkDestroyAction }}',
},
},
},
],

View File

@ -7,20 +7,23 @@ import { useCollection, useDesignable } from '../../..';
const useTableColumnInitializerFields = () => {
const { name, fields } = useCollection();
return fields
// .filter((field) => field?.uiSchema?.title)
.map((field) => {
return {
type: 'item',
title: field?.uiSchema?.title || field.name,
schema: {
name: field.name,
'x-collection-field': `${name}.${field.name}`,
'x-component': 'CollectionField',
},
component: ColumnInitializerItem,
} as SchemaInitializerItemOptions;
});
return (
fields
// .filter((field) => field?.uiSchema?.title)
.map((field) => {
return {
type: 'item',
title: field?.uiSchema?.title || field.name,
schema: {
name: field.name,
'x-designer': 'TestDesigner',
'x-collection-field': `${name}.${field.name}`,
'x-component': 'CollectionField',
},
component: ColumnInitializerItem,
} as SchemaInitializerItemOptions;
})
);
};
const useCurrentColumnSchema = (path: string) => {

View File

@ -67,6 +67,7 @@ const InitializeAction = SchemaInitializer.itemWrap((props) => {
}
insert({
type: 'void',
'x-designer': 'TestDesigner',
'x-component': 'Action.Link',
...item.schema,
});
@ -79,7 +80,7 @@ const InitializeAction = SchemaInitializer.itemWrap((props) => {
);
});
export const TableColumnActionInitializer = observer((props: any) => {
export const TableRecordActionInitializer = observer((props: any) => {
const fieldSchema = useFieldSchema();
const api = useAPIClient();
const { refresh } = useDesignable();
@ -181,6 +182,9 @@ export const TableColumnActionInitializer = observer((props: any) => {
schema: {
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component-props': {
useAction: '{{ useDestroyAction }}',
},
},
},
],

View File

@ -4,6 +4,6 @@ export * from './FormActionInitializer';
export * from './FormItemInitializer';
export * from './RecordBlockInitializer';
export * from './TableActionInitializer';
export * from './TableColumnActionInitializer';
export * from './TableColumnInitializer';
export * from './TableRecordActionInitializer';