mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-28 05:31:58 +08:00
style(FE/layout): Fix app scroll behaviour and sidenav footer section inconsistency (#3426)
This commit is contained in:
parent
32a55f3c4f
commit
9aa72f847c
@ -25,7 +25,7 @@ import {
|
|||||||
} from 'types/actions/app';
|
} from 'types/actions/app';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
import { ChildrenContainer, Layout } from './styles';
|
import { ChildrenContainer, Layout, LayoutContent } from './styles';
|
||||||
import { getRouteKey } from './utils';
|
import { getRouteKey } from './utils';
|
||||||
|
|
||||||
function AppLayout(props: AppLayoutProps): JSX.Element {
|
function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
@ -240,12 +240,12 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||||||
{isToDisplayLayout && <Header />}
|
{isToDisplayLayout && <Header />}
|
||||||
<Layout>
|
<Layout>
|
||||||
{isToDisplayLayout && <SideNav />}
|
{isToDisplayLayout && <SideNav />}
|
||||||
<Layout.Content>
|
<LayoutContent>
|
||||||
<ChildrenContainer>
|
<ChildrenContainer>
|
||||||
{isToDisplayLayout && <TopNav />}
|
{isToDisplayLayout && <TopNav />}
|
||||||
{children}
|
{children}
|
||||||
</ChildrenContainer>
|
</ChildrenContainer>
|
||||||
</Layout.Content>
|
</LayoutContent>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
@ -7,9 +7,14 @@ export const Layout = styled(LayoutComponent)`
|
|||||||
position: relative;
|
position: relative;
|
||||||
min-height: calc(100vh - 4rem);
|
min-height: calc(100vh - 4rem);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const LayoutContent = styled(LayoutComponent.Content)`
|
||||||
|
overflow-y: auto;
|
||||||
|
`;
|
||||||
|
|
||||||
export const ChildrenContainer = styled.div`
|
export const ChildrenContainer = styled.div`
|
||||||
margin: 0 1rem;
|
margin: 0 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,33 +1,30 @@
|
|||||||
import { CheckCircleTwoTone, WarningOutlined } from '@ant-design/icons';
|
import { CheckCircleTwoTone, WarningOutlined } from '@ant-design/icons';
|
||||||
import { Menu, MenuProps } from 'antd';
|
import { MenuProps } from 'antd';
|
||||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||||
import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
|
import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import {
|
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
ReactNode,
|
|
||||||
useCallback,
|
|
||||||
useLayoutEffect,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { SideBarCollapse } from 'store/actions/app';
|
import { sideBarCollapse } from 'store/actions/app';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
import { routeConfig, styles } from './config';
|
import { routeConfig, styles } from './config';
|
||||||
import { getQueryString } from './helper';
|
import { getQueryString } from './helper';
|
||||||
import menus from './menuItems';
|
import menuItems from './menuItems';
|
||||||
|
import { MenuItem, SecondaryMenuItemKey } from './sideNav.types';
|
||||||
|
import { getActiveMenuKeyFromPath } from './sideNav.utils';
|
||||||
import Slack from './Slack';
|
import Slack from './Slack';
|
||||||
import {
|
import {
|
||||||
|
MenuLabelContainer,
|
||||||
RedDot,
|
RedDot,
|
||||||
Sider,
|
Sider,
|
||||||
SlackButton,
|
StyledPrimaryMenu,
|
||||||
SlackMenuItemContainer,
|
StyledSecondaryMenu,
|
||||||
VersionContainer,
|
StyledText,
|
||||||
} from './styles';
|
} from './styles';
|
||||||
|
|
||||||
function SideNav(): JSX.Element {
|
function SideNav(): JSX.Element {
|
||||||
@ -49,7 +46,7 @@ function SideNav(): JSX.Element {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
dispatch(SideBarCollapse(collapsed));
|
dispatch(sideBarCollapse(collapsed));
|
||||||
}, [collapsed, dispatch]);
|
}, [collapsed, dispatch]);
|
||||||
|
|
||||||
const onClickHandler = useCallback(
|
const onClickHandler = useCallback(
|
||||||
@ -80,90 +77,56 @@ function SideNav(): JSX.Element {
|
|||||||
|
|
||||||
const isNotCurrentVersion = currentVersion !== latestVersion;
|
const isNotCurrentVersion = currentVersion !== latestVersion;
|
||||||
|
|
||||||
const sidebar: SidebarItem[] = [
|
const secondaryMenuItems: MenuItem[] = [
|
||||||
{
|
{
|
||||||
onClick: onClickSlackHandler,
|
key: SecondaryMenuItemKey.Version,
|
||||||
icon: <Slack />,
|
|
||||||
text: <SlackButton>Support</SlackButton>,
|
|
||||||
key: 'slack',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
onClick: onClickVersionHandler,
|
|
||||||
key: 'version',
|
|
||||||
icon: isNotCurrentVersion ? (
|
icon: isNotCurrentVersion ? (
|
||||||
<WarningOutlined style={{ color: '#E87040' }} />
|
<WarningOutlined style={{ color: '#E87040' }} />
|
||||||
) : (
|
) : (
|
||||||
<CheckCircleTwoTone twoToneColor={['#D5F2BB', '#1f1f1f']} />
|
<CheckCircleTwoTone twoToneColor={['#D5F2BB', '#1f1f1f']} />
|
||||||
),
|
),
|
||||||
text: (
|
label: (
|
||||||
<VersionContainer>
|
<MenuLabelContainer>
|
||||||
{!isCurrentVersionError ? (
|
<StyledText ellipsis>
|
||||||
<SlackButton>{currentVersion}</SlackButton>
|
{!isCurrentVersionError ? currentVersion : t('n_a')}
|
||||||
) : (
|
</StyledText>
|
||||||
<SlackButton>{t('n_a')}</SlackButton>
|
|
||||||
)}
|
|
||||||
{isNotCurrentVersion && <RedDot />}
|
{isNotCurrentVersion && <RedDot />}
|
||||||
</VersionContainer>
|
</MenuLabelContainer>
|
||||||
),
|
),
|
||||||
|
onClick: onClickVersionHandler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: SecondaryMenuItemKey.Slack,
|
||||||
|
icon: <Slack />,
|
||||||
|
label: <StyledText>Support</StyledText>,
|
||||||
|
onClick: onClickSlackHandler,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const currentMenu = useMemo(() => {
|
const activeMenuKey = useMemo(() => getActiveMenuKeyFromPath(pathname), [
|
||||||
const routeKeys = Object.keys(ROUTES) as (keyof typeof ROUTES)[];
|
pathname,
|
||||||
const currentRouteKey = routeKeys.find((key) => {
|
]);
|
||||||
const route = ROUTES[key];
|
|
||||||
return pathname === route;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!currentRouteKey) return null;
|
|
||||||
|
|
||||||
return ROUTES[currentRouteKey];
|
|
||||||
}, [pathname]);
|
|
||||||
|
|
||||||
const sidebarItems = (props: SidebarItem, index: number): SidebarItem => ({
|
|
||||||
key: `${index}`,
|
|
||||||
icon: props.icon,
|
|
||||||
onClick: props.onClick,
|
|
||||||
label: props.text,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse} width={200}>
|
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse} width={200}>
|
||||||
<Menu
|
<StyledPrimaryMenu
|
||||||
theme="dark"
|
theme="dark"
|
||||||
defaultSelectedKeys={[ROUTES.APPLICATION]}
|
defaultSelectedKeys={[ROUTES.APPLICATION]}
|
||||||
selectedKeys={currentMenu ? [currentMenu] : []}
|
selectedKeys={activeMenuKey ? [activeMenuKey] : []}
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
style={styles}
|
style={styles}
|
||||||
items={menus}
|
items={menuItems}
|
||||||
onClick={onClickMenuHandler}
|
onClick={onClickMenuHandler}
|
||||||
/>
|
/>
|
||||||
{sidebar.map((props, index) => (
|
<StyledSecondaryMenu
|
||||||
<SlackMenuItemContainer
|
theme="dark"
|
||||||
index={index + 1}
|
selectedKeys={activeMenuKey ? [activeMenuKey] : []}
|
||||||
key={`${index + 1}`}
|
mode="vertical"
|
||||||
collapsed={collapsed}
|
style={styles}
|
||||||
>
|
items={secondaryMenuItems}
|
||||||
<Menu
|
/>
|
||||||
theme="dark"
|
|
||||||
defaultSelectedKeys={[ROUTES.APPLICATION]}
|
|
||||||
selectedKeys={currentMenu ? [currentMenu] : []}
|
|
||||||
mode="inline"
|
|
||||||
style={styles}
|
|
||||||
items={[sidebarItems(props, index)]}
|
|
||||||
/>
|
|
||||||
</SlackMenuItemContainer>
|
|
||||||
))}
|
|
||||||
</Sider>
|
</Sider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SidebarItem {
|
|
||||||
onClick: VoidFunction;
|
|
||||||
icon?: ReactNode;
|
|
||||||
text?: ReactNode;
|
|
||||||
key: string;
|
|
||||||
label?: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SideNav;
|
export default SideNav;
|
@ -1,6 +1,6 @@
|
|||||||
interface ISlackProps {
|
interface ISlackProps {
|
||||||
width?: number;
|
width?: number | string;
|
||||||
height?: number;
|
height?: number | string;
|
||||||
}
|
}
|
||||||
function Slack({ width, height }: ISlackProps): JSX.Element {
|
function Slack({ width, height }: ISlackProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
@ -47,8 +47,8 @@ function Slack({ width, height }: ISlackProps): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Slack.defaultProps = {
|
Slack.defaultProps = {
|
||||||
width: 28,
|
width: '1em',
|
||||||
height: 28,
|
height: '1em',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Slack;
|
export default Slack;
|
||||||
|
3
frontend/src/container/SideNav/index.ts
Normal file
3
frontend/src/container/SideNav/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import SideNav from './SideNav';
|
||||||
|
|
||||||
|
export default SideNav;
|
@ -10,28 +10,11 @@ import {
|
|||||||
MenuOutlined,
|
MenuOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { MenuProps, Space, Typography } from 'antd';
|
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
|
|
||||||
import { Tags } from './styles';
|
import { SidebarMenu } from './sideNav.types';
|
||||||
|
|
||||||
type MenuItem = Required<MenuProps>['items'][number];
|
const menuItems: SidebarMenu[] = [
|
||||||
|
|
||||||
export const createLabelWithTags = (
|
|
||||||
label: string,
|
|
||||||
tags: string[],
|
|
||||||
): JSX.Element => (
|
|
||||||
<Space>
|
|
||||||
<div>{label}</div>
|
|
||||||
{tags.map((tag) => (
|
|
||||||
<Tags key={tag}>
|
|
||||||
<Typography.Text>{tag}</Typography.Text>
|
|
||||||
</Tags>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
|
|
||||||
const menus: SidebarMenu[] = [
|
|
||||||
{
|
{
|
||||||
key: ROUTES.APPLICATION,
|
key: ROUTES.APPLICATION,
|
||||||
label: 'Services',
|
label: 'Services',
|
||||||
@ -111,8 +94,11 @@ const menus: SidebarMenu[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type SidebarMenu = MenuItem & {
|
/** Mapping of some newly added routes and their corresponding active sidebar menu key */
|
||||||
tags?: string[];
|
export const NEW_ROUTES_MENU_ITEM_KEY_MAP = {
|
||||||
|
[ROUTES.TRACES_EXPLORER]: ROUTES.TRACE,
|
||||||
|
[ROUTES.TRACE_EXPLORER]: ROUTES.TRACE,
|
||||||
|
[ROUTES.LOGS_EXPLORER]: ROUTES.LOGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default menus;
|
export default menuItems;
|
||||||
|
21
frontend/src/container/SideNav/sideNav.types.ts
Normal file
21
frontend/src/container/SideNav/sideNav.types.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { MenuProps } from 'antd';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
export type MenuItem = Required<MenuProps>['items'][number];
|
||||||
|
|
||||||
|
export type SidebarMenu = MenuItem & {
|
||||||
|
tags?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface SidebarItem {
|
||||||
|
onClick: VoidFunction;
|
||||||
|
icon?: ReactNode;
|
||||||
|
text?: ReactNode;
|
||||||
|
key: string;
|
||||||
|
label?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SecondaryMenuItemKey {
|
||||||
|
Slack = 'slack',
|
||||||
|
Version = 'version',
|
||||||
|
}
|
11
frontend/src/container/SideNav/sideNav.utils.ts
Normal file
11
frontend/src/container/SideNav/sideNav.utils.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { NEW_ROUTES_MENU_ITEM_KEY_MAP } from './menuItems';
|
||||||
|
|
||||||
|
export const getActiveMenuKeyFromPath = (pathname: string): string => {
|
||||||
|
const basePath = pathname?.split('/')?.[1]; // Get the base path, Eg; /dashboard/dc5beb63-589c-46a3-ad4c-1b9ca248ee33 -> dashboard
|
||||||
|
|
||||||
|
if (!basePath) return '';
|
||||||
|
|
||||||
|
const baseRoute = `/${basePath}`;
|
||||||
|
|
||||||
|
return NEW_ROUTES_MENU_ITEM_KEY_MAP[baseRoute] || baseRoute;
|
||||||
|
};
|
@ -1,87 +1,68 @@
|
|||||||
import { Layout, Tag, Typography } from 'antd';
|
import { Layout, Menu, Typography } from 'antd';
|
||||||
import { StyledCSS } from 'container/GantChart/Trace/styles';
|
import styled from 'styled-components';
|
||||||
import styled, { css } from 'styled-components';
|
|
||||||
|
|
||||||
const { Sider: SiderComponent } = Layout;
|
const { Sider: SiderComponent } = Layout;
|
||||||
|
|
||||||
interface LogoProps {
|
|
||||||
collapsed: boolean;
|
|
||||||
index: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Sider = styled(SiderComponent)`
|
export const Sider = styled(SiderComponent)`
|
||||||
&&& {
|
&&& {
|
||||||
background: #1f1f1f;
|
background: #1f1f1f;
|
||||||
|
|
||||||
|
.ant-layout-sider-children {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-layout-sider-trigger {
|
.ant-layout-sider-trigger {
|
||||||
background: #1f1f1f;
|
background: #1f1f1f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SlackButton = styled(Typography)`
|
export const StyledPrimaryMenu = styled(Menu)`
|
||||||
&&& {
|
flex: 1;
|
||||||
margin-left: 1rem;
|
overflow-y: auto;
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SlackMenuItemContainer = styled.div<LogoProps>`
|
export const StyledSecondaryMenu = styled(Menu)`
|
||||||
position: fixed;
|
|
||||||
bottom: ${({ index }): string => `${index * 48 + (index + 16)}px`};
|
|
||||||
background: #262626;
|
|
||||||
width: ${({ collapsed }): string => (!collapsed ? '200px' : '80px')};
|
|
||||||
transition: inherit;
|
|
||||||
background: #1f1f1f;
|
|
||||||
|
|
||||||
&&& {
|
&&& {
|
||||||
li {
|
:not(.ant-menu-inline-collapsed) > .ant-menu-item {
|
||||||
${({ collapsed }): StyledCSS =>
|
padding-inline: 48px;
|
||||||
collapsed &&
|
|
||||||
css`
|
display: flex;
|
||||||
padding-left: 24px;
|
align-items: center;
|
||||||
padding-top: 6px;
|
justify-content: center;
|
||||||
`}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-left: ${({ collapsed }): string => (collapsed ? '0' : '24px')};
|
|
||||||
width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
|
|
||||||
${({ collapsed }): StyledCSS =>
|
|
||||||
collapsed &&
|
|
||||||
css`
|
|
||||||
height: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
`}
|
|
||||||
}
|
|
||||||
.ant-menu-title-content {
|
.ant-menu-title-content {
|
||||||
margin: 0;
|
margin-inline-start: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-menu-inline-collapsed .ant-menu-title-content {
|
||||||
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const RedDot = styled.div`
|
export const RedDot = styled.div`
|
||||||
width: 12px;
|
width: 10px;
|
||||||
height: 12px;
|
height: 10px;
|
||||||
background: #d32029;
|
background: #d32029;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
margin-top: 0.5rem;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const VersionContainer = styled.div`
|
export const MenuLabelContainer = styled.div`
|
||||||
&&& {
|
display: inline-flex;
|
||||||
display: flex;
|
align-items: center;
|
||||||
}
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Tags = styled(Tag)`
|
export const StyledText = styled(Typography.Text)`
|
||||||
&&& {
|
width: 100%;
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
color: white;
|
||||||
border-radius: 0.5rem;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
@ -4,6 +4,5 @@ import styled from 'styled-components';
|
|||||||
export const Container = styled(Row)`
|
export const Container = styled(Row)`
|
||||||
&&& {
|
&&& {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
min-height: 8vh;
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
18
frontend/src/globalStyles.ts
Normal file
18
frontend/src/globalStyles.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { createGlobalStyle } from 'styled-components';
|
||||||
|
|
||||||
|
const GlobalStyles = createGlobalStyle`
|
||||||
|
#root,
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default GlobalStyles;
|
@ -57,7 +57,7 @@
|
|||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 0; padding: 0; box-sizing: border-box">
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -2,6 +2,7 @@ import './wdyr';
|
|||||||
import './ReactI18';
|
import './ReactI18';
|
||||||
|
|
||||||
import AppRoutes from 'AppRoutes';
|
import AppRoutes from 'AppRoutes';
|
||||||
|
import GlobalStyles from 'globalStyles';
|
||||||
import { ThemeProvider } from 'hooks/useDarkMode';
|
import { ThemeProvider } from 'hooks/useDarkMode';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { HelmetProvider } from 'react-helmet-async';
|
import { HelmetProvider } from 'react-helmet-async';
|
||||||
@ -33,6 +34,7 @@ if (container) {
|
|||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
|
<GlobalStyles />
|
||||||
<AppRoutes />
|
<AppRoutes />
|
||||||
</Provider>
|
</Provider>
|
||||||
{process.env.NODE_ENV === 'development' && (
|
{process.env.NODE_ENV === 'development' && (
|
||||||
|
@ -3,7 +3,7 @@ import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
|
|||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
import AppActions from 'types/actions';
|
import AppActions from 'types/actions';
|
||||||
|
|
||||||
export const SideBarCollapse = (
|
export const sideBarCollapse = (
|
||||||
collapseState: boolean,
|
collapseState: boolean,
|
||||||
): ((dispatch: Dispatch<AppActions>) => void) => {
|
): ((dispatch: Dispatch<AppActions>) => void) => {
|
||||||
setLocalStorageKey(IS_SIDEBAR_COLLAPSED, `${collapseState}`);
|
setLocalStorageKey(IS_SIDEBAR_COLLAPSED, `${collapseState}`);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user