refactor(client): schema initializer
This commit is contained in:
parent
d486768eda
commit
f45b08af38
@ -10,6 +10,7 @@ import {
|
|||||||
DesignableSwitch,
|
DesignableSwitch,
|
||||||
DocumentTitleProvider,
|
DocumentTitleProvider,
|
||||||
i18n,
|
i18n,
|
||||||
|
MenuItemInitializers,
|
||||||
PluginManagerProvider,
|
PluginManagerProvider,
|
||||||
RemoteCollectionManagerProvider,
|
RemoteCollectionManagerProvider,
|
||||||
RouteSchemaComponent,
|
RouteSchemaComponent,
|
||||||
@ -50,7 +51,7 @@ const providers = [
|
|||||||
],
|
],
|
||||||
[SchemaComponentProvider, { components: { Link, NavLink } }],
|
[SchemaComponentProvider, { components: { Link, NavLink } }],
|
||||||
RemoteCollectionManagerProvider,
|
RemoteCollectionManagerProvider,
|
||||||
SchemaInitializerProvider,
|
[SchemaInitializerProvider, { initializers: { MenuItemInitializers } }],
|
||||||
AntdSchemaComponentProvider,
|
AntdSchemaComponentProvider,
|
||||||
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
|
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
|
||||||
[
|
[
|
||||||
|
@ -125,7 +125,7 @@ export default (apiClient: APIClient) => {
|
|||||||
type: 'void',
|
type: 'void',
|
||||||
name: 'grid1',
|
name: 'grid1',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-item-initializer': 'Grid.AddBlockItem',
|
'x-initializer': 'Grid.AddBlockItem',
|
||||||
'x-uid': uid(),
|
'x-uid': uid(),
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
@ -152,7 +152,7 @@ export default (apiClient: APIClient) => {
|
|||||||
type: 'void',
|
type: 'void',
|
||||||
name: 'grid1',
|
name: 'grid1',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-item-initializer': 'Grid.AddBlockItem',
|
'x-initializer': 'Grid.AddBlockItem',
|
||||||
'x-uid': uid(),
|
'x-uid': uid(),
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { observer, RecursionField, useFieldSchema } from '@formily/react';
|
import { observer, RecursionField, useFieldSchema } from '@formily/react';
|
||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useSchemaInitializer } from '../../../schema-initializer';
|
||||||
import { DndContext } from '../../common';
|
import { DndContext } from '../../common';
|
||||||
import { useComponent } from '../../hooks';
|
|
||||||
|
|
||||||
export const ActionBar = observer((props: any) => {
|
export const ActionBar = observer((props: any) => {
|
||||||
const { layout = 'tow-columns', style, ...others } = props;
|
const { layout = 'tow-columns', style, ...others } = props;
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const ActionInitializer = useComponent(fieldSchema['x-action-initializer']);
|
const { render } = useSchemaInitializer(fieldSchema['x-initializer']);
|
||||||
if (layout === 'one-column') {
|
if (layout === 'one-column') {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', ...style }} {...others}>
|
<div style={{ display: 'flex', ...style }} {...others}>
|
||||||
{props.children && <div style={{ marginRight: 8 }}>{props.children}</div>}
|
{props.children && <div style={{ marginRight: 8 }}>{props.children}</div>}
|
||||||
{ActionInitializer && <ActionInitializer />}
|
{render()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ export const ActionBar = observer((props: any) => {
|
|||||||
</Space>
|
</Space>
|
||||||
</DndContext>
|
</DndContext>
|
||||||
</div>
|
</div>
|
||||||
{ActionInitializer && <ActionInitializer />}
|
{render()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -5,8 +5,7 @@ import { Table, TableColumnProps } from 'antd';
|
|||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DndContext } from '../..';
|
import { DndContext } from '../..';
|
||||||
import { RecordProvider } from '../../../';
|
import { RecordProvider, useSchemaInitializer } from '../../../';
|
||||||
import { useComponent } from '../../hooks';
|
|
||||||
|
|
||||||
const isColumnComponent = (schema: Schema) => {
|
const isColumnComponent = (schema: Schema) => {
|
||||||
return schema['x-component']?.endsWith('.Column') > -1;
|
return schema['x-component']?.endsWith('.Column') > -1;
|
||||||
@ -15,7 +14,7 @@ const isColumnComponent = (schema: Schema) => {
|
|||||||
const useTableColumns = () => {
|
const useTableColumns = () => {
|
||||||
const field = useField<ArrayField>();
|
const field = useField<ArrayField>();
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const Initializer = useComponent(schema['x-column-initializer']);
|
const { exists, render } = useSchemaInitializer(schema['x-initializer']);
|
||||||
const columns = schema
|
const columns = schema
|
||||||
.reduceProperties((buf, s) => {
|
.reduceProperties((buf, s) => {
|
||||||
if (isColumnComponent(s)) {
|
if (isColumnComponent(s)) {
|
||||||
@ -38,11 +37,11 @@ const useTableColumns = () => {
|
|||||||
} as TableColumnProps<any>;
|
} as TableColumnProps<any>;
|
||||||
});
|
});
|
||||||
console.log(columns);
|
console.log(columns);
|
||||||
if (!Initializer) {
|
if (!exists) {
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
return columns.concat({
|
return columns.concat({
|
||||||
title: <Initializer />,
|
title: render(),
|
||||||
dataIndex: 'TABLE_COLUMN_INITIALIZER',
|
dataIndex: 'TABLE_COLUMN_INITIALIZER',
|
||||||
key: 'TABLE_COLUMN_INITIALIZER',
|
key: 'TABLE_COLUMN_INITIALIZER',
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,7 @@ export const useColumnSchema = () => {
|
|||||||
return buf;
|
return buf;
|
||||||
}, null);
|
}, null);
|
||||||
if (!fieldSchema) {
|
if (!fieldSchema) {
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
const collectionField = getField(fieldSchema.name);
|
const collectionField = getField(fieldSchema.name);
|
||||||
return { columnSchema, fieldSchema, collectionField };
|
return { columnSchema, fieldSchema, collectionField };
|
||||||
@ -21,7 +21,7 @@ export const useColumnSchema = () => {
|
|||||||
export const TableColumnDecorator = (props) => {
|
export const TableColumnDecorator = (props) => {
|
||||||
const Designer = useDesigner();
|
const Designer = useDesigner();
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const { columnSchema, fieldSchema, collectionField } = useColumnSchema();
|
const { fieldSchema, collectionField } = useColumnSchema();
|
||||||
const { refresh } = useDesignable();
|
const { refresh } = useDesignable();
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (field.title) {
|
if (field.title) {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { DragOutlined } from '@ant-design/icons';
|
import { DragOutlined } from '@ant-design/icons';
|
||||||
import { useFieldSchema } from '@formily/react';
|
import { useFieldSchema } from '@formily/react';
|
||||||
|
import { useSchemaInitializer } from '@nocobase/client';
|
||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DragHandler, useComponent } from '../../../schema-component';
|
import { DragHandler } from '../../../schema-component';
|
||||||
|
|
||||||
export const TableRecordActionDesigner = (props: any) => {
|
export const TableRecordActionDesigner = (props: any) => {
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const ActionInitializer = useComponent(fieldSchema['x-action-initializer']);
|
const { render } = useSchemaInitializer(fieldSchema['x-initializer']);
|
||||||
|
console.log("fieldSchema['x-initializer']", fieldSchema['x-initializer'])
|
||||||
return (
|
return (
|
||||||
<div className={'general-schema-designer'}>
|
<div className={'general-schema-designer'}>
|
||||||
<div className={'general-schema-designer-icons'}>
|
<div className={'general-schema-designer-icons'}>
|
||||||
@ -14,7 +16,7 @@ export const TableRecordActionDesigner = (props: any) => {
|
|||||||
<DragHandler>
|
<DragHandler>
|
||||||
<DragOutlined />
|
<DragOutlined />
|
||||||
</DragHandler>
|
</DragHandler>
|
||||||
<ActionInitializer />
|
{render()}
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +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, { createContext, useContext, useState } from 'react';
|
import React, { createContext, useContext, useState } from 'react';
|
||||||
import { useComponent } from '../..';
|
import { useSchemaInitializer } from '../../../';
|
||||||
import { DndContext } from '../../common/dnd-context';
|
import { DndContext } from '../../common/dnd-context';
|
||||||
|
|
||||||
const GridRowContext = createContext(null);
|
const GridRowContext = createContext(null);
|
||||||
@ -123,7 +123,7 @@ const useColProperties = () => {
|
|||||||
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 { render } = useSchemaInitializer(fieldSchema['x-initializer']);
|
||||||
const addr = field.address.toString();
|
const addr = field.address.toString();
|
||||||
const rows = useRowProperties();
|
const rows = useRowProperties();
|
||||||
return (
|
return (
|
||||||
@ -145,7 +145,7 @@ export const Grid: any = observer((props) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</DndContext>
|
</DndContext>
|
||||||
<div>{ItemInitializer && <ItemInitializer />}</div>
|
<div>{render()}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -10,8 +10,8 @@ import {
|
|||||||
import { Menu as AntdMenu } from 'antd';
|
import { Menu as AntdMenu } from 'antd';
|
||||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { createDesignable, DndContext, SortableItem, useComponent, useDesignable, useDesigner } from '../..';
|
import { createDesignable, DndContext, SortableItem, useDesignable, useDesigner } from '../..';
|
||||||
import { Icon, useAPIClient } from '../../../';
|
import { Icon, useAPIClient, useSchemaInitializer } from '../../../';
|
||||||
import { MenuDesigner } from './Menu.Designer';
|
import { MenuDesigner } from './Menu.Designer';
|
||||||
import { findKeysByUid, findMenuItem } from './util';
|
import { findKeysByUid, findMenuItem } from './util';
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ export const Menu: ComposedMenu = observer((props) => {
|
|||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const { refresh } = useDesignable();
|
const { refresh } = useDesignable();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const Initializer = useComponent(schema['x-initializer']);
|
const { render } = useSchemaInitializer(schema['x-initializer']);
|
||||||
const sideMenuRef = useSideMenuRef();
|
const sideMenuRef = useSideMenuRef();
|
||||||
const [defaultSelectedKeys, setDefaultSelectedKeys] = useState(() => {
|
const [defaultSelectedKeys, setDefaultSelectedKeys] = useState(() => {
|
||||||
if (dSelectedKeys) {
|
if (dSelectedKeys) {
|
||||||
@ -241,7 +241,7 @@ export const Menu: ComposedMenu = observer((props) => {
|
|||||||
defaultSelectedKeys={defaultSelectedKeys}
|
defaultSelectedKeys={defaultSelectedKeys}
|
||||||
>
|
>
|
||||||
<RecursionField schema={schema} onlyRenderProperties />
|
<RecursionField schema={schema} onlyRenderProperties />
|
||||||
{Initializer && <Initializer style={{ background: 'none', marginTop: 7, marginLeft: 8 }} />}
|
{render({ style: { background: 'none', marginTop: 7, marginLeft: 8 } })}
|
||||||
</AntdMenu>
|
</AntdMenu>
|
||||||
{loading
|
{loading
|
||||||
? null
|
? null
|
||||||
@ -285,21 +285,19 @@ export const Menu: ComposedMenu = observer((props) => {
|
|||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<RecursionField schema={sideMenuSchema} onlyRenderProperties />
|
<RecursionField schema={sideMenuSchema} onlyRenderProperties />
|
||||||
{Initializer && (
|
{render({
|
||||||
<Initializer
|
style: { margin: 8 },
|
||||||
style={{ margin: 8 }}
|
insert: (s) => {
|
||||||
insert={(s) => {
|
console.log('createDesignable', s);
|
||||||
console.log('createDesignable', s);
|
const dn = createDesignable({
|
||||||
const dn = createDesignable({
|
api,
|
||||||
api,
|
refresh,
|
||||||
refresh,
|
current: sideMenuSchema,
|
||||||
current: sideMenuSchema,
|
});
|
||||||
});
|
dn.loadAPIClientEvents();
|
||||||
dn.loadAPIClientEvents();
|
dn.insertAdjacent('beforeEnd', s);
|
||||||
dn.insertAdjacent('beforeEnd', s);
|
},
|
||||||
}}
|
})}
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</AntdMenu>
|
</AntdMenu>
|
||||||
</MenuModeContext.Provider>,
|
</MenuModeContext.Provider>,
|
||||||
sideMenuRef.current.firstChild,
|
sideMenuRef.current.firstChild,
|
||||||
@ -331,9 +329,15 @@ Menu.URL = observer((props) => {
|
|||||||
const field = useField();
|
const field = useField();
|
||||||
const Designer = useContext(MenuItemDesignerContext);
|
const Designer = useContext(MenuItemDesignerContext);
|
||||||
return (
|
return (
|
||||||
<AntdMenu.Item {...others} key={schema.name} eventKey={schema.name} schema={schema} onClick={() => {
|
<AntdMenu.Item
|
||||||
window.open(props.href, '_blank');
|
{...others}
|
||||||
}}>
|
key={schema.name}
|
||||||
|
eventKey={schema.name}
|
||||||
|
schema={schema}
|
||||||
|
onClick={() => {
|
||||||
|
window.open(props.href, '_blank');
|
||||||
|
}}
|
||||||
|
>
|
||||||
<SortableItem className={designerCss}>
|
<SortableItem className={designerCss}>
|
||||||
<Icon style={{ marginRight: 5 }} type={icon} />
|
<Icon style={{ marginRight: 5 }} type={icon} />
|
||||||
{schema.title}
|
{schema.title}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { FormDialog, FormLayout } from '@formily/antd';
|
import { FormDialog, FormLayout } from '@formily/antd';
|
||||||
import { observer, SchemaOptionsContext } from '@formily/react';
|
import { SchemaOptionsContext } from '@formily/react';
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SchemaComponent, SchemaComponentOptions } from '../../..';
|
import { SchemaComponent, SchemaComponentOptions } from '../../..';
|
||||||
import { SchemaInitializer } from '../../../../schema-initializer';
|
import { SchemaInitializer } from '../../../../schema-initializer';
|
||||||
|
|
||||||
export const MenuItemInitializer = observer((props: any) => {
|
export const MenuItemInitializers = (props: any) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<SchemaInitializer.Button
|
<SchemaInitializer.Button
|
||||||
@ -34,7 +34,7 @@ export const MenuItemInitializer = observer((props: any) => {
|
|||||||
{t('Add menu item')}
|
{t('Add menu item')}
|
||||||
</SchemaInitializer.Button>
|
</SchemaInitializer.Button>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
const itemWrap = SchemaInitializer.itemWrap;
|
const itemWrap = SchemaInitializer.itemWrap;
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ export const PageMenuItem = itemWrap((props) => {
|
|||||||
grid: {
|
grid: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-item-initializer': 'BlockInitializer',
|
'x-initializer': 'BlockInitializers',
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
@ -1,4 +1,4 @@
|
|||||||
export * from './Menu';
|
export * from './Menu';
|
||||||
export * from './MenuItemInitializer';
|
export * from './MenuItemInitializers';
|
||||||
export * from './util';
|
export * from './util';
|
||||||
|
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
import { ISchema, observer } from '@formily/react';
|
|
||||||
import { uid } from '@formily/shared';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { CalendarBlock } from './CalendarBlock';
|
|
||||||
import { FormBlock } from './FormBlock';
|
|
||||||
import { MarkdownBlock } from './MarkdownBlock';
|
|
||||||
import { TableBlock } from './TableBlock';
|
|
||||||
|
|
||||||
const gridRowColWrap = (schema: ISchema) => {
|
|
||||||
return {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid.Row',
|
|
||||||
properties: {
|
|
||||||
[uid()]: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid.Col',
|
|
||||||
properties: {
|
|
||||||
[schema.name || uid()]: schema,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const BlockInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
wrap={gridRowColWrap}
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Data blocks'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Table'),
|
|
||||||
component: TableBlock,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Form'),
|
|
||||||
component: FormBlock,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Calendar'),
|
|
||||||
component: CalendarBlock,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Media'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Markdown'),
|
|
||||||
component: MarkdownBlock,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Add block')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,41 @@
|
|||||||
|
import { gridRowColWrap } from './utils';
|
||||||
|
|
||||||
|
// 页面里添加区块
|
||||||
|
export const BlockInitializers = {
|
||||||
|
title: '{{t("Add block")}}',
|
||||||
|
wrap: gridRowColWrap,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Data blocks',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Table',
|
||||||
|
component: 'TableBlockInitializer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Form',
|
||||||
|
component: 'FormBlockInitializer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Calendar',
|
||||||
|
component: 'CalendarBlockInitializer',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Media',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Markdown',
|
||||||
|
component: 'MarkdownBlockInitializer',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -1,187 +0,0 @@
|
|||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { useDesignable } from '../../../schema-component';
|
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-component': 'Action',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title}
|
|
||||||
<Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const CalendarActionInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
style={{ marginLeft: 8 }}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Enable actions'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Today'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: t('Today'),
|
|
||||||
'x-component': 'Calendar.Today',
|
|
||||||
'x-action': `calendar:today`,
|
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Turn page'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: t('Turn page'),
|
|
||||||
'x-component': 'Calendar.Nav',
|
|
||||||
'x-action': `calendar:nav`,
|
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Title'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: t('Title'),
|
|
||||||
'x-component': 'Calendar.Title',
|
|
||||||
'x-action': `calendar:title`,
|
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Select view'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: t('Select view'),
|
|
||||||
'x-component': 'Calendar.ViewSelect',
|
|
||||||
'x-action': `calendar:viewSelect`,
|
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Filter'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Filter") }}',
|
|
||||||
'x-action': 'filter',
|
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Add new'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{ t("Add new") }}',
|
|
||||||
'x-action': 'create',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
|
||||||
type: 'primary',
|
|
||||||
openMode: 'drawer',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
drawer: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{ t("Add new record") }}',
|
|
||||||
'x-component': 'Action.Container',
|
|
||||||
'x-component-props': {},
|
|
||||||
'x-decorator': 'Form',
|
|
||||||
properties: {
|
|
||||||
grid: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid',
|
|
||||||
'x-item-initializer': 'FormItemInitializer',
|
|
||||||
properties: {},
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Action.Container.Footer',
|
|
||||||
properties: {
|
|
||||||
actions: {
|
|
||||||
type: 'void',
|
|
||||||
'x-action-initializer': 'PopupFormActionInitializer',
|
|
||||||
'x-decorator': 'DndContext',
|
|
||||||
'x-component': 'ActionBar',
|
|
||||||
'x-component-props': {
|
|
||||||
layout: 'one-column',
|
|
||||||
},
|
|
||||||
properties: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Delete'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Delete") }}',
|
|
||||||
'x-action': 'destroy',
|
|
||||||
'x-component-props': {
|
|
||||||
confirm: {
|
|
||||||
title: "{{t('Delete record')}}",
|
|
||||||
content: "{{t('Are you sure you want to delete it?')}}",
|
|
||||||
},
|
|
||||||
useAction: '{{ cm.useBulkDestroyAction }}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Configure actions')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,75 @@
|
|||||||
|
// 日历的操作配置
|
||||||
|
export const CalendarActionInitializers = {
|
||||||
|
title: 'Configure actions',
|
||||||
|
style: { marginLeft: 8 },
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Enable actions',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Today',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: 'Today',
|
||||||
|
'x-component': 'Calendar.Today',
|
||||||
|
'x-action': `calendar:today`,
|
||||||
|
'x-align': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Turn pages',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: 'Turn page',
|
||||||
|
'x-component': 'Calendar.Nav',
|
||||||
|
'x-action': `calendar:nav`,
|
||||||
|
'x-align': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Title',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: 'Title',
|
||||||
|
'x-component': 'Calendar.Title',
|
||||||
|
'x-action': `calendar:title`,
|
||||||
|
'x-align': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Select view',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: 'Select view',
|
||||||
|
'x-component': 'Calendar.ViewSelect',
|
||||||
|
'x-action': `calendar:viewSelect`,
|
||||||
|
'x-align': 'right',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Filter',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Filter") }}',
|
||||||
|
'x-action': 'filter',
|
||||||
|
'x-align': 'right',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: '{{ t("Add new") }}',
|
||||||
|
component: 'AddNewActionInitializer',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -1,84 +0,0 @@
|
|||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { useDesignable } from '../../../schema-component';
|
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'TestDesigner',
|
|
||||||
'x-component': 'Action',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const DetailsActionInitializer = observer((props: any) => {
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
style={{ marginLeft: 8 }}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: 'Enable actions',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: 'Edit',
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: 'Edit',
|
|
||||||
'x-action': 'update',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: 'Delete',
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: 'Delete',
|
|
||||||
'x-action': 'delete',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Configure actions
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,30 @@
|
|||||||
|
// 详情的操作配置
|
||||||
|
export const DetailsActionInitializers = {
|
||||||
|
title: 'Configure actions',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Enable actions',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Edit',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: 'Edit',
|
||||||
|
'x-action': 'update',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Delete',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: 'Delete',
|
||||||
|
'x-action': 'delete',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -1,83 +0,0 @@
|
|||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { useDesignable } from '../../../schema-component';
|
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-component': 'Action',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title}
|
|
||||||
<Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const FormActionInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Enable actions'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Submit'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Submit") }}',
|
|
||||||
'x-action': 'submit',
|
|
||||||
'x-align': 'left',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
|
||||||
type: 'primary',
|
|
||||||
useAction: '{{ cm.useCreateActionWithoutRefresh }}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Configure actions')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,27 @@
|
|||||||
|
// 普通表单的操作配置
|
||||||
|
export const FormActionInitializers = {
|
||||||
|
title: 'Configure actions',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Enable actions',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: '{{ t("Submit") }}',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Submit") }}',
|
||||||
|
'x-action': 'submit',
|
||||||
|
'x-align': 'left',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ cm.useCreateActionWithoutRefresh }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -1,145 +0,0 @@
|
|||||||
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 { name, fields } = useCollection();
|
|
||||||
return fields?.map((field) => {
|
|
||||||
return {
|
|
||||||
type: 'item',
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
component: FormItem,
|
|
||||||
schema: {
|
|
||||||
name: field.name,
|
|
||||||
'x-designer': 'FormItem.Designer',
|
|
||||||
'x-component': 'CollectionField',
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-collection-field': `${name}.${field.name}`,
|
|
||||||
},
|
|
||||||
} as SchemaInitializerItemOptions;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
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 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, {
|
|
||||||
removeParentsIfNoChildren: true,
|
|
||||||
breakRemoveOn: (s) => {
|
|
||||||
return s['x-component'] === 'Grid';
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const itemWrap = SchemaInitializer.itemWrap;
|
|
||||||
|
|
||||||
const FormItem = itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { schema, exists, remove } = useCurrentFieldSchema(item.schema['x-collection-field']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const TextItem = itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-editable': false,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-designer': 'Markdown.Void.Designer',
|
|
||||||
'x-component': 'Markdown.Void',
|
|
||||||
'x-component-props': {
|
|
||||||
content: t('This is a demo text, **supports Markdown syntax**.'),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const FormItemInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
wrap={gridRowColWrap}
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Display fields'),
|
|
||||||
children: useFormItemInitializerFields(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Add text'),
|
|
||||||
component: TextItem,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Configure fields')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { SchemaInitializer } from '../SchemaInitializer';
|
||||||
|
import { gridRowColWrap, useFormItemInitializerFields } from './utils';
|
||||||
|
|
||||||
|
// Grid 组件里配置字段
|
||||||
|
export const GridFormItemInitializers = (props: any) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<SchemaInitializer.Button
|
||||||
|
wrap={gridRowColWrap}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Display fields',
|
||||||
|
children: useFormItemInitializerFields(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Add text',
|
||||||
|
component: 'GeneralInitializer',
|
||||||
|
schema: {
|
||||||
|
type: 'void',
|
||||||
|
'x-editable': false,
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-designer': 'Markdown.Void.Designer',
|
||||||
|
'x-component': 'Markdown.Void',
|
||||||
|
'x-component-props': {
|
||||||
|
content: t('This is a demo text, **supports Markdown syntax**.'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t('Configure fields')}
|
||||||
|
</SchemaInitializer.Button>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Switch } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { SchemaInitializer } from '../../SchemaInitializer';
|
||||||
|
import { useCurrentSchema } from '../utils';
|
||||||
|
|
||||||
|
export const ActionInitializer = (props) => {
|
||||||
|
const { item, insert } = props;
|
||||||
|
const { exists, remove } = useCurrentSchema(item.schema['x-action'], 'x-action', item.find);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SchemaInitializer.Item
|
||||||
|
onClick={() => {
|
||||||
|
if (exists) {
|
||||||
|
return remove();
|
||||||
|
}
|
||||||
|
insert({
|
||||||
|
...item.schema,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
|
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
||||||
|
</div>
|
||||||
|
</SchemaInitializer.Item>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,67 @@
|
|||||||
|
import { Switch } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { SchemaInitializer } from '../../SchemaInitializer';
|
||||||
|
import { useCurrentSchema } from '../utils';
|
||||||
|
|
||||||
|
export const AddNewActionInitializer = (props) => {
|
||||||
|
const { item, insert } = props;
|
||||||
|
const { exists, remove } = useCurrentSchema(item?.schema?.['x-action'] || 'create', 'x-action', item.find);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SchemaInitializer.Item
|
||||||
|
onClick={() => {
|
||||||
|
if (exists) {
|
||||||
|
return remove();
|
||||||
|
}
|
||||||
|
insert({
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Add new") }}',
|
||||||
|
'x-action': 'create',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
openMode: 'drawer',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Add new record") }}',
|
||||||
|
'x-component': 'Action.Container',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
properties: {
|
||||||
|
grid: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'GridFormItemInitializers',
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Container.Footer',
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
type: 'void',
|
||||||
|
'x-initializer': 'PopupFormActionInitializers',
|
||||||
|
'x-decorator': 'DndContext',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
layout: 'one-column',
|
||||||
|
},
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...item.schema,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
|
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
||||||
|
</div>
|
||||||
|
</SchemaInitializer.Item>
|
||||||
|
);
|
||||||
|
};
|
@ -3,9 +3,9 @@ import { FormDialog, FormLayout } from '@formily/antd';
|
|||||||
import { ISchema, SchemaOptionsContext } from '@formily/react';
|
import { ISchema, SchemaOptionsContext } from '@formily/react';
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { useCollectionManager } from '../../../collection-manager';
|
import { useCollectionManager } from '../../../collection-manager';
|
||||||
import { SchemaComponent, SchemaComponentOptions } from '../../../schema-component';
|
import { SchemaComponent, SchemaComponentOptions } from '../../../schema-component';
|
||||||
|
import { SchemaInitializer } from '../../SchemaInitializer';
|
||||||
|
|
||||||
const createSchema = (collectionName, { title, start, end }) => {
|
const createSchema = (collectionName, { title, start, end }) => {
|
||||||
const schema: ISchema = {
|
const schema: ISchema = {
|
||||||
@ -38,7 +38,12 @@ const createSchema = (collectionName, { title, start, end }) => {
|
|||||||
toolBar: {
|
toolBar: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Calendar.ActionBar',
|
'x-component': 'Calendar.ActionBar',
|
||||||
'x-action-initializer': 'CalendarActionInitializer',
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-initializer': 'CalendarActionInitializers',
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
event: {
|
event: {
|
||||||
@ -58,7 +63,7 @@ const createSchema = (collectionName, { title, start, end }) => {
|
|||||||
grid: {
|
grid: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-item-initializer': 'FormItemInitializer',
|
'x-initializer': 'GridFormItemInitializers',
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
@ -67,7 +72,7 @@ const createSchema = (collectionName, { title, start, end }) => {
|
|||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-action-initializer': 'PopupFormActionInitializer',
|
'x-initializer': 'PopupFormActionInitializers',
|
||||||
'x-decorator': 'DndContext',
|
'x-decorator': 'DndContext',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
@ -88,9 +93,7 @@ const createSchema = (collectionName, { title, start, end }) => {
|
|||||||
return schema;
|
return schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
const itemWrap = SchemaInitializer.itemWrap;
|
export const CalendarBlockInitializer = (props) => {
|
||||||
|
|
||||||
export const CalendarBlock = itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const { collections, getCollection } = useCollectionManager();
|
const { collections, getCollection } = useCollectionManager();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -160,4 +163,4 @@ export const CalendarBlock = itemWrap((props) => {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { Switch } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { SchemaInitializer } from '../../SchemaInitializer';
|
||||||
|
import { useCurrentSchema } from '../utils';
|
||||||
|
|
||||||
|
export const CollectionFieldInitializer = (props) => {
|
||||||
|
const { item, insert } = props;
|
||||||
|
const { exists, remove } = useCurrentSchema(
|
||||||
|
item.schema['x-collection-field'],
|
||||||
|
'x-collection-field',
|
||||||
|
item.find,
|
||||||
|
item.remove,
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<SchemaInitializer.Item
|
||||||
|
onClick={() => {
|
||||||
|
console.log(item, exists);
|
||||||
|
if (exists) {
|
||||||
|
return remove();
|
||||||
|
}
|
||||||
|
insert({
|
||||||
|
...item.schema,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
|
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
||||||
|
</div>
|
||||||
|
</SchemaInitializer.Item>
|
||||||
|
);
|
||||||
|
};
|
@ -29,12 +29,12 @@ const createSchema = (collectionName) => {
|
|||||||
grid: {
|
grid: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid',
|
'x-component': 'Grid',
|
||||||
'x-item-initializer': 'FormItemInitializer',
|
'x-initializer': 'GridFormItemInitializers',
|
||||||
properties: {},
|
properties: {},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-action-initializer': 'FormActionInitializer',
|
'x-initializer': 'FormActionInitializers',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
layout: 'one-column',
|
layout: 'one-column',
|
||||||
@ -51,9 +51,7 @@ const createSchema = (collectionName) => {
|
|||||||
return schema;
|
return schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
const itemWrap = SchemaInitializer.itemWrap;
|
export const FormBlockInitializer = (props) => {
|
||||||
|
|
||||||
export const FormBlock = itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const { collections } = useCollectionManager();
|
const { collections } = useCollectionManager();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -79,4 +77,4 @@ export const FormBlock = itemWrap((props) => {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
};
|
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { SchemaInitializer } from '../../SchemaInitializer';
|
||||||
|
|
||||||
|
export const GeneralInitializer = (props) => {
|
||||||
|
const { item, insert } = props;
|
||||||
|
return (
|
||||||
|
<SchemaInitializer.Item
|
||||||
|
onClick={() => {
|
||||||
|
insert({
|
||||||
|
...item.schema,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -3,9 +3,7 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SchemaInitializer } from '../..';
|
import { SchemaInitializer } from '../..';
|
||||||
|
|
||||||
const itemWrap = SchemaInitializer.itemWrap;
|
export const MarkdownBlockInitializer = (props) => {
|
||||||
|
|
||||||
export const MarkdownBlock = itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
@ -26,4 +24,4 @@ export const MarkdownBlock = itemWrap((props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
};
|
@ -28,7 +28,7 @@ const createSchema = (collectionName) => {
|
|||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-action-initializer': 'TableActionInitializer',
|
'x-initializer': 'TableActionInitializers',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
style: {
|
style: {
|
||||||
@ -47,7 +47,7 @@ const createSchema = (collectionName) => {
|
|||||||
},
|
},
|
||||||
useDataSource: '{{ cm.useDataSourceFromRAC }}',
|
useDataSource: '{{ cm.useDataSourceFromRAC }}',
|
||||||
},
|
},
|
||||||
'x-column-initializer': 'TableColumnInitializer',
|
'x-initializer': 'TableColumnInitializers',
|
||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
@ -55,7 +55,7 @@ const createSchema = (collectionName) => {
|
|||||||
'x-decorator': 'TableColumnActionBar',
|
'x-decorator': 'TableColumnActionBar',
|
||||||
'x-component': 'VoidTable.Column',
|
'x-component': 'VoidTable.Column',
|
||||||
'x-designer': 'TableRecordActionDesigner',
|
'x-designer': 'TableRecordActionDesigner',
|
||||||
'x-action-initializer': 'TableRecordActionInitializer',
|
'x-initializer': 'TableRecordActionInitializers',
|
||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
@ -75,9 +75,7 @@ const createSchema = (collectionName) => {
|
|||||||
return schema;
|
return schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
const itemWrap = SchemaInitializer.itemWrap;
|
export const TableBlockInitializer = (props) => {
|
||||||
|
|
||||||
export const TableBlock = itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const { collections } = useCollectionManager();
|
const { collections } = useCollectionManager();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -103,4 +101,4 @@ export const TableBlock = itemWrap((props) => {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
};
|
@ -0,0 +1,9 @@
|
|||||||
|
export * from './ActionInitializer';
|
||||||
|
export * from './AddNewActionInitializer';
|
||||||
|
export * from './CalendarBlockInitializer';
|
||||||
|
export * from './CollectionFieldInitializer';
|
||||||
|
export * from './FormBlockInitializer';
|
||||||
|
export * from './GeneralInitializer';
|
||||||
|
export * from './MarkdownBlockInitializer';
|
||||||
|
export * from './TableBlockInitializer';
|
||||||
|
|
@ -1,95 +0,0 @@
|
|||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { useDesignable } from '../../../schema-component';
|
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-component': 'Action',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title}
|
|
||||||
<Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const PopupFormActionInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Enable actions'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Submit'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Submit") }}',
|
|
||||||
'x-action': 'submit',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
|
||||||
type: 'primary',
|
|
||||||
useAction: '{{ cm.useCreateAction }}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Cancel'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Cancel") }}',
|
|
||||||
'x-action': 'cancel',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
|
||||||
useAction: '{{ cm.useCancelAction }}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Configure actions')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,39 @@
|
|||||||
|
// 弹窗表单的操作配置
|
||||||
|
export const PopupFormActionInitializers = {
|
||||||
|
title: "{{t('Configure actions')}}",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: "{{t('Enable actions')}}",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Submit')}}",
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Submit") }}',
|
||||||
|
'x-action': 'submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ cm.useCreateAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Cancel')}}",
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Cancel") }}',
|
||||||
|
'x-action': 'cancel',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ cm.useCancelAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -1,64 +0,0 @@
|
|||||||
import { FormOutlined } from '@ant-design/icons';
|
|
||||||
import { ISchema, observer } from '@formily/react';
|
|
||||||
import { uid } from '@formily/shared';
|
|
||||||
import React from 'react';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
|
|
||||||
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 itemWrap = SchemaInitializer.itemWrap;
|
|
||||||
|
|
||||||
const FormBlock = itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
icon={<FormOutlined />}
|
|
||||||
onClick={() => {
|
|
||||||
insert({});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const RecordBlockInitializer = observer((props: any) => {
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
wrap={gridRowColWrap}
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: 'Data blocks',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: 'Form',
|
|
||||||
component: FormBlock,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: 'Details',
|
|
||||||
component: FormBlock,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Add block
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,8 @@
|
|||||||
|
import { gridRowColWrap } from './utils';
|
||||||
|
|
||||||
|
// 当前行记录所在面板的添加区块
|
||||||
|
export const RecordBlockInitializers = {
|
||||||
|
wrap: gridRowColWrap,
|
||||||
|
title: "{{t('Add block')}}",
|
||||||
|
items: [],
|
||||||
|
};
|
@ -1,143 +0,0 @@
|
|||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaInitializer } from '../..';
|
|
||||||
import { useDesignable } from '../../../schema-component';
|
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-component': 'Action',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title}
|
|
||||||
<Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const TableActionInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
style={{ marginLeft: 8 }}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Enable actions'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Filter'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Filter") }}',
|
|
||||||
'x-action': 'filter',
|
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Add new'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{ t("Add new") }}',
|
|
||||||
'x-action': 'create',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
|
||||||
type: 'primary',
|
|
||||||
openMode: 'drawer',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
drawer: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{ t("Add new record") }}',
|
|
||||||
'x-component': 'Action.Container',
|
|
||||||
'x-component-props': {},
|
|
||||||
'x-decorator': 'Form',
|
|
||||||
properties: {
|
|
||||||
grid: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid',
|
|
||||||
'x-item-initializer': 'FormItemInitializer',
|
|
||||||
properties: {},
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Action.Container.Footer',
|
|
||||||
properties: {
|
|
||||||
actions: {
|
|
||||||
type: 'void',
|
|
||||||
'x-action-initializer': 'PopupFormActionInitializer',
|
|
||||||
'x-decorator': 'DndContext',
|
|
||||||
'x-component': 'ActionBar',
|
|
||||||
'x-component-props': {
|
|
||||||
layout: 'one-column',
|
|
||||||
},
|
|
||||||
properties: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: t('Delete'),
|
|
||||||
component: InitializeAction,
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Delete") }}',
|
|
||||||
'x-action': 'destroy',
|
|
||||||
'x-component-props': {
|
|
||||||
confirm: {
|
|
||||||
title: "{{t('Delete record')}}",
|
|
||||||
content: "{{t('Are you sure you want to delete it?')}}",
|
|
||||||
},
|
|
||||||
useAction: '{{ cm.useBulkDestroyAction }}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Configure actions')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,50 @@
|
|||||||
|
// 表格操作配置
|
||||||
|
export const TableActionInitializers = {
|
||||||
|
title: "{{t('Configure actions')}}",
|
||||||
|
style: {
|
||||||
|
marginLeft: 8,
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: "{{t('Enable actions')}}",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Filter')}}",
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Filter") }}',
|
||||||
|
'x-action': 'filter',
|
||||||
|
'x-align': 'left',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Add new')}}",
|
||||||
|
component: 'AddNewActionInitializer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Delete')}}",
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Delete") }}',
|
||||||
|
'x-action': 'destroy',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-component-props': {
|
||||||
|
confirm: {
|
||||||
|
title: "{{t('Delete record')}}",
|
||||||
|
content: "{{t('Are you sure you want to delete it?')}}",
|
||||||
|
},
|
||||||
|
useAction: '{{ cm.useBulkDestroyAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -1,102 +0,0 @@
|
|||||||
import { observer, Schema, useFieldSchema } from '@formily/react';
|
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaInitializer, SchemaInitializerItemOptions } from '../..';
|
|
||||||
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;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const useCurrentColumnSchema = (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.parent);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const ColumnInitializerItem = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentColumnSchema(item.schema['x-collection-field']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-decorator': 'TableColumnDecorator',
|
|
||||||
'x-designer': 'TableColumnDeigner',
|
|
||||||
'x-component': 'VoidTable.Column',
|
|
||||||
properties: {
|
|
||||||
[item.schema.name]: {
|
|
||||||
'x-read-pretty': true,
|
|
||||||
...item.schema,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 表格列配置器
|
|
||||||
*/
|
|
||||||
export const TableColumnInitializer = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: t('Display fields'),
|
|
||||||
children: useTableColumnInitializerFields(),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t('Configure columns')}
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,37 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { SchemaInitializer } from '../SchemaInitializer';
|
||||||
|
import { useTableColumnInitializerFields } from './utils';
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
export const TableColumnInitializers = (props: any) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<SchemaInitializer.Button
|
||||||
|
insertPosition={'beforeEnd'}
|
||||||
|
wrap={(s) => {
|
||||||
|
return {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableColumnDecorator',
|
||||||
|
'x-designer': 'TableColumnDeigner',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
[s.name]: {
|
||||||
|
'x-read-pretty': true,
|
||||||
|
...s,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: t('Display fields'),
|
||||||
|
children: useTableColumnInitializerFields(),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t('Configure columns')}
|
||||||
|
</SchemaInitializer.Button>
|
||||||
|
);
|
||||||
|
};
|
@ -1,92 +1,18 @@
|
|||||||
import { MenuOutlined } from '@ant-design/icons';
|
import { MenuOutlined } from '@ant-design/icons';
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { observer, Schema, useFieldSchema } from '@formily/react';
|
import { useFieldSchema } from '@formily/react';
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SchemaInitializer } from '../..';
|
import { SchemaInitializer } from '../..';
|
||||||
import { useAPIClient } from '../../../api-client';
|
import { useAPIClient } from '../../api-client';
|
||||||
import { createDesignable, useDesignable } from '../../../schema-component';
|
import { createDesignable, useDesignable } from '../../schema-component';
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
export const TableRecordActionInitializers = (props: any) => {
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const findActionSchema = (schema: Schema) => {
|
|
||||||
return schema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
const c = findActionSchema(s);
|
|
||||||
if (c) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const schema = findActionSchema(fieldSchema);
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeViewAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
console.log('InitializeAction', insert);
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Action.Link',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
console.log('InitializeAction', insert);
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-component': 'Action.Link',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const TableRecordActionInitializer = observer((props: any) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const { refresh } = useDesignable();
|
const { refresh } = useDesignable();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
console.log('TableRecordActionInitializers');
|
||||||
return (
|
return (
|
||||||
<SchemaInitializer.Button
|
<SchemaInitializer.Button
|
||||||
className={css`
|
className={css`
|
||||||
@ -126,7 +52,7 @@ export const TableRecordActionInitializer = observer((props: any) => {
|
|||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: t('View'),
|
title: t('View'),
|
||||||
component: InitializeViewAction,
|
component: 'ActionInitializer',
|
||||||
schema: {
|
schema: {
|
||||||
title: '{{ t("View") }}',
|
title: '{{ t("View") }}',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
@ -171,11 +97,12 @@ export const TableRecordActionInitializer = observer((props: any) => {
|
|||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: t('Edit'),
|
title: t('Edit'),
|
||||||
component: InitializeAction,
|
component: 'ActionInitializer',
|
||||||
schema: {
|
schema: {
|
||||||
title: '{{ t("Edit") }}',
|
title: '{{ t("Edit") }}',
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-action': 'update',
|
'x-action': 'update',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
'x-component': 'Action.Link',
|
'x-component': 'Action.Link',
|
||||||
'x-component-props': {},
|
'x-component-props': {},
|
||||||
properties: {
|
properties: {
|
||||||
@ -218,10 +145,12 @@ export const TableRecordActionInitializer = observer((props: any) => {
|
|||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: t('Delete'),
|
title: t('Delete'),
|
||||||
component: InitializeAction,
|
component: 'ActionInitializer',
|
||||||
schema: {
|
schema: {
|
||||||
title: '{{ t("Delete") }}',
|
title: '{{ t("Delete") }}',
|
||||||
'x-action': 'destroy',
|
'x-action': 'destroy',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
confirm: {
|
confirm: {
|
||||||
title: "{{t('Delete record')}}",
|
title: "{{t('Delete record')}}",
|
||||||
@ -238,4 +167,4 @@ export const TableRecordActionInitializer = observer((props: any) => {
|
|||||||
<MenuOutlined />
|
<MenuOutlined />
|
||||||
</SchemaInitializer.Button>
|
</SchemaInitializer.Button>
|
||||||
);
|
);
|
||||||
});
|
};
|
@ -1,11 +0,0 @@
|
|||||||
export * from './BlockInitializer';
|
|
||||||
export * from './CalendarActionInitializer';
|
|
||||||
export * from './DetailsActionInitializer';
|
|
||||||
export * from './FormActionInitializer';
|
|
||||||
export * from './FormItemInitializer';
|
|
||||||
export * from './PopupFormActionInitializer';
|
|
||||||
export * from './RecordBlockInitializer';
|
|
||||||
export * from './TableActionInitializer';
|
|
||||||
export * from './TableColumnInitializer';
|
|
||||||
export * from './TableRecordActionInitializer';
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
import { BlockInitializers } from './BlockInitializers';
|
||||||
|
import { CalendarActionInitializers } from './CalendarActionInitializers';
|
||||||
|
import { DetailsActionInitializers } from './DetailsActionInitializers';
|
||||||
|
import { FormActionInitializers } from './FormActionInitializers';
|
||||||
|
import { GridFormItemInitializers } from './GridFormItemInitializers';
|
||||||
|
import * as Items from './Items';
|
||||||
|
import { PopupFormActionInitializers } from './PopupFormActionInitializers';
|
||||||
|
import { RecordBlockInitializers } from './RecordBlockInitializers';
|
||||||
|
import { TableActionInitializers } from './TableActionInitializers';
|
||||||
|
import { TableColumnInitializers } from './TableColumnInitializers';
|
||||||
|
import { TableRecordActionInitializers } from './TableRecordActionInitializers';
|
||||||
|
|
||||||
|
export const items = { ...Items };
|
||||||
|
|
||||||
|
export const initializes = {
|
||||||
|
// 页面里的「添加区块」
|
||||||
|
BlockInitializers,
|
||||||
|
// 日历的「操作配置」
|
||||||
|
CalendarActionInitializers,
|
||||||
|
// 详情的「操作配置」
|
||||||
|
DetailsActionInitializers,
|
||||||
|
// 普通表单的「操作配置」
|
||||||
|
FormActionInitializers,
|
||||||
|
// Grid 组件里「配置字段」
|
||||||
|
GridFormItemInitializers,
|
||||||
|
// 弹窗表单的「操作配置」
|
||||||
|
PopupFormActionInitializers,
|
||||||
|
// 当前行记录所在面板的「添加区块」
|
||||||
|
RecordBlockInitializers,
|
||||||
|
// 表格「操作配置」
|
||||||
|
TableActionInitializers,
|
||||||
|
// 表格「列配置」
|
||||||
|
TableColumnInitializers,
|
||||||
|
// 表格当前行记录的「操作配置」
|
||||||
|
TableRecordActionInitializers,
|
||||||
|
};
|
109
packages/client/src/schema-initializer/Initializers/utils.ts
Normal file
109
packages/client/src/schema-initializer/Initializers/utils.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import { ISchema, Schema, useFieldSchema } from '@formily/react';
|
||||||
|
import { uid } from '@formily/shared';
|
||||||
|
import { SchemaInitializerItemOptions } from '../';
|
||||||
|
import { useCollection } from '../../collection-manager';
|
||||||
|
import { useDesignable } from '../../schema-component';
|
||||||
|
|
||||||
|
export const gridRowColWrap = (schema: ISchema) => {
|
||||||
|
return {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
properties: {
|
||||||
|
[uid()]: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
properties: {
|
||||||
|
[schema.name || uid()]: schema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeTableColumn = (schema, cb) => {
|
||||||
|
cb(schema, {
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
breakRemoveOn: {
|
||||||
|
'x-component': 'ArrayTable',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeGridFormItem = (schema, cb) => {
|
||||||
|
cb(schema, {
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
breakRemoveOn: {
|
||||||
|
'x-component': 'Grid',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export 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: 'CollectionFieldInitializer',
|
||||||
|
remove: removeTableColumn,
|
||||||
|
} as SchemaInitializerItemOptions;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFormItemInitializerFields = () => {
|
||||||
|
const { name, fields } = useCollection();
|
||||||
|
return fields?.map((field) => {
|
||||||
|
return {
|
||||||
|
type: 'item',
|
||||||
|
title: field?.uiSchema?.title || field.name,
|
||||||
|
component: 'CollectionFieldInitializer',
|
||||||
|
remove: removeGridFormItem,
|
||||||
|
schema: {
|
||||||
|
name: field.name,
|
||||||
|
'x-designer': 'FormItem.Designer',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-collection-field': `${name}.${field.name}`,
|
||||||
|
},
|
||||||
|
} as SchemaInitializerItemOptions;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const findSchema = (schema: Schema, key: string, action: string) => {
|
||||||
|
return schema.reduceProperties((buf, s) => {
|
||||||
|
if (s[key] === action) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
const c = findSchema(s, key, action);
|
||||||
|
if (c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeSchema = (schema, cb) => {
|
||||||
|
return cb(schema);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCurrentSchema = (action: string, key: string, find = findSchema, rm = removeSchema) => {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { remove } = useDesignable();
|
||||||
|
const schema = find(fieldSchema, key, action);
|
||||||
|
return {
|
||||||
|
schema,
|
||||||
|
exists: !!schema,
|
||||||
|
remove() {
|
||||||
|
schema && rm(schema, remove);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
@ -2,6 +2,7 @@ import { ISchema, observer } from '@formily/react';
|
|||||||
import { Button, Dropdown, Menu } from 'antd';
|
import { Button, Dropdown, Menu } from 'antd';
|
||||||
import React, { createContext, useContext, useState } from 'react';
|
import React, { createContext, useContext, useState } from 'react';
|
||||||
import { useDesignable } from '../schema-component/hooks';
|
import { useDesignable } from '../schema-component/hooks';
|
||||||
|
import { initializes, items } from './Initializers';
|
||||||
import {
|
import {
|
||||||
SchemaInitializerButtonProps,
|
SchemaInitializerButtonProps,
|
||||||
SchemaInitializerItemComponent,
|
SchemaInitializerItemComponent,
|
||||||
@ -15,8 +16,21 @@ export const SchemaInitializerItemContext = createContext(null);
|
|||||||
|
|
||||||
export const SchemaInitializer = () => null;
|
export const SchemaInitializer = () => null;
|
||||||
|
|
||||||
|
SchemaInitializer.items = items;
|
||||||
|
|
||||||
|
SchemaInitializer.initializes = initializes;
|
||||||
|
|
||||||
SchemaInitializer.Button = observer((props: SchemaInitializerButtonProps) => {
|
SchemaInitializer.Button = observer((props: SchemaInitializerButtonProps) => {
|
||||||
const { insert, wrap = defaultWrap, items = [], insertPosition, dropdown, style, ...others } = props;
|
const {
|
||||||
|
title,
|
||||||
|
insert,
|
||||||
|
wrap = defaultWrap,
|
||||||
|
items = [],
|
||||||
|
insertPosition = 'beforeEnd',
|
||||||
|
dropdown,
|
||||||
|
style,
|
||||||
|
...others
|
||||||
|
} = props;
|
||||||
let { insertAdjacent, findComponent, designable } = useDesignable();
|
let { insertAdjacent, findComponent, designable } = useDesignable();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const insertSchema = (schema) => {
|
const insertSchema = (schema) => {
|
||||||
@ -102,7 +116,9 @@ SchemaInitializer.Button = observer((props: SchemaInitializerButtonProps) => {
|
|||||||
borderColor: '#f18b62',
|
borderColor: '#f18b62',
|
||||||
color: '#f18b62',
|
color: '#f18b62',
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
{props.children || props.title}
|
||||||
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,54 @@
|
|||||||
import React from 'react';
|
import { isPlainObj } from '@formily/shared';
|
||||||
|
import React, { createContext, useContext } from 'react';
|
||||||
import { SchemaComponentOptions } from '../schema-component';
|
import { SchemaComponentOptions } from '../schema-component';
|
||||||
import * as initializers from './Initializers';
|
import { initializes as globals, items } from './Initializers';
|
||||||
|
import { SchemaInitializer } from './SchemaInitializer';
|
||||||
|
|
||||||
export const SchemaInitializerProvider: React.FC = (props) => {
|
const SchemaInitializerContext = createContext(null);
|
||||||
return <SchemaComponentOptions components={initializers}>{props.children}</SchemaComponentOptions>;
|
|
||||||
|
export interface SchemaInitializerProviderProps {
|
||||||
|
initializers?: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSchemaInitializer = (name: string) => {
|
||||||
|
const initializers = useContext(SchemaInitializerContext);
|
||||||
|
|
||||||
|
const render = (component?: any, props?: any) => {
|
||||||
|
return component && React.createElement(component, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
return { exists: false, render };
|
||||||
|
}
|
||||||
|
|
||||||
|
const initializer = initializers?.[name];
|
||||||
|
|
||||||
|
if (!initializer) {
|
||||||
|
return { exists: false, render };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPlainObj(initializer)) {
|
||||||
|
return {
|
||||||
|
exists: true,
|
||||||
|
render: (props?: any) => {
|
||||||
|
const component = (initializer as any).component || SchemaInitializer.Button;
|
||||||
|
return render(component, { ...initializer, ...props });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
exists: true,
|
||||||
|
render: (props?: any) => render(initializer, props),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SchemaInitializerProvider: React.FC<SchemaInitializerProviderProps> = (props) => {
|
||||||
|
const { initializers, children } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SchemaInitializerContext.Provider value={{ ...globals, ...initializers }}>
|
||||||
|
<SchemaComponentOptions components={{ ...items }}>{children}</SchemaComponentOptions>
|
||||||
|
</SchemaInitializerContext.Provider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { FormOutlined, TableOutlined } from '@ant-design/icons';
|
import { TableOutlined } from '@ant-design/icons';
|
||||||
import { Field } from '@formily/core';
|
import { Field } from '@formily/core';
|
||||||
import { observer, useField } from '@formily/react';
|
import { observer, useField } from '@formily/react';
|
||||||
import { SchemaComponent, SchemaComponentProvider, SchemaInitializer } from '@nocobase/client';
|
import {
|
||||||
|
SchemaComponent,
|
||||||
|
SchemaComponentProvider,
|
||||||
|
SchemaInitializer,
|
||||||
|
SchemaInitializerProvider,
|
||||||
|
useSchemaInitializer
|
||||||
|
} from '@nocobase/client';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const Hello = observer((props) => {
|
const Hello = observer((props) => {
|
||||||
@ -13,36 +19,7 @@ const Hello = observer((props) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const AddBlockButton = observer((props: any) => {
|
const TableBlockInitializer = SchemaInitializer.itemWrap((props) => {
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
wrap={(schema) => schema}
|
|
||||||
insertPosition={'beforeBegin'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: 'Data blocks',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: 'Table',
|
|
||||||
component: TableBlockInitializerItem,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: 'Form',
|
|
||||||
component: FormBlockInitializerItem,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
Add block
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const TableBlockInitializerItem = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const items: any = [
|
const items: any = [
|
||||||
{
|
{
|
||||||
@ -77,48 +54,69 @@ const TableBlockInitializerItem = SchemaInitializer.itemWrap((props) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const FormBlockInitializerItem = SchemaInitializer.itemWrap((props) => {
|
const initializers = {
|
||||||
const { insert } = props;
|
AddBlock: {
|
||||||
return (
|
title: 'Add block',
|
||||||
<SchemaInitializer.Item
|
insertPosition: 'beforeBegin',
|
||||||
icon={<FormOutlined />}
|
items: [
|
||||||
onClick={() => {
|
{
|
||||||
insert({
|
type: 'itemGroup',
|
||||||
type: 'void',
|
title: 'Data blocks',
|
||||||
title: 'Form',
|
children: [
|
||||||
'x-component': 'Hello',
|
{
|
||||||
});
|
type: 'item',
|
||||||
}}
|
title: 'Table',
|
||||||
/>
|
component: 'TableBlockInitializer',
|
||||||
);
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Form',
|
||||||
|
component: 'GeneralInitializer',
|
||||||
|
schema: {
|
||||||
|
type: 'void',
|
||||||
|
title: 'Form',
|
||||||
|
'x-component': 'Hello',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddBlockButton = observer((props: any) => {
|
||||||
|
const { render } = useSchemaInitializer('AddBlock');
|
||||||
|
return <>{render()}</>;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<SchemaComponentProvider components={{ Hello, AddBlockButton }}>
|
<SchemaComponentProvider components={{ TableBlockInitializer, Hello, AddBlockButton }}>
|
||||||
<SchemaComponent
|
<SchemaInitializerProvider initializers={initializers}>
|
||||||
schema={{
|
<SchemaComponent
|
||||||
type: 'void',
|
schema={{
|
||||||
name: 'page',
|
type: 'void',
|
||||||
'x-component': 'div',
|
name: 'page',
|
||||||
properties: {
|
'x-component': 'div',
|
||||||
hello1: {
|
properties: {
|
||||||
type: 'void',
|
hello1: {
|
||||||
title: 'Test1',
|
type: 'void',
|
||||||
'x-component': 'Hello',
|
title: 'Test1',
|
||||||
|
'x-component': 'Hello',
|
||||||
|
},
|
||||||
|
hello2: {
|
||||||
|
type: 'void',
|
||||||
|
title: 'Test2',
|
||||||
|
'x-component': 'Hello',
|
||||||
|
},
|
||||||
|
initializer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'AddBlockButton',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hello2: {
|
}}
|
||||||
type: 'void',
|
/>
|
||||||
title: 'Test2',
|
</SchemaInitializerProvider>
|
||||||
'x-component': 'Hello',
|
|
||||||
},
|
|
||||||
initializer: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'AddBlockButton',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SchemaComponentProvider>
|
</SchemaComponentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,117 +1,77 @@
|
|||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
ActionBar,
|
ActionBar,
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
SchemaComponentProvider,
|
SchemaComponentProvider,
|
||||||
SchemaInitializer,
|
SchemaInitializerProvider
|
||||||
useDesignable
|
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const AddActionButton = observer((props: any) => {
|
const initializers = {
|
||||||
return (
|
AddAction: {
|
||||||
<SchemaInitializer.Button
|
title: 'Configure actions',
|
||||||
insertPosition={'beforeEnd'}
|
insertPosition: 'beforeEnd',
|
||||||
style={{ marginLeft: 8 }}
|
style: { marginLeft: 8 },
|
||||||
items={[
|
items: [
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
title: 'Enable actions',
|
title: 'Enable actions',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
|
title: 'Create',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
title: 'Create',
|
title: 'Create',
|
||||||
component: InitializeAction,
|
'x-action': 'posts:create',
|
||||||
schema: {
|
'x-component': 'Action',
|
||||||
title: 'Create',
|
'x-designer': 'Action.Designer',
|
||||||
'x-action': 'posts:create',
|
'x-align': 'left',
|
||||||
'x-align': 'left',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
type: 'item',
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Update',
|
||||||
|
component: 'ActionInitializer',
|
||||||
|
schema: {
|
||||||
title: 'Update',
|
title: 'Update',
|
||||||
component: InitializeAction,
|
'x-action': 'posts:update',
|
||||||
schema: {
|
'x-component': 'Action',
|
||||||
title: 'Update',
|
'x-designer': 'Action.Designer',
|
||||||
'x-action': 'posts:update',
|
'x-align': 'right',
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
},
|
],
|
||||||
]}
|
},
|
||||||
>
|
],
|
||||||
Configure actions
|
},
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const useCurrentActionSchema = (action: string) => {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const { remove } = useDesignable();
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-action'] === action) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
schema,
|
|
||||||
exists: !!schema,
|
|
||||||
remove() {
|
|
||||||
schema && remove(schema);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const InitializeAction = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentActionSchema(item.schema['x-action']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Action',
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<SchemaComponentProvider components={{ ActionBar, Action, AddActionButton }}>
|
<SchemaComponentProvider components={{ ActionBar, Action }}>
|
||||||
<SchemaComponent
|
<SchemaInitializerProvider initializers={initializers}>
|
||||||
schema={{
|
<SchemaComponent
|
||||||
type: 'void',
|
schema={{
|
||||||
name: 'page',
|
type: 'void',
|
||||||
'x-component': 'ActionBar',
|
name: 'page',
|
||||||
// 指定初始化的按钮组件,
|
'x-component': 'ActionBar',
|
||||||
// Table、Form、Details、Calendar、Kanban 等等不同区块
|
// 指定初始化的按钮组件,
|
||||||
// 可以根据情况组装自己的 initializer
|
// Table、Form、Details、Calendar、Kanban 等等不同区块
|
||||||
'x-action-initializer': 'AddActionButton',
|
// 可以根据情况组装自己的 initializer
|
||||||
properties: {
|
'x-initializer': 'AddAction',
|
||||||
action1: {
|
properties: {
|
||||||
type: 'void',
|
action1: {
|
||||||
title: 'Update',
|
type: 'void',
|
||||||
// 使用 x-action 来标记 action schema
|
title: 'Update',
|
||||||
'x-action': 'posts:update',
|
// 使用 x-action 来标记 action schema
|
||||||
'x-component': 'Action',
|
'x-action': 'posts:update',
|
||||||
|
'x-component': 'Action',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</SchemaInitializerProvider>
|
||||||
</SchemaComponentProvider>
|
</SchemaComponentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { observer, Schema, useFieldSchema } from '@formily/react';
|
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormItem,
|
FormItem,
|
||||||
@ -6,18 +5,18 @@ import {
|
|||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
SchemaComponentProvider,
|
SchemaComponentProvider,
|
||||||
SchemaInitializer,
|
SchemaInitializer,
|
||||||
SchemaInitializerItemOptions,
|
SchemaInitializerItemOptions
|
||||||
useDesignable
|
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { Input, Switch } from 'antd';
|
import { Input } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { SchemaInitializerProvider, useSchemaInitializer } from '..';
|
||||||
|
|
||||||
const useFormItemInitializerFields = () => {
|
const useFormItemInitializerFields = () => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
component: InitializeFormItem,
|
component: 'CollectionFieldInitializer',
|
||||||
schema: {
|
schema: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
@ -30,7 +29,7 @@ const useFormItemInitializerFields = () => {
|
|||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: 'Title',
|
title: 'Title',
|
||||||
component: InitializeFormItem,
|
component: 'CollectionFieldInitializer',
|
||||||
schema: {
|
schema: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: 'Title',
|
title: 'Title',
|
||||||
@ -43,79 +42,7 @@ const useFormItemInitializerFields = () => {
|
|||||||
] as SchemaInitializerItemOptions[];
|
] as SchemaInitializerItemOptions[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const AddFormItemButton = observer((props: any) => {
|
const TextInitializer = SchemaInitializer.itemWrap((props) => {
|
||||||
return (
|
|
||||||
<SchemaInitializer.Button
|
|
||||||
wrap={(schema) => schema}
|
|
||||||
insertPosition={'beforeEnd'}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: 'Display fields',
|
|
||||||
children: useFormItemInitializerFields(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
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);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const InitializeFormItem = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentFieldSchema(item.schema['x-collection-field']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
...item.schema,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const InitializeTextFormItem = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
return (
|
return (
|
||||||
<SchemaInitializer.Item
|
<SchemaInitializer.Item
|
||||||
@ -132,41 +59,66 @@ const InitializeTextFormItem = SchemaInitializer.itemWrap((props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const Page = (props) => {
|
const Page = (props) => {
|
||||||
|
const { render } = useSchemaInitializer('AddFormItem');
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{props.children}
|
{props.children}
|
||||||
<AddFormItemButton />
|
{render()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
const initializers = {
|
||||||
|
AddFormItem: {
|
||||||
|
title: 'Configure fields',
|
||||||
|
insertPosition: 'beforeEnd',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: 'Display fields',
|
||||||
|
// 从 hook 动态加载字段
|
||||||
|
children: useFormItemInitializerFields(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: 'Add text',
|
||||||
|
component: 'TextInitializer',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<SchemaComponentProvider components={{ Page, Form, Input, FormItem, Markdown }}>
|
<SchemaComponentProvider components={{ TextInitializer, Page, Form, Input, FormItem, Markdown }}>
|
||||||
<SchemaComponent
|
<SchemaInitializerProvider initializers={initializers}>
|
||||||
schema={{
|
<SchemaComponent
|
||||||
type: 'void',
|
schema={{
|
||||||
name: 'page',
|
type: 'void',
|
||||||
'x-decorator': 'Form',
|
name: 'page',
|
||||||
'x-component': 'Page',
|
'x-decorator': 'Form',
|
||||||
properties: {
|
'x-component': 'Page',
|
||||||
title: {
|
properties: {
|
||||||
type: 'string',
|
title: {
|
||||||
title: 'Title',
|
type: 'string',
|
||||||
'x-component': 'Input',
|
title: 'Title',
|
||||||
'x-decorator': 'FormItem',
|
'x-component': 'Input',
|
||||||
'x-collection-field': 'posts.title',
|
'x-decorator': 'FormItem',
|
||||||
|
'x-collection-field': 'posts.title',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
title: 'Name',
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-collection-field': 'posts.name',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
name: {
|
}}
|
||||||
type: 'string',
|
/>
|
||||||
title: 'Name',
|
</SchemaInitializerProvider>
|
||||||
'x-component': 'Input',
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-collection-field': 'posts.name',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SchemaComponentProvider>
|
</SchemaComponentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,116 +1,90 @@
|
|||||||
import { observer, Schema, useFieldSchema } from '@formily/react';
|
import { uid } from '@formily/shared';
|
||||||
import {
|
import {
|
||||||
ArrayTable,
|
ArrayTable,
|
||||||
Input,
|
Input,
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
SchemaComponentProvider,
|
SchemaComponentProvider,
|
||||||
SchemaInitializer,
|
|
||||||
SchemaInitializerItemOptions,
|
SchemaInitializerItemOptions,
|
||||||
useDesignable
|
SchemaInitializerProvider
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { Switch } from 'antd';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
const removeColumn = (schema, cb) => {
|
||||||
|
cb(schema, {
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
breakRemoveOn: {
|
||||||
|
'x-component': 'ArrayTable',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const useTableColumnInitializerFields = () => {
|
const useTableColumnInitializerFields = () => {
|
||||||
const fields: SchemaInitializerItemOptions[] = [
|
const fields: SchemaInitializerItemOptions[] = [
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
|
remove: removeColumn,
|
||||||
schema: {
|
schema: {
|
||||||
type: 'string',
|
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
type: 'string',
|
||||||
|
title: 'Name',
|
||||||
'x-collection-field': 'posts.name',
|
'x-collection-field': 'posts.name',
|
||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
|
'x-read-pretty': true,
|
||||||
},
|
},
|
||||||
component: ColumnInitializerItem,
|
component: 'CollectionFieldInitializer',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: 'Title',
|
title: 'Title',
|
||||||
|
remove: removeColumn,
|
||||||
schema: {
|
schema: {
|
||||||
type: 'string',
|
|
||||||
name: 'title',
|
name: 'title',
|
||||||
|
type: 'string',
|
||||||
|
title: 'Title',
|
||||||
'x-collection-field': 'posts.title',
|
'x-collection-field': 'posts.title',
|
||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
|
'x-read-pretty': true,
|
||||||
},
|
},
|
||||||
component: ColumnInitializerItem,
|
component: 'CollectionFieldInitializer',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return fields;
|
return fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AddTableColumn = observer((props: any) => {
|
const columnWrap = (s) => {
|
||||||
return (
|
return {
|
||||||
<SchemaInitializer.Button
|
name: [uid()],
|
||||||
wrap={(schema) => schema}
|
type: 'void',
|
||||||
insertPosition={'beforeEnd'}
|
title: s.title,
|
||||||
items={[
|
'x-component': 'ArrayTable.Column',
|
||||||
|
properties: {
|
||||||
|
[s.name]: {
|
||||||
|
...s,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 因为有个动态获取字段的 hook,所以这里将 SchemaInitializerProvider 自定义的处理了一下
|
||||||
|
const CustomSchemaInitializerProvider: React.FC = (props) => {
|
||||||
|
const initializers = {
|
||||||
|
AddColumn: {
|
||||||
|
insertPosition: 'beforeEnd',
|
||||||
|
title: 'Configure columns',
|
||||||
|
wrap: columnWrap,
|
||||||
|
items: [
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
title: 'Display fields',
|
title: 'Display fields',
|
||||||
children: useTableColumnInitializerFields(),
|
children: useTableColumnInitializerFields(),
|
||||||
},
|
},
|
||||||
]}
|
],
|
||||||
>
|
|
||||||
Configure columns
|
|
||||||
</SchemaInitializer.Button>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const useCurrentColumnSchema = (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.parent);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
return <SchemaInitializerProvider initializers={initializers}>{props.children}</SchemaInitializerProvider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ColumnInitializerItem = SchemaInitializer.itemWrap((props) => {
|
|
||||||
const { item, insert } = props;
|
|
||||||
const { exists, remove } = useCurrentColumnSchema(item.schema['x-collection-field']);
|
|
||||||
return (
|
|
||||||
<SchemaInitializer.Item
|
|
||||||
onClick={() => {
|
|
||||||
if (exists) {
|
|
||||||
return remove();
|
|
||||||
}
|
|
||||||
insert({
|
|
||||||
type: 'void',
|
|
||||||
title: item.schema.name,
|
|
||||||
'x-component': 'ArrayTable.Column',
|
|
||||||
properties: {
|
|
||||||
[item.schema.name]: {
|
|
||||||
'x-read-pretty': true,
|
|
||||||
...item.schema,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
||||||
{item.title} <Switch size={'small'} checked={exists} />
|
|
||||||
</div>
|
|
||||||
</SchemaInitializer.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@ -122,7 +96,7 @@ const schema = {
|
|||||||
{ id: 3, name: 'Name3' },
|
{ id: 3, name: 'Name3' },
|
||||||
],
|
],
|
||||||
'x-component': 'ArrayTable',
|
'x-component': 'ArrayTable',
|
||||||
'x-column-initializer': 'AddTableColumn',
|
'x-initializer': 'AddColumn',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
},
|
},
|
||||||
@ -147,8 +121,10 @@ const schema = {
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<SchemaComponentProvider components={{ AddTableColumn, Input, ArrayTable }}>
|
<SchemaComponentProvider components={{ Input, ArrayTable }}>
|
||||||
<SchemaComponent schema={schema} />
|
<CustomSchemaInitializerProvider>
|
||||||
|
<SchemaComponent schema={schema} />
|
||||||
|
</CustomSchemaInitializerProvider>
|
||||||
</SchemaComponentProvider>
|
</SchemaComponentProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -150,3 +150,70 @@ const TableBlockInitializerItem = SchemaInitializer.itemWrap((props) => {
|
|||||||
### Table.Column
|
### Table.Column
|
||||||
|
|
||||||
<code src="./demos/demo4.tsx" />
|
<code src="./demos/demo4.tsx" />
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
核心的参数
|
||||||
|
|
||||||
|
```tsx | pure
|
||||||
|
const initializers = {
|
||||||
|
xxx: {
|
||||||
|
title: '{{t("Add block")}}',
|
||||||
|
insertPosition: 'beforeEnd',
|
||||||
|
items: [], // 在这里配置
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
<SchemaInitializerProvider initializers={initializers}>
|
||||||
|
{/* children */}
|
||||||
|
</SchemaInitializerProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
items 例子:
|
||||||
|
|
||||||
|
- Initializer.Item 只有添加的逻辑
|
||||||
|
- Initializer.SwitchItem 可以添加或移除
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
BlockInitializer: {
|
||||||
|
insertPosition: 'beforeEnd',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: "{{t('Enable actions')}}",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Tody')}}",
|
||||||
|
component: 'Initializer.SwitchItem',
|
||||||
|
schema: {
|
||||||
|
title: "{{t('Tody')}}",
|
||||||
|
'x-component': 'Calendar.Today',
|
||||||
|
'x-action': `calendar:today`,
|
||||||
|
'x-align': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: "{{t('Tody')}}",
|
||||||
|
component: 'Initializer.Item',
|
||||||
|
schema: {
|
||||||
|
title: "{{t('Tody')}}",
|
||||||
|
'x-component': 'Calendar.Today',
|
||||||
|
'x-action': `calendar:today`,
|
||||||
|
'x-align': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
内置的 Initializer 有:
|
||||||
|
|
||||||
|
- `GeneralInitializer` 通用的配置项,只有插入的逻辑
|
||||||
|
- `ActionInitializer` 用于配置操作按钮,有插入和移除的逻辑
|
||||||
|
- `CollectionFieldInitializer` 用于配置数据表字段,有插入和移除的逻辑
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from './SchemaInitializer';
|
export * from './SchemaInitializer';
|
||||||
export * from './SchemaInitializerProvider';
|
export * from './SchemaInitializerProvider';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ISchema } from '@formily/react';
|
import { ISchema, Schema } from '@formily/react';
|
||||||
import { ButtonProps, DropDownProps, MenuItemProps } from 'antd';
|
import { ButtonProps, DropDownProps, MenuItemProps } from 'antd';
|
||||||
|
|
||||||
export interface SchemaInitializerButtonProps extends ButtonProps {
|
export interface SchemaInitializerButtonProps extends ButtonProps {
|
||||||
@ -25,10 +25,21 @@ interface SubMenuOptions extends ItemCommonOptions {
|
|||||||
children?: SchemaInitializerItemOptions[];
|
children?: SchemaInitializerItemOptions[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BreakFn = (s: ISchema) => boolean;
|
||||||
|
|
||||||
|
interface RemoveOptions {
|
||||||
|
removeParentsIfNoChildren?: boolean;
|
||||||
|
breakRemoveOn?: ISchema | BreakFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoveCallback = (s: Schema, options?: RemoveOptions) => void;
|
||||||
|
|
||||||
interface ItemOptions extends ItemCommonOptions {
|
interface ItemOptions extends ItemCommonOptions {
|
||||||
type: 'item';
|
type: 'item';
|
||||||
component?: any;
|
component?: any;
|
||||||
schema?: ISchema;
|
schema?: ISchema;
|
||||||
|
remove?: (schema: Schema, cb: RemoveCallback) => void;
|
||||||
|
find?: (schema: Schema, current: string) => Schema | null | undefined;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ export class UiRoutesStoragePlugin extends Plugin {
|
|||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Menu',
|
'x-component': 'Menu',
|
||||||
'x-designer': 'Menu.Designer',
|
'x-designer': 'Menu.Designer',
|
||||||
'x-initializer': 'MenuItemInitializer',
|
'x-initializer': 'MenuItemInitializers',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
mode: 'mix',
|
mode: 'mix',
|
||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
|
Loading…
Reference in New Issue
Block a user