Unverified Commit 2fb019c3 authored by chenos's avatar chenos Committed by GitHub
Browse files

feat: block templates (#240)

* feat: block templates

* feat: improve code

* feat: improve code

* feat: schema  settings for block templates

* feat: improve code

* feat: transition

* feat: transition
parent 5c92d3ba
Showing with 288 additions and 179 deletions
+288 -179
......@@ -5,6 +5,8 @@ import {
AntdSchemaComponentProvider,
APIClientProvider,
AuthLayout,
BlockTemplateDetails,
BlockTemplatePage,
ChinaRegionProvider,
CollectionManagerShortcut,
compose,
......@@ -13,19 +15,20 @@ import {
i18n,
MenuItemInitializers,
PluginManagerProvider,
RemoteRouteSwitchProvider,
// RemoteCollectionManagerProvider,
RouteSchemaComponent,
RouteSwitch,
RouteSwitchProvider,
SchemaComponentProvider,
SchemaInitializerProvider,
SchemaTemplateShortcut,
SigninPage,
SignupPage,
SystemSettingsProvider,
SystemSettingsShortcut,
useRequest
useRoutes
} from '@nocobase/client';
import { notification, Spin } from 'antd';
import { notification } from 'antd';
import 'antd/dist/antd.css';
import React from 'react';
import { I18nextProvider } from 'react-i18next';
......@@ -50,6 +53,20 @@ const providers = [
[APIClientProvider, { apiClient }],
[I18nextProvider, { i18n }],
[AntdConfigProvider, { remoteLocale: true }],
[
RemoteRouteSwitchProvider,
{
components: {
AuthLayout,
AdminLayout,
RouteSchemaComponent,
SigninPage,
SignupPage,
BlockTemplatePage,
BlockTemplateDetails,
},
},
],
SystemSettingsProvider,
[
PluginManagerProvider,
......@@ -59,39 +76,30 @@ const providers = [
DesignableSwitch,
CollectionManagerShortcut,
SystemSettingsShortcut,
SchemaTemplateShortcut,
},
},
],
[SchemaComponentProvider, { components: { Link, NavLink } }],
// RemoteCollectionManagerProvider,
[SchemaInitializerProvider, { initializers: { MenuItemInitializers } }],
AntdSchemaComponentProvider,
ChinaRegionProvider,
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
[
RouteSwitchProvider,
SchemaInitializerProvider,
{
components: {
AuthLayout,
AdminLayout,
RouteSchemaComponent,
SigninPage,
SignupPage,
initializers: {
MenuItemInitializers,
},
},
],
AntdSchemaComponentProvider,
ChinaRegionProvider,
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
];
const App = compose(...providers)(() => {
const { data, loading } = useRequest({
url: 'uiRoutes:getAccessible',
});
if (loading) {
return <Spin />;
}
const routes = useRoutes();
return (
<div>
<RouteSwitch routes={data?.data || []} />
<RouteSwitch routes={routes} />
</div>
);
});
......
......@@ -19,6 +19,7 @@ export * from './route-switch';
export * from './schema-component';
export * from './schema-initializer';
export * from './schema-settings';
export * from './schema-templates';
export * from './settings-form';
export * from './system-settings';
export * from './user';
......
......@@ -279,5 +279,10 @@
"Add card": "添加卡片",
"edit title": "修改标题",
"turn page": "翻页"
"turn page": "翻页",
"Save as template": "保存为模板",
"Block templates": "区块模板",
"Convert reference to duplicate": "模板引用转为复制",
"Template name": "模板名称",
"Block type": "区块类型"
}
import { Spin } from 'antd';
import React from 'react';
import { useRequest } from '../api-client';
import { RouteSwitchContext } from './context';
import { RouteSwitchProviderProps } from './types';
export function RouteSwitchProvider(props: RouteSwitchProviderProps) {
const { children, components } = props;
return <RouteSwitchContext.Provider value={{ components }}>{children}</RouteSwitchContext.Provider>;
const { children, components, routes } = props;
return <RouteSwitchContext.Provider value={{ routes, components }}>{children}</RouteSwitchContext.Provider>;
}
export function RemoteRouteSwitchProvider(props: RouteSwitchProviderProps) {
const { data, loading } = useRequest({
url: 'uiRoutes:getAccessible',
});
if (loading) {
return <Spin />;
}
return <RouteSwitchProvider {...props} routes={data?.data || []} />;
}
......@@ -10,6 +10,7 @@ import {
PluginManager,
RemoteCollectionManagerProvider,
RemoteSchemaComponent,
RemoteSchemaTemplateManagerProvider,
useDocumentTitle,
useRoute,
useSystemSettings
......@@ -94,6 +95,7 @@ const InternalAdminLayout = (props: any) => {
{ component: 'DesignableSwitch', pin: true },
{ component: 'CollectionManagerShortcut', pin: true },
{ component: 'ACLShortcut', pin: true },
{ component: 'SchemaTemplateShortcut', pin: true },
{ component: 'SystemSettingsShortcut' },
]}
/>
......@@ -110,11 +112,13 @@ const InternalAdminLayout = (props: any) => {
export const AdminLayout = (props) => {
return (
<RemoteCollectionManagerProvider>
<CurrentUserProvider>
<InternalAdminLayout {...props} />
</CurrentUserProvider>
</RemoteCollectionManagerProvider>
<RemoteSchemaTemplateManagerProvider>
<RemoteCollectionManagerProvider>
<CurrentUserProvider>
<InternalAdminLayout {...props} />
</CurrentUserProvider>
</RemoteCollectionManagerProvider>
</RemoteSchemaTemplateManagerProvider>
);
};
......
......@@ -3,6 +3,7 @@ import { RouteProps } from './types';
export const RouteSwitchContext = createContext({
components: {},
routes: [],
});
export const RouteContext = createContext<RouteProps>(null);
import { useContext } from 'react';
import get from 'lodash/get';
import { useContext } from 'react';
import { RouteContext, RouteSwitchContext } from './context';
export function useRouteComponent(name?: string) {
......@@ -13,3 +13,8 @@ export function useRouteComponent(name?: string) {
export function useRoute() {
return useContext(RouteContext);
}
export function useRoutes() {
const { routes } = useContext(RouteSwitchContext);
return routes || [];
}
......@@ -23,6 +23,7 @@ export interface RouteProps {
export interface RouteSwitchProviderProps {
components?: any;
children?: any;
routes?: RouteRedirectProps[];
}
export type RouteRedirectProps = RedirectProps | RouteProps;
......
......@@ -4,6 +4,7 @@ import { useCompile, useDesignable } from '../..';
import { useCollection, useResourceActionContext } from '../../../collection-manager';
import { useCollectionFilterOptions } from '../../../collection-manager/action-hooks';
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
import { useSchemaTemplate } from '../../../schema-templates';
export const CalendarDesigner = () => {
const field = useField();
......@@ -13,6 +14,7 @@ export const CalendarDesigner = () => {
const ctx = useResourceActionContext();
const { dn } = useDesignable();
const compile = useCompile();
const template = useSchemaTemplate();
const defaultFilter = fieldSchema?.['x-decorator-props']?.request?.params?.filter || {};
const options = fields?.map((field) => {
return {
......@@ -23,7 +25,7 @@ export const CalendarDesigner = () => {
const calendarSchema = fieldSchema.properties.calendar;
const fieldNames = calendarSchema?.['x-component-props']?.['fieldNames'] || {};
return (
<GeneralSchemaDesigner title={title || name}>
<GeneralSchemaDesigner template={template} title={title || name}>
<SchemaSettings.SelectItem
title={'标题字段'}
value={fieldNames.title}
......@@ -128,6 +130,8 @@ export const CalendarDesigner = () => {
}}
/>
<SchemaSettings.Divider />
<SchemaSettings.Template componentName={'Calendar'} collectionName={name} />
<SchemaSettings.Divider />
<SchemaSettings.Remove
removeParentsIfNoChildren
breakRemoveOn={{
......
......@@ -6,6 +6,8 @@ export const FormDesigner = () => {
const { name, title } = useCollection();
return (
<GeneralSchemaDesigner title={title || name}>
<SchemaSettings.Template componentName={'Form'} collectionName={name} />
<SchemaSettings.Divider />
<SchemaSettings.Remove
removeParentsIfNoChildren
breakRemoveOn={{
......
......@@ -8,6 +8,7 @@ import { useAttach, useComponent } from '../..';
import { useRequest } from '../../../api-client';
import { useCollection } from '../../../collection-manager';
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
import { useSchemaTemplate } from '../../../schema-templates';
type Opts = Options<any, any> & { uid?: string };
......@@ -113,8 +114,11 @@ export const Form: React.FC<FormProps> & { Designer?: any } = observer((props) =
Form.Designer = () => {
const { name, title } = useCollection();
const template = useSchemaTemplate();
return (
<GeneralSchemaDesigner title={title || name}>
<GeneralSchemaDesigner template={template} title={title || name}>
<SchemaSettings.Template componentName={'Form'} collectionName={name} />
<SchemaSettings.Divider />
<SchemaSettings.Remove
removeParentsIfNoChildren
breakRemoveOn={{
......
......@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import { useCollection, useResourceActionContext } from '../../../collection-manager';
import { useCollectionFilterOptions } from '../../../collection-manager/action-hooks';
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
import { useSchemaTemplate } from '../../../schema-templates';
import { useDesignable } from '../../hooks';
export const KanbanDesigner = () => {
......@@ -15,8 +16,9 @@ export const KanbanDesigner = () => {
const { t } = useTranslation();
const { dn } = useDesignable();
const defaultFilter = fieldSchema?.['x-decorator-props']?.request?.params?.filter || {};
const template = useSchemaTemplate();
return (
<GeneralSchemaDesigner title={title || name}>
<GeneralSchemaDesigner template={template} title={title || name}>
<SchemaSettings.ModalItem
title={'设置数据范围'}
schema={
......@@ -49,6 +51,8 @@ export const KanbanDesigner = () => {
}}
/>
<SchemaSettings.Divider />
<SchemaSettings.Template componentName={'Kanban'} collectionName={name} />
<SchemaSettings.Divider />
<SchemaSettings.Remove
removeParentsIfNoChildren
breakRemoveOn={{
......
......@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useCollection, useResourceActionContext } from '../../../collection-manager';
import { useCollectionFilterOptions, useSortFields } from '../../../collection-manager/action-hooks';
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
import { useSchemaTemplate } from '../../../schema-templates';
import { useDesignable } from '../../hooks';
export const TableVoidDesigner = () => {
......@@ -29,8 +30,9 @@ export const TableVoidDesigner = () => {
direction: 'asc',
};
});
const template = useSchemaTemplate();
return (
<GeneralSchemaDesigner title={title || name}>
<GeneralSchemaDesigner template={template} title={title || name}>
<SchemaSettings.SwitchItem
title={t('Enable drag and drop sorting')}
checked={field.decoratorProps.dragSort}
......@@ -193,6 +195,8 @@ export const TableVoidDesigner = () => {
}}
/>
<SchemaSettings.Divider />
<SchemaSettings.Template componentName={'Table'} collectionName={name}/>
<SchemaSettings.Divider />
<SchemaSettings.Remove
removeParentsIfNoChildren
breakRemoveOn={{
......
......@@ -11,6 +11,7 @@ interface CreateDesignableProps {
current: Schema;
api?: APIClient;
refresh?: () => void;
onSuccess?: any;
}
export function createDesignable(options: CreateDesignableProps) {
......@@ -26,6 +27,7 @@ interface InsertAdjacentOptions {
wrap?: (s: ISchema) => ISchema;
removeParentsIfNoChildren?: boolean;
breakRemoveOn?: ISchema | BreakFn;
onSuccess?: any;
}
type BreakFn = (s: ISchema) => boolean;
......@@ -80,7 +82,7 @@ export class Designable {
if (!api) {
return;
}
this.on('insertAdjacent', async ({ current, position, schema, removed }) => {
this.on('insertAdjacent', async ({ onSuccess, current, position, schema, removed }) => {
refresh();
await api.request({
url: `/uiSchemas:insertAdjacent/${current['x-uid']}?position=${position}`,
......@@ -93,6 +95,7 @@ export class Designable {
method: 'post',
});
}
onSuccess?.();
message.success('配置保存成功!', 0.2);
});
this.on('patch', async ({ schema }) => {
......@@ -229,6 +232,19 @@ export class Designable {
this.emit('remove', { removed });
}
removeWithoutEmit(schema?: Schema, options: RemoveOptions = {}) {
const { breakRemoveOn, removeParentsIfNoChildren } = options;
let s = schema || this.current;
let removed = s.parent.removeProperty(s.name);
if (removeParentsIfNoChildren) {
const parent = this.recursiveRemoveIfNoChildren(s.parent, { breakRemoveOn });
if (parent) {
removed = parent;
}
}
return removed;
}
insertBeforeBeginOrAfterEnd(schema: ISchema, options: InsertAdjacentOptions = {}) {
if (!Schema.isSchemaInstance(this.current)) {
return;
......@@ -393,7 +409,7 @@ export class Designable {
if (!Schema.isSchemaInstance(this.current)) {
return;
}
const opts = {};
const opts = { onSuccess: options?.onSuccess };
const { wrap = defaultWrap, breakRemoveOn, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
if (this.parentsIn(schema)) {
......
......@@ -5,7 +5,9 @@ import React, { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { useCollectionManager } from '../../../collection-manager';
import { SchemaComponent, SchemaComponentOptions } from '../../../schema-component';
import { useSchemaTemplateManager } from '../../../schema-templates';
import { SchemaInitializer } from '../../SchemaInitializer';
import { useCollectionDataSourceItems } from '../utils';
const createSchema = (collectionName, { title, start, end }) => {
const schema: ISchema = {
......@@ -102,11 +104,17 @@ export const CalendarBlockInitializer = (props) => {
const { collections, getCollection } = useCollectionManager();
const { t } = useTranslation();
const options = useContext(SchemaOptionsContext);
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
return (
<SchemaInitializer.Item
{...props}
icon={<FormOutlined />}
onClick={async ({ item }) => {
if (item.template) {
const s = await getTemplateSchemaByMode(item);
insert(s);
return;
}
const collection = getCollection(item.name);
const stringFields = collection?.fields
?.filter((field) => field.type === 'string')
......@@ -161,23 +169,10 @@ export const CalendarBlockInitializer = (props) => {
}).open({
initialValues: {},
});
insert(createSchema(item.name, values));
}}
items={[
{
type: 'itemGroup',
title: t('Select data source'),
children: collections
?.filter((item) => !item.inherit)
?.map((item) => {
return {
type: 'item',
name: item.name,
title: item.title,
};
}),
},
]}
items={useCollectionDataSourceItems('Calendar')}
/>
);
};
......@@ -4,6 +4,8 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaInitializer } from '../..';
import { useCollectionManager } from '../../../collection-manager';
import { useSchemaTemplateManager } from '../../../schema-templates';
import { useCollectionDataSourceItems } from '../utils';
const createSchema = (collectionName) => {
const schema: ISchema = {
......@@ -55,28 +57,20 @@ export const FormBlockInitializer = (props) => {
const { insert } = props;
const { collections } = useCollectionManager();
const { t } = useTranslation();
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
return (
<SchemaInitializer.Item
{...props}
icon={<FormOutlined />}
onClick={({ item }) => {
insert(createSchema(item.name));
onClick={async ({ item }) => {
if (item.template) {
const s = await getTemplateSchemaByMode(item);
insert(s);
} else {
insert(createSchema(item.name));
}
}}
items={[
{
type: 'itemGroup',
title: t('Select data source'),
children: collections
?.filter((item) => !item.inherit)
?.map((item) => {
return {
type: 'item',
name: item.name,
title: item.title,
};
}),
},
]}
items={useCollectionDataSourceItems('Form')}
/>
);
};
......@@ -6,7 +6,9 @@ import { useTranslation } from 'react-i18next';
import { useAPIClient } from '../../../api-client';
import { useCollectionManager } from '../../../collection-manager';
import { SchemaComponent, SchemaComponentOptions } from '../../../schema-component';
import { useSchemaTemplateManager } from '../../../schema-templates';
import { SchemaInitializer } from '../../SchemaInitializer';
import { useCollectionDataSourceItems } from '../utils';
const createSchema = (collectionName, { groupField, sortName }) => {
const schema: ISchema = {
......@@ -158,6 +160,7 @@ export const KanbanBlockInitializer = (props) => {
const { insert } = props;
const { collections, getCollection } = useCollectionManager();
const { t } = useTranslation();
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
const options = useContext(SchemaOptionsContext);
const api = useAPIClient();
return (
......@@ -165,6 +168,11 @@ export const KanbanBlockInitializer = (props) => {
{...props}
icon={<FormOutlined />}
onClick={async ({ item }) => {
if (item.template) {
const s = await getTemplateSchemaByMode(item);
insert(s);
return;
}
const collection = getCollection(item.name);
const fields = collection?.fields
?.filter((field) => ['select', 'radioGroup'].includes(field.interface))
......@@ -219,21 +227,7 @@ export const KanbanBlockInitializer = (props) => {
}
insert(createSchema(item.name, { ...values, sortName }));
}}
items={[
{
type: 'itemGroup',
title: t('Select data source'),
children: collections
?.filter((item) => !item.inherit)
?.map((item) => {
return {
type: 'item',
name: item.name,
title: item.title,
};
}),
},
]}
items={useCollectionDataSourceItems('Kanban')}
/>
);
};
import { TableOutlined } from '@ant-design/icons';
import { ISchema } from '@formily/react';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaInitializer } from '../..';
import { useCollectionManager } from '../../../collection-manager';
import { useSchemaTemplateManager } from '../../../schema-templates';
import { useCollectionDataSourceItems } from '../utils';
const createSchema = (collectionName) => {
export const createTableBlockSchema = (collectionName) => {
const schema: ISchema = {
type: 'void',
'x-collection': 'collections',
......@@ -79,30 +79,20 @@ const createSchema = (collectionName) => {
export const TableBlockInitializer = (props) => {
const { insert } = props;
const { collections } = useCollectionManager();
const { t } = useTranslation();
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
return (
<SchemaInitializer.Item
{...props}
icon={<TableOutlined />}
onClick={({ item }) => {
insert(createSchema(item.name));
onClick={async ({ item }) => {
if (item.template) {
const s = await getTemplateSchemaByMode(item);
insert(s);
} else {
insert(createTableBlockSchema(item.name));
}
}}
items={[
{
type: 'itemGroup',
title: t('Select data source'),
children: collections
?.filter((item) => !item.inherit)
?.map((item) => {
return {
type: 'item',
name: item.name,
title: item.title,
};
}),
},
]}
items={useCollectionDataSourceItems('Table')}
/>
);
};
import { ISchema, Schema, useFieldSchema } from '@formily/react';
import { uid } from '@formily/shared';
import { useTranslation } from 'react-i18next';
import { SchemaInitializerItemOptions } from '../';
import { useCollection } from '../../collection-manager';
import { useCollection, useCollectionManager } from '../../collection-manager';
import { useDesignable } from '../../schema-component';
import { useSchemaTemplateManager } from '../../schema-templates';
export const gridRowColWrap = (schema: ISchema) => {
return {
......@@ -203,3 +205,76 @@ export const useCurrentSchema = (action: string, key: string, find = findSchema,
},
};
};
export const useCollectionDataSourceItems = (componentName) => {
const { t } = useTranslation();
const { collections } = useCollectionManager();
const { getTemplatesByCollection } = useSchemaTemplateManager();
return [
{
key: 'tableBlock',
type: 'itemGroup',
title: t('Select data source'),
children: collections
?.filter((item) => !item.inherit)
?.map((item, index) => {
const templates = getTemplatesByCollection(item.name).filter((template) => {
return componentName && template.componentName === componentName;
});
if (!templates.length) {
return {
type: 'item',
name: item.name,
title: item.title,
};
}
return {
key: `${componentName}_table_subMenu_${index}`,
type: 'subMenu',
name: `${item.name}_${index}`,
title: item.title,
children: [
{
type: 'item',
name: item.name,
title: '空白区块',
},
{
type: 'divider',
},
{
key: `${componentName}_table_subMenu_${index}_copy`,
type: 'subMenu',
name: 'copy',
title: '复制模板',
children: templates.map((template) => {
return {
type: 'item',
mode: 'copy',
name: item.name,
template,
title: template.name || '未命名',
};
}),
},
{
key: `${componentName}_table_subMenu_${index}_ref`,
type: 'subMenu',
name: 'ref',
title: '引用模板',
children: templates.map((template) => {
return {
type: 'item',
mode: 'reference',
name: item.name,
template,
title: template.name || '未命名',
};
}),
},
],
};
}),
},
];
};
......@@ -42,76 +42,56 @@ SchemaInitializer.Button = observer((props: SchemaInitializerButtonProps) => {
insertAdjacent(insertPosition, wrap(schema));
}
};
const menu = (
<Menu>
{items?.map((item, indexA) => {
if (item.type === 'divider') {
return <Menu.Divider key={`item-${indexA}`} />;
}
if (item.type === 'item' && item.component) {
const Component = findComponent(item.component);
return (
Component && (
<SchemaInitializerItemContext.Provider
key={`item-${indexA}`}
value={{
index: indexA,
item,
info: item,
insert: insertSchema,
}}
>
<Component
{...item}
item={{
...item,
title: compile(item.title),
}}
insert={insertSchema}
/>
</SchemaInitializerItemContext.Provider>
)
);
}
const renderItems = (items: any) => {
return items?.map((item, indexA) => {
if (item.type === 'divider') {
return <Menu.Divider key={item.key || `item-${indexA}`} />;
}
if (item.type === 'item' && item.component) {
const Component = findComponent(item.component);
return (
item?.children?.length > 0 && (
<Menu.ItemGroup key={`item-group-${indexA}`} title={compile(item.title)}>
{item?.children?.map((child, indexB) => {
if (!child.component) {
return null;
}
const Component = findComponent(child.component);
return (
Component && (
<SchemaInitializerItemContext.Provider
key={`item-${indexB}`}
value={{
index: indexB,
item: child,
info: child,
insert: insertSchema,
}}
>
<Component
{...child}
item={{
...child,
title: compile(child.title),
}}
insert={insertSchema}
/>
</SchemaInitializerItemContext.Provider>
)
);
})}
</Menu.ItemGroup>
Component && (
<SchemaInitializerItemContext.Provider
key={`item-${indexA}`}
value={{
index: indexA,
item,
info: item,
insert: insertSchema,
}}
>
<Component
{...item}
item={{
...item,
title: compile(item.title),
}}
insert={insertSchema}
/>
</SchemaInitializerItemContext.Provider>
)
);
})}
</Menu>
);
}
if (item.type === 'itemGroup') {
return (
<Menu.ItemGroup key={item.key || `item-group-${indexA}`} title={compile(item.title)}>
{renderItems(item.children)}
</Menu.ItemGroup>
);
}
if (item.type === 'subMenu') {
return (
<Menu.SubMenu key={item.key || `item-group-${indexA}`} title={compile(item.title)}>
{renderItems(item.children)}
</Menu.SubMenu>
);
}
});
};
if (!designable) {
const menu = <Menu>{renderItems(items)}</Menu>;
if (!designable && props.designable !== true) {
return null;
}
......@@ -124,15 +104,17 @@ SchemaInitializer.Button = observer((props: SchemaInitializerButtonProps) => {
{...dropdown}
overlay={menu}
>
{component ? component : (
{component ? (
component
) : (
<Button
{...others}
type={'dashed'}
style={{
...style,
borderColor: '#f18b62',
color: '#f18b62',
...style,
}}
{...others}
>
{compile(props.children || props.title)}
</Button>
......@@ -156,16 +138,24 @@ SchemaInitializer.Item = (props: SchemaInitializerItemProps) => {
}
if (item.type === 'itemGroup') {
return (
// @ts-ignore
<Menu.ItemGroup eventKey={`item-group-${indexA}`} key={`item-group-${indexA}`} title={compile(item.title)}>
<Menu.ItemGroup
// @ts-ignore
eventKey={item.key || `item-group-${indexA}`}
key={item.key || `item-group-${indexA}`}
title={compile(item.title)}
>
{renderMenuItem(item.children)}
</Menu.ItemGroup>
);
}
if (item.type === 'subMenu') {
return (
// @ts-ignore
<Menu.SubMenu eventKey={`sub-menu-${indexA}`} key={`sub-menu-${indexA}`} title={compile(item.title)}>
<Menu.SubMenu
// @ts-ignore
eventKey={item.key || `sub-menu-${indexA}`}
key={item.key || `sub-menu-${indexA}`}
title={compile(item.title)}
>
{renderMenuItem(item.children)}
</Menu.SubMenu>
);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment