Files
grafana/public/app/core/components/sidemenu/BottomSection.tsx
Ashley Harrison ca53f5c8da Navigation: Implement active state for items in the Sidemenu (#39030)
* Navigation: Implement active state for items in the Sidemenu

* Navigation: Improve logic for when link is active and extract isSearchActive into a util function

* Navigation: Implement custom rule for dashboards under /d/ and fix minor bugs

* Navigation: only show first matching active state + strip query params from link urls
2021-09-13 16:49:27 +01:00

113 lines
3.6 KiB
TypeScript

import React, { useState } from 'react';
import { useLocation } from 'react-router-dom';
import { cloneDeep } from 'lodash';
import { css } from '@emotion/css';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { Icon, IconName, styleMixins, useTheme2 } from '@grafana/ui';
import { contextSrv } from 'app/core/services/context_srv';
import appEvents from '../../app_events';
import { ShowModalReactEvent } from '../../../types/events';
import config from '../../config';
import { OrgSwitcher } from '../OrgSwitcher';
import { getFooterLinks } from '../Footer/Footer';
import { HelpModal } from '../help/HelpModal';
import SideMenuItem from './SideMenuItem';
import { getForcedLoginUrl, isLinkActive, isSearchActive } from './utils';
export default function BottomSection() {
const theme = useTheme2();
const styles = getStyles(theme);
const navTree: NavModelItem[] = cloneDeep(config.bootData.navTree);
const bottomNav = navTree.filter((item) => item.hideFromMenu);
const isSignedIn = contextSrv.isSignedIn;
const location = useLocation();
const activeItemId = bottomNav.find((item) => isLinkActive(location.pathname, item))?.id;
const forcedLoginUrl = getForcedLoginUrl(location.pathname + location.search);
const user = contextSrv.user;
const [showSwitcherModal, setShowSwitcherModal] = useState(false);
const toggleSwitcherModal = () => {
setShowSwitcherModal(!showSwitcherModal);
};
const onOpenShortcuts = () => {
appEvents.publish(new ShowModalReactEvent({ component: HelpModal }));
};
if (user && user.orgCount > 1) {
const profileNode = bottomNav.find((bottomNavItem) => bottomNavItem.id === 'profile');
if (profileNode) {
profileNode.showOrgSwitcher = true;
profileNode.subTitle = `Current Org.: ${user?.orgName}`;
}
}
return (
<div data-testid="bottom-section-items" className={styles.container}>
{!isSignedIn && (
<SideMenuItem label="Sign In" target="_self" url={forcedLoginUrl}>
<Icon name="signout" size="xl" />
</SideMenuItem>
)}
{bottomNav.map((link, index) => {
let menuItems = link.children || [];
if (link.id === 'help') {
menuItems = [
...getFooterLinks(),
{
text: 'Keyboard shortcuts',
icon: 'keyboard',
onClick: onOpenShortcuts,
},
];
}
if (link.showOrgSwitcher) {
menuItems = [
...menuItems,
{
text: 'Switch organization',
icon: 'arrow-random',
onClick: toggleSwitcherModal,
},
];
}
return (
<SideMenuItem
key={`${link.url}-${index}`}
isActive={!isSearchActive(location) && activeItemId === link.id}
label={link.text}
menuItems={menuItems}
menuSubTitle={link.subTitle}
onClick={link.onClick}
reverseMenuDirection
target={link.target}
url={link.url}
>
{link.icon && <Icon name={link.icon as IconName} size="xl" />}
{link.img && <img src={link.img} alt={`${link.text} logo`} />}
</SideMenuItem>
);
})}
{showSwitcherModal && <OrgSwitcher onDismiss={toggleSwitcherModal} />}
</div>
);
}
const getStyles = (theme: GrafanaTheme2) => ({
container: css`
display: none;
@media ${styleMixins.mediaUp(`${theme.breakpoints.values.md}px`)} {
display: block;
margin-bottom: ${theme.spacing(2)};
}
.sidemenu-open--xs & {
display: block;
}
`,
});