fix: the left menu does not collapse when switching routes

This commit is contained in:
chenos 2022-04-24 16:05:08 +08:00
parent 85882f7c7a
commit 4f8cf13d1d
2 changed files with 92 additions and 50 deletions

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
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 {
ACLAllowConfigure,
@ -11,10 +11,11 @@ import {
findMenuItem,
PluginManager,
RemoteCollectionManagerProvider,
RemoteSchemaComponent,
RemoteSchemaTemplateManagerProvider,
SchemaComponent,
useACLRoleContext,
useDocumentTitle,
useRequest,
useRoute,
useSystemSettings
} from '../../../';
@ -27,6 +28,9 @@ const filterByACL = (schema, options) => {
return schema;
}
const filterSchema = (s) => {
if (!s) {
return;
}
for (const key in s.properties) {
if (Object.prototype.hasOwnProperty.call(s.properties, key)) {
const element = s.properties[key];
@ -40,23 +44,74 @@ const filterByACL = (schema, options) => {
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 route = useRoute();
const history = useHistory();
const match = useRouteMatch<any>();
const { setTitle } = useDocumentTitle();
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 { service } = useCollectionManager();
return (
@ -91,40 +146,7 @@ const InternalAdminLayout = (props: any) => {
width: 'calc(100% - 590px)',
}}
>
<RemoteSchemaComponent
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']}`);
}
}}
/>
<MenuEditor sideMenuRef={sideMenuRef} />
</div>
</div>
<div style={{ position: 'absolute', top: 0, right: 0 }}>

View File

@ -13,6 +13,7 @@ import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { createDesignable, DndContext, SortableItem, useDesignable, useDesigner } from '../..';
import { Icon, useAPIClient, useSchemaInitializer } from '../../../';
import { useProps } from '../../hooks/useProps';
import { MenuDesigner } from './Menu.Designer';
import { findKeysByUid, findMenuItem } from './util';
@ -139,12 +140,13 @@ export const Menu: ComposedMenu = observer((props) => {
let {
onSelect,
mode,
selectedUid,
defaultSelectedUid,
sideMenuRefScopeKey,
defaultSelectedKeys: dSelectedKeys,
defaultOpenKeys: dOpenKeys,
...others
} = props;
} = useProps(props);
const { t } = useTranslation();
const Designer = useDesigner();
const schema = useFieldSchema();
@ -178,6 +180,24 @@ export const Menu: ComposedMenu = observer((props) => {
}
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(() => {
if (['inline', 'mix'].includes(mode)) {
setDefaultOpenKeys(defaultSelectedKeys);
@ -244,8 +264,8 @@ export const Menu: ComposedMenu = observer((props) => {
}
}}
mode={mode === 'mix' ? 'horizontal' : mode}
defaultOpenKeys={defaultOpenKeys}
defaultSelectedKeys={defaultSelectedKeys}
openKeys={defaultOpenKeys}
selectedKeys={defaultSelectedKeys}
>
{designable && (
<AntdMenu.Item disabled style={{ padding: '0 8px', order: 9999 }}>