fix(InternalAdminLayout): fix the issue of missing left sidebar menu

This commit is contained in:
Zeke Zhang 2024-11-03 19:13:52 +08:00
parent 023aa0ce4f
commit 7efab73f0d
2 changed files with 127 additions and 117 deletions

View File

@ -40,6 +40,14 @@ MatchAdminContext.displayName = 'MatchAdminContext';
const MatchAdminNameContext = React.createContext<PathMatch<string> | null>(null); const MatchAdminNameContext = React.createContext<PathMatch<string> | null>(null);
MatchAdminNameContext.displayName = 'MatchAdminNameContext'; MatchAdminNameContext.displayName = 'MatchAdminNameContext';
const IsInSettingsPageContext = React.createContext<boolean>(false);
IsInSettingsPageContext.displayName = 'IsInSettingsPageContext';
const IsInSettingsPageProvider: FC = ({ children }) => {
const isInSettingsPage = useLocation().pathname.includes('/settings');
return <IsInSettingsPageContext.Provider value={isInSettingsPage}>{children}</IsInSettingsPageContext.Provider>;
};
const MatchAdminProvider: FC = ({ children }) => { const MatchAdminProvider: FC = ({ children }) => {
const matchAdmin = useMatch('/admin'); const matchAdmin = useMatch('/admin');
return <MatchAdminContext.Provider value={matchAdmin}>{children}</MatchAdminContext.Provider>; return <MatchAdminContext.Provider value={matchAdmin}>{children}</MatchAdminContext.Provider>;
@ -56,8 +64,8 @@ const IsAdminPageProvider: FC = ({ children }) => {
return <IsAdminPageContext.Provider value={isAdminPage}>{children}</IsAdminPageContext.Provider>; return <IsAdminPageContext.Provider value={isAdminPage}>{children}</IsAdminPageContext.Provider>;
}; };
const CurrentPageUidProvider: FC = ({ children }) => { export const CurrentPageUidProvider: FC = ({ children }) => {
const params = useParams<any>(); const params = useParams();
return <CurrentPageUidContext.Provider value={params.name}>{children}</CurrentPageUidContext.Provider>; return <CurrentPageUidContext.Provider value={params.name}>{children}</CurrentPageUidContext.Provider>;
}; };
@ -141,17 +149,21 @@ export const useMatchAdminName = () => {
return React.useContext(MatchAdminNameContext); return React.useContext(MatchAdminNameContext);
}; };
export const useIsInSettingsPage = () => {
return React.useContext(IsInSettingsPageContext);
};
export const CustomRouterContextProvider: FC = ({ children }) => { export const CustomRouterContextProvider: FC = ({ children }) => {
return ( return (
<NavigateNoUpdateProvider> <NavigateNoUpdateProvider>
<LocationNoUpdateProvider> <LocationNoUpdateProvider>
<IsAdminPageProvider> <IsAdminPageProvider>
<LocationSearchProvider> <LocationSearchProvider>
<CurrentPageUidProvider> <MatchAdminProvider>
<MatchAdminProvider> <MatchAdminNameProvider>
<MatchAdminNameProvider>{children}</MatchAdminNameProvider> <IsInSettingsPageProvider>{children}</IsInSettingsPageProvider>
</MatchAdminProvider> </MatchAdminNameProvider>
</CurrentPageUidProvider> </MatchAdminProvider>
</LocationSearchProvider> </LocationSearchProvider>
</IsAdminPageProvider> </IsAdminPageProvider>
</LocationNoUpdateProvider> </LocationNoUpdateProvider>

View File

@ -12,7 +12,7 @@ import { useSessionStorageState } from 'ahooks';
import { App, ConfigProvider, Divider, Layout } from 'antd'; import { App, ConfigProvider, Divider, Layout } from 'antd';
import { createGlobalStyle } from 'antd-style'; import { createGlobalStyle } from 'antd-style';
import React, { FC, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import React, { FC, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { Link, Outlet, useParams } from 'react-router-dom'; import { Link, Outlet } from 'react-router-dom';
import { import {
ACLRolesCheckProvider, ACLRolesCheckProvider,
CurrentAppInfoProvider, CurrentAppInfoProvider,
@ -34,8 +34,9 @@ import {
useToken, useToken,
} from '../../../'; } from '../../../';
import { import {
CurrentPageUidProvider,
useCurrentPageUid, useCurrentPageUid,
useLocationNoUpdate, useIsInSettingsPage,
useMatchAdmin, useMatchAdmin,
useMatchAdminName, useMatchAdminName,
useNavigateNoUpdate, useNavigateNoUpdate,
@ -86,9 +87,9 @@ const MenuEditor = (props) => {
const [, setHasNotice] = useSessionStorageState('plugin-notice', { defaultValue: false }); const [, setHasNotice] = useSessionStorageState('plugin-notice', { defaultValue: false });
const { t } = useMenuTranslation(); const { t } = useMenuTranslation();
const { setTitle: _setTitle } = useDocumentTitle(); const { setTitle: _setTitle } = useDocumentTitle();
const setTitle = useCallback((title) => _setTitle(t(title)), []); const setTitle = useCallback((title) => _setTitle(t(title)), [_setTitle, t]);
const navigate = useNavigateNoUpdate(); const navigate = useNavigateNoUpdate();
const location = useLocationNoUpdate(); const isInSettingsPage = useIsInSettingsPage();
const isMatchAdmin = useMatchAdmin(); const isMatchAdmin = useMatchAdmin();
const isMatchAdminName = useMatchAdminName(); const isMatchAdminName = useMatchAdminName();
const currentPageUid = useCurrentPageUid(); const currentPageUid = useCurrentPageUid();
@ -97,12 +98,15 @@ const MenuEditor = (props) => {
const ctx = useACLRoleContext(); const ctx = useACLRoleContext();
const [current, setCurrent] = useState(null); const [current, setCurrent] = useState(null);
const onSelect = useCallback(({ item }: { item; key; keyPath; domEvent }) => { const onSelect = useCallback(
const schema = item.props.schema; ({ item }: { item; key; keyPath; domEvent }) => {
setTitle(schema.title); const schema = item.props.schema;
setCurrent(schema); setTitle(schema.title);
navigate(`/admin/${schema['x-uid']}`); setCurrent(schema);
}, []); navigate(`/admin/${schema['x-uid']}`);
},
[navigate, setTitle],
);
const { render } = useAppSpin(); const { render } = useAppSpin();
const adminSchemaUid = useAdminSchemaUid(); const adminSchemaUid = useAdminSchemaUid();
const { data, loading } = useRequest<{ const { data, loading } = useRequest<{
@ -155,14 +159,13 @@ const MenuEditor = (props) => {
Object.values(properties).find( Object.values(properties).find(
(item) => item['x-uid'] === currentPageUid && item['x-component'] === 'Menu.Item', (item) => item['x-uid'] === currentPageUid && item['x-component'] === 'Menu.Item',
); );
const isSettingPage = location?.pathname.includes('/settings'); if (pageType || isInSettingsPage) {
if (pageType || isSettingPage) {
sideMenuRef.current.style.display = 'none'; sideMenuRef.current.style.display = 'none';
} else { } else {
sideMenuRef.current.style.display = 'block'; sideMenuRef.current.style.display = 'block';
} }
} }
}, [data?.data, currentPageUid, sideMenuRef, location?.pathname]); }, [current?.root?.properties, currentPageUid, data?.data?.properties, isInSettingsPage, sideMenuRef]);
const schema = useMemo(() => { const schema = useMemo(() => {
const s = filterByACL(data?.data, ctx); const s = filterByACL(data?.data, ctx);
@ -221,7 +224,7 @@ const MenuEditor = (props) => {
const scope = useMemo(() => { const scope = useMemo(() => {
return { useMenuProps, onSelect, sideMenuRef, defaultSelectedUid: currentPageUid }; return { useMenuProps, onSelect, sideMenuRef, defaultSelectedUid: currentPageUid };
}, []); }, [currentPageUid, onSelect, sideMenuRef]);
if (loading) { if (loading) {
return render(); return render();
@ -322,8 +325,8 @@ const InternalAdminSideBar: FC<{ pageUid: string; sideMenuRef: any }> = memo((pr
InternalAdminSideBar.displayName = 'InternalAdminSideBar'; InternalAdminSideBar.displayName = 'InternalAdminSideBar';
const AdminSideBar = ({ sideMenuRef }) => { const AdminSideBar = ({ sideMenuRef }) => {
const params = useParams<any>(); const currentPageUid = useCurrentPageUid();
return <InternalAdminSideBar pageUid={params.name} sideMenuRef={sideMenuRef} />; return <InternalAdminSideBar pageUid={currentPageUid} sideMenuRef={sideMenuRef} />;
}; };
export const AdminDynamicPage = () => { export const AdminDynamicPage = () => {
@ -357,6 +360,60 @@ const layoutContentHeaderClass = css`
pointer-events: none; pointer-events: none;
`; `;
const style1: any = {
position: 'relative',
width: '100%',
height: '100%',
display: 'flex',
};
const style2: any = {
position: 'relative',
zIndex: 1,
flex: '1 1 auto',
display: 'flex',
height: '100%',
};
const className1 = css`
width: 200px;
display: inline-flex;
flex-shrink: 0;
color: #fff;
padding: 0;
align-items: center;
`;
const className2 = css`
padding: 0 16px;
object-fit: contain;
width: 100%;
height: 100%;
`;
const className3 = css`
padding: 0 16px;
width: 100%;
height: 100%;
font-weight: 500;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const className4 = css`
flex: 1 1 auto;
width: 0;
`;
const className5 = css`
position: relative;
flex-shrink: 0;
height: 100%;
z-index: 10;
`;
const theme = {
token: {
colorSplit: 'rgba(255, 255, 255, 0.1)',
},
};
export const InternalAdminLayout = () => { export const InternalAdminLayout = () => {
const result = useSystemSettings(); const result = useSystemSettings();
const { token } = useToken(); const { token } = useToken();
@ -404,107 +461,48 @@ export const InternalAdminLayout = () => {
token.colorBgHeader, token.colorBgHeader,
token.colorTextHeaderMenu, token.colorTextHeaderMenu,
]); ]);
const fontSizeStyle = useMemo(() => ({ fontSize: token.fontSizeHeading3 }), [token.fontSizeHeading3]);
return ( return (
<Layout> <Layout>
<GlobalStyleForAdminLayout /> <GlobalStyleForAdminLayout />
<Layout.Header className={layoutHeaderCss}> <CurrentPageUidProvider>
<div <Layout.Header className={layoutHeaderCss}>
style={{ <div style={style1}>
position: 'relative', <div style={style2}>
width: '100%', <div className={className1}>
height: '100%', {result?.data?.data?.logo?.url ? (
display: 'flex', <img className={className2} src={result?.data?.data?.logo?.url} />
}} ) : (
> <span style={fontSizeStyle} className={className3}>
<div {result?.data?.data?.title}
style={{ </span>
position: 'relative', )}
zIndex: 1, </div>
flex: '1 1 auto', <div className={className4}>
display: 'flex', <SetThemeOfHeaderSubmenu>
height: '100%', <MenuEditor sideMenuRef={sideMenuRef} />
}} </SetThemeOfHeaderSubmenu>
> </div>
<div
className={css`
width: 200px;
display: inline-flex;
flex-shrink: 0;
color: #fff;
padding: 0;
align-items: center;
`}
>
{result?.data?.data?.logo?.url ? (
<img
className={css`
padding: 0 16px;
object-fit: contain;
width: 100%;
height: 100%;
`}
src={result?.data?.data?.logo?.url}
/>
) : (
<span
style={{ fontSize: token.fontSizeHeading3 }}
className={css`
padding: 0 16px;
width: 100%;
height: 100%;
font-weight: 500;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`}
>
{result?.data?.data?.title}
</span>
)}
</div> </div>
<div <div className={className5}>
className={css` <PinnedPluginList />
flex: 1 1 auto; <ConfigProvider theme={theme}>
width: 0; <Divider type="vertical" />
`} </ConfigProvider>
> <Help />
<SetThemeOfHeaderSubmenu> <CurrentUser />
<MenuEditor sideMenuRef={sideMenuRef} />
</SetThemeOfHeaderSubmenu>
</div> </div>
</div> </div>
<div </Layout.Header>
className={css` <AdminSideBar sideMenuRef={sideMenuRef} />
position: relative; {/* Use the "nb-subpages-slot-without-header-and-side" class name to locate the position of the subpages */}
flex-shrink: 0; <Layout.Content className={`${layoutContentClass} nb-subpages-slot-without-header-and-side`}>
height: 100%; <header className={layoutContentHeaderClass}></header>
z-index: 10; <Outlet />
`} {/* {service.contentLoading ? render() : <Outlet />} */}
> </Layout.Content>
<PinnedPluginList /> </CurrentPageUidProvider>
<ConfigProvider
theme={{
token: {
colorSplit: 'rgba(255, 255, 255, 0.1)',
},
}}
>
<Divider type="vertical" />
</ConfigProvider>
<Help />
<CurrentUser />
</div>
</div>
</Layout.Header>
<AdminSideBar sideMenuRef={sideMenuRef} />
{/* Use the "nb-subpages-slot-without-header-and-side" class name to locate the position of the subpages */}
<Layout.Content className={`${layoutContentClass} nb-subpages-slot-without-header-and-side`}>
<header className={layoutContentHeaderClass}></header>
<Outlet />
{/* {service.contentLoading ? render() : <Outlet />} */}
</Layout.Content>
</Layout> </Layout>
); );
}; };