fix: the left menu does not collapse when switching routes
This commit is contained in:
parent
85882f7c7a
commit
4f8cf13d1d
@ -1,6 +1,6 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { Layout, Spin } from 'antd';
|
import { Layout, Spin } from 'antd';
|
||||||
import React, { useRef, useState } from 'react';
|
import React, { createContext, useContext, useMemo, useRef } from 'react';
|
||||||
import { useHistory, useRouteMatch } from 'react-router-dom';
|
import { useHistory, useRouteMatch } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
ACLAllowConfigure,
|
ACLAllowConfigure,
|
||||||
@ -11,10 +11,11 @@ import {
|
|||||||
findMenuItem,
|
findMenuItem,
|
||||||
PluginManager,
|
PluginManager,
|
||||||
RemoteCollectionManagerProvider,
|
RemoteCollectionManagerProvider,
|
||||||
RemoteSchemaComponent,
|
|
||||||
RemoteSchemaTemplateManagerProvider,
|
RemoteSchemaTemplateManagerProvider,
|
||||||
|
SchemaComponent,
|
||||||
useACLRoleContext,
|
useACLRoleContext,
|
||||||
useDocumentTitle,
|
useDocumentTitle,
|
||||||
|
useRequest,
|
||||||
useRoute,
|
useRoute,
|
||||||
useSystemSettings
|
useSystemSettings
|
||||||
} from '../../../';
|
} from '../../../';
|
||||||
@ -27,6 +28,9 @@ const filterByACL = (schema, options) => {
|
|||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
const filterSchema = (s) => {
|
const filterSchema = (s) => {
|
||||||
|
if (!s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (const key in s.properties) {
|
for (const key in s.properties) {
|
||||||
if (Object.prototype.hasOwnProperty.call(s.properties, key)) {
|
if (Object.prototype.hasOwnProperty.call(s.properties, key)) {
|
||||||
const element = s.properties[key];
|
const element = s.properties[key];
|
||||||
@ -40,23 +44,74 @@ const filterByACL = (schema, options) => {
|
|||||||
return schema;
|
return schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SchemaIdContext = createContext(null);
|
||||||
|
const useMenuProps = () => {
|
||||||
|
const defaultSelectedUid = useContext(SchemaIdContext);
|
||||||
|
return {
|
||||||
|
selectedUid: defaultSelectedUid,
|
||||||
|
defaultSelectedUid,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const MenuEditor = (props) => {
|
||||||
|
const { setTitle } = useDocumentTitle();
|
||||||
|
const history = useHistory();
|
||||||
|
const match = useRouteMatch<any>();
|
||||||
|
const defaultSelectedUid = match.params.name;
|
||||||
|
const { sideMenuRef } = props;
|
||||||
|
const ctx = useACLRoleContext();
|
||||||
|
const route = useRoute();
|
||||||
|
const onSelect = ({ item }) => {
|
||||||
|
const schema = item.props.schema;
|
||||||
|
setTitle(schema.title);
|
||||||
|
history.push(`/admin/${schema['x-uid']}`);
|
||||||
|
};
|
||||||
|
const { data, loading } = useRequest(
|
||||||
|
{
|
||||||
|
url: `/uiSchemas:getJsonSchema/${route.uiSchemaUid}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refreshDeps: [route.uiSchemaUid],
|
||||||
|
onSuccess(data) {
|
||||||
|
const schema = filterByACL(data?.data, ctx);
|
||||||
|
if (defaultSelectedUid) {
|
||||||
|
const s = findByUid(schema, defaultSelectedUid);
|
||||||
|
if (s) {
|
||||||
|
setTitle(s.title);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const s = findMenuItem(schema);
|
||||||
|
if (s) {
|
||||||
|
history.push(`/admin/${s['x-uid']}`);
|
||||||
|
setTitle(s.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const schema = useMemo(() => {
|
||||||
|
const s = filterByACL(data?.data, ctx);
|
||||||
|
if (s?.['x-component-props']) {
|
||||||
|
s['x-component-props']['useProps'] = useMenuProps;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}, [data?.data]);
|
||||||
|
if (loading) {
|
||||||
|
return <Spin />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<SchemaIdContext.Provider value={defaultSelectedUid}>
|
||||||
|
<SchemaComponent memoized scope={{ useMenuProps, onSelect, sideMenuRef, defaultSelectedUid }} schema={schema} />
|
||||||
|
</SchemaIdContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const InternalAdminLayout = (props: any) => {
|
const InternalAdminLayout = (props: any) => {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const match = useRouteMatch<any>();
|
const match = useRouteMatch<any>();
|
||||||
const { setTitle } = useDocumentTitle();
|
const { setTitle } = useDocumentTitle();
|
||||||
const sideMenuRef = useRef();
|
const sideMenuRef = useRef();
|
||||||
const defaultSelectedUid = match.params.name;
|
|
||||||
const [schema, setSchema] = useState({});
|
|
||||||
const ctx = useACLRoleContext();
|
|
||||||
const onSelect = ({ item }) => {
|
|
||||||
const schema = item.props.schema;
|
|
||||||
console.log('onSelect', schema);
|
|
||||||
setSchema(schema);
|
|
||||||
setTitle(schema.title);
|
|
||||||
history.push(`/admin/${schema['x-uid']}`);
|
|
||||||
};
|
|
||||||
const [hidden, setHidden] = useState(false);
|
|
||||||
const result = useSystemSettings();
|
const result = useSystemSettings();
|
||||||
const { service } = useCollectionManager();
|
const { service } = useCollectionManager();
|
||||||
return (
|
return (
|
||||||
@ -91,40 +146,7 @@ const InternalAdminLayout = (props: any) => {
|
|||||||
width: 'calc(100% - 590px)',
|
width: 'calc(100% - 590px)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RemoteSchemaComponent
|
<MenuEditor sideMenuRef={sideMenuRef} />
|
||||||
hidden={hidden}
|
|
||||||
uid={route.uiSchemaUid}
|
|
||||||
scope={{ onSelect, sideMenuRef, defaultSelectedUid }}
|
|
||||||
schemaTransform={(data) => {
|
|
||||||
if (!data) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
data['x-component-props'] = data['x-component-props'] || {};
|
|
||||||
data['x-component-props']['defaultSelectedUid'] = defaultSelectedUid;
|
|
||||||
return filterByACL(data, ctx);
|
|
||||||
}}
|
|
||||||
onSuccess={(data) => {
|
|
||||||
if (defaultSelectedUid && defaultSelectedUid.includes('/')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const schema = filterByACL(data?.data, ctx);
|
|
||||||
if (defaultSelectedUid) {
|
|
||||||
const s = findByUid(schema, defaultSelectedUid);
|
|
||||||
if (s) {
|
|
||||||
setTitle(s.title);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setHidden(true);
|
|
||||||
setTimeout(() => setHidden(false), 11);
|
|
||||||
const s = findMenuItem(schema);
|
|
||||||
if (s) {
|
|
||||||
setSchema(s);
|
|
||||||
setTitle(s.title);
|
|
||||||
history.push(`/admin/${s['x-uid']}`);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ position: 'absolute', top: 0, right: 0 }}>
|
<div style={{ position: 'absolute', top: 0, right: 0 }}>
|
||||||
|
@ -13,6 +13,7 @@ import { createPortal } from 'react-dom';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { createDesignable, DndContext, SortableItem, useDesignable, useDesigner } from '../..';
|
import { createDesignable, DndContext, SortableItem, useDesignable, useDesigner } from '../..';
|
||||||
import { Icon, useAPIClient, useSchemaInitializer } from '../../../';
|
import { Icon, useAPIClient, useSchemaInitializer } from '../../../';
|
||||||
|
import { useProps } from '../../hooks/useProps';
|
||||||
import { MenuDesigner } from './Menu.Designer';
|
import { MenuDesigner } from './Menu.Designer';
|
||||||
import { findKeysByUid, findMenuItem } from './util';
|
import { findKeysByUid, findMenuItem } from './util';
|
||||||
|
|
||||||
@ -139,12 +140,13 @@ export const Menu: ComposedMenu = observer((props) => {
|
|||||||
let {
|
let {
|
||||||
onSelect,
|
onSelect,
|
||||||
mode,
|
mode,
|
||||||
|
selectedUid,
|
||||||
defaultSelectedUid,
|
defaultSelectedUid,
|
||||||
sideMenuRefScopeKey,
|
sideMenuRefScopeKey,
|
||||||
defaultSelectedKeys: dSelectedKeys,
|
defaultSelectedKeys: dSelectedKeys,
|
||||||
defaultOpenKeys: dOpenKeys,
|
defaultOpenKeys: dOpenKeys,
|
||||||
...others
|
...others
|
||||||
} = props;
|
} = useProps(props);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const Designer = useDesigner();
|
const Designer = useDesigner();
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
@ -178,6 +180,24 @@ export const Menu: ComposedMenu = observer((props) => {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
useEffect(() => {
|
||||||
|
const keys = findKeysByUid(schema, selectedUid);
|
||||||
|
setDefaultSelectedKeys(keys);
|
||||||
|
if (['inline', 'mix'].includes(mode)) {
|
||||||
|
setDefaultOpenKeys(dOpenKeys || keys);
|
||||||
|
}
|
||||||
|
const key = keys?.[0] || null;
|
||||||
|
if (mode === 'mix') {
|
||||||
|
if (key) {
|
||||||
|
const s = schema.properties?.[key];
|
||||||
|
if (s['x-component'] === 'Menu.SubMenu') {
|
||||||
|
setSideMenuSchema(s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSideMenuSchema(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedUid]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (['inline', 'mix'].includes(mode)) {
|
if (['inline', 'mix'].includes(mode)) {
|
||||||
setDefaultOpenKeys(defaultSelectedKeys);
|
setDefaultOpenKeys(defaultSelectedKeys);
|
||||||
@ -244,8 +264,8 @@ export const Menu: ComposedMenu = observer((props) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
mode={mode === 'mix' ? 'horizontal' : mode}
|
mode={mode === 'mix' ? 'horizontal' : mode}
|
||||||
defaultOpenKeys={defaultOpenKeys}
|
openKeys={defaultOpenKeys}
|
||||||
defaultSelectedKeys={defaultSelectedKeys}
|
selectedKeys={defaultSelectedKeys}
|
||||||
>
|
>
|
||||||
{designable && (
|
{designable && (
|
||||||
<AntdMenu.Item disabled style={{ padding: '0 8px', order: 9999 }}>
|
<AntdMenu.Item disabled style={{ padding: '0 8px', order: 9999 }}>
|
||||||
|
Loading…
Reference in New Issue
Block a user