2023-04-03 13:30:48 +05:30

166 lines
3.9 KiB
TypeScript

import { CheckCircleTwoTone, WarningOutlined } from '@ant-design/icons';
import { Menu, Space, Typography } from 'antd';
import getLocalStorageKey from 'api/browser/localstorage/get';
import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
import ROUTES from 'constants/routes';
import history from 'lib/history';
import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { SideBarCollapse } from 'store/actions/app';
import { AppState } from 'store/reducers';
import AppReducer from 'types/reducer/app';
import { styles } from './config';
import menus from './menuItems';
import Slack from './Slack';
import {
RedDot,
Sider,
SlackButton,
SlackMenuItemContainer,
Tags,
VersionContainer,
} from './styles';
function SideNav(): JSX.Element {
const dispatch = useDispatch();
const [collapsed, setCollapsed] = useState<boolean>(
getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true',
);
const { currentVersion, latestVersion, isCurrentVersionError } = useSelector<
AppState,
AppReducer
>((state) => state.app);
const { pathname } = useLocation();
const { t } = useTranslation('');
const onCollapse = useCallback(() => {
setCollapsed((collapsed) => !collapsed);
}, []);
useLayoutEffect(() => {
dispatch(SideBarCollapse(collapsed));
}, [collapsed, dispatch]);
const onClickHandler = useCallback(
(to: string) => {
if (pathname !== to) {
history.push(`${to}`);
}
},
[pathname],
);
const onClickSlackHandler = (): void => {
window.open('https://signoz.io/slack', '_blank');
};
const onClickVersionHandler = (): void => {
history.push(ROUTES.VERSION);
};
const isNotCurrentVersion = currentVersion !== latestVersion;
const sidebar: SidebarItem[] = [
{
onClick: onClickSlackHandler,
icon: <Slack />,
text: <SlackButton>Support</SlackButton>,
key: 'slack',
},
{
onClick: onClickVersionHandler,
key: 'version',
icon: isNotCurrentVersion ? (
<WarningOutlined style={{ color: '#E87040' }} />
) : (
<CheckCircleTwoTone twoToneColor={['#D5F2BB', '#1f1f1f']} />
),
text: (
<VersionContainer>
{!isCurrentVersionError ? (
<SlackButton>{currentVersion}</SlackButton>
) : (
<SlackButton>{t('n_a')}</SlackButton>
)}
{isNotCurrentVersion && <RedDot />}
</VersionContainer>
),
},
];
const currentMenu = useMemo(
() => menus.find((menu) => pathname.startsWith(menu.to)),
[pathname],
);
const items = [
...menus.map(({ to, Icon, name, tags, children }) => ({
key: to,
icon: <Icon />,
onClick: (): void => onClickHandler(to),
label: (
<Space>
<div>{name}</div>
{tags &&
tags.map((e) => (
<Tags key={e}>
<Typography.Text>{e}</Typography.Text>
</Tags>
))}
</Space>
),
children,
})),
];
const sidebarItems = (props: SidebarItem, index: number): SidebarItem => ({
key: `${index}`,
icon: props.icon,
onClick: props.onClick,
label: props.text,
});
return (
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse} width={200}>
<Menu
theme="dark"
defaultSelectedKeys={[ROUTES.APPLICATION]}
selectedKeys={currentMenu ? [currentMenu?.to] : []}
mode="vertical"
style={styles}
items={items}
/>
{sidebar.map((props, index) => (
<SlackMenuItemContainer
index={index + 1}
key={`${index + 1}`}
collapsed={collapsed}
>
<Menu
theme="dark"
defaultSelectedKeys={[ROUTES.APPLICATION]}
selectedKeys={currentMenu ? [currentMenu?.to] : []}
mode="inline"
style={styles}
items={[sidebarItems(props, index)]}
/>
</SlackMenuItemContainer>
))}
</Sider>
);
}
interface SidebarItem {
onClick: VoidFunction;
icon?: React.ReactNode;
text?: React.ReactNode;
key: string;
label?: React.ReactNode;
}
export default SideNav;