mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Sidemenu: Refactor SignIn to use SideMenuItem (#38882)
This commit is contained in:
parent
cbdba57924
commit
b82fe083d7
@ -1,11 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
import { ShowModalReactEvent } from '../../../types/events';
|
import { ShowModalReactEvent } from '../../../types/events';
|
||||||
import { HelpModal } from '../help/HelpModal';
|
import { HelpModal } from '../help/HelpModal';
|
||||||
import appEvents from '../../app_events';
|
import appEvents from '../../app_events';
|
||||||
import BottomSection from './BottomSection';
|
import BottomSection from './BottomSection';
|
||||||
|
|
||||||
|
jest.mock('./utils', () => ({
|
||||||
|
getForcedLoginUrl: () => '/mockForcedLoginUrl',
|
||||||
|
}));
|
||||||
jest.mock('../../app_events', () => ({
|
jest.mock('../../app_events', () => ({
|
||||||
publish: jest.fn(),
|
publish: jest.fn(),
|
||||||
}));
|
}));
|
||||||
@ -44,13 +48,21 @@ jest.mock('app/core/services/context_srv', () => ({
|
|||||||
|
|
||||||
describe('BottomSection', () => {
|
describe('BottomSection', () => {
|
||||||
it('should render the correct children', () => {
|
it('should render the correct children', () => {
|
||||||
render(<BottomSection />);
|
render(
|
||||||
|
<BrowserRouter>
|
||||||
|
<BottomSection />
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
|
||||||
expect(screen.getByTestId('bottom-section-items').children.length).toBe(3);
|
expect(screen.getByTestId('bottom-section-items').children.length).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates the correct children for the help link', () => {
|
it('creates the correct children for the help link', () => {
|
||||||
render(<BottomSection />);
|
render(
|
||||||
|
<BrowserRouter>
|
||||||
|
<BottomSection />
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
|
||||||
const documentation = screen.getByRole('link', { name: 'Documentation' });
|
const documentation = screen.getByRole('link', { name: 'Documentation' });
|
||||||
const support = screen.getByRole('link', { name: 'Support' });
|
const support = screen.getByRole('link', { name: 'Support' });
|
||||||
@ -63,7 +75,11 @@ describe('BottomSection', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('clicking the keyboard shortcuts button shows the modal', () => {
|
it('clicking the keyboard shortcuts button shows the modal', () => {
|
||||||
render(<BottomSection />);
|
render(
|
||||||
|
<BrowserRouter>
|
||||||
|
<BottomSection />
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
|
||||||
const keyboardShortcuts = screen.getByText('Keyboard shortcuts');
|
const keyboardShortcuts = screen.getByText('Keyboard shortcuts');
|
||||||
expect(keyboardShortcuts).toBeInTheDocument();
|
expect(keyboardShortcuts).toBeInTheDocument();
|
||||||
@ -73,7 +89,11 @@ describe('BottomSection', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('shows the current organization and organization switcher if showOrgSwitcher is true', () => {
|
it('shows the current organization and organization switcher if showOrgSwitcher is true', () => {
|
||||||
render(<BottomSection />);
|
render(
|
||||||
|
<BrowserRouter>
|
||||||
|
<BottomSection />
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
|
||||||
const currentOrg = screen.getByText(new RegExp('Grafana', 'i'));
|
const currentOrg = screen.getByText(new RegExp('Grafana', 'i'));
|
||||||
const orgSwitcher = screen.getByText('Switch organization');
|
const orgSwitcher = screen.getByText('Switch organization');
|
||||||
|
@ -3,7 +3,7 @@ import { cloneDeep } from 'lodash';
|
|||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { Icon, IconName } from '@grafana/ui';
|
import { Icon, IconName } from '@grafana/ui';
|
||||||
import appEvents from '../../app_events';
|
import appEvents from '../../app_events';
|
||||||
import { SignIn } from './SignIn';
|
import { useLocation } from 'react-router-dom';
|
||||||
import SideMenuItem from './SideMenuItem';
|
import SideMenuItem from './SideMenuItem';
|
||||||
import { ShowModalReactEvent } from '../../../types/events';
|
import { ShowModalReactEvent } from '../../../types/events';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
@ -11,11 +11,14 @@ import { OrgSwitcher } from '../OrgSwitcher';
|
|||||||
import { getFooterLinks } from '../Footer/Footer';
|
import { getFooterLinks } from '../Footer/Footer';
|
||||||
import { HelpModal } from '../help/HelpModal';
|
import { HelpModal } from '../help/HelpModal';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
|
import { getForcedLoginUrl } from './utils';
|
||||||
|
|
||||||
export default function BottomSection() {
|
export default function BottomSection() {
|
||||||
const navTree: NavModelItem[] = cloneDeep(config.bootData.navTree);
|
const navTree: NavModelItem[] = cloneDeep(config.bootData.navTree);
|
||||||
const bottomNav = navTree.filter((item) => item.hideFromMenu);
|
const bottomNav = navTree.filter((item) => item.hideFromMenu);
|
||||||
const isSignedIn = contextSrv.isSignedIn;
|
const isSignedIn = contextSrv.isSignedIn;
|
||||||
|
const location = useLocation();
|
||||||
|
const forcedLoginUrl = getForcedLoginUrl(location.pathname + location.search);
|
||||||
const user = contextSrv.user;
|
const user = contextSrv.user;
|
||||||
const [showSwitcherModal, setShowSwitcherModal] = useState(false);
|
const [showSwitcherModal, setShowSwitcherModal] = useState(false);
|
||||||
|
|
||||||
@ -37,7 +40,11 @@ export default function BottomSection() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="bottom-section-items" className="sidemenu__bottom">
|
<div data-testid="bottom-section-items" className="sidemenu__bottom">
|
||||||
{!isSignedIn && <SignIn />}
|
{!isSignedIn && (
|
||||||
|
<SideMenuItem label="Sign In" target="_self" url={forcedLoginUrl}>
|
||||||
|
<Icon name="signout" size="xl" />
|
||||||
|
</SideMenuItem>
|
||||||
|
)}
|
||||||
{bottomNav.map((link, index) => {
|
{bottomNav.map((link, index) => {
|
||||||
let menuItems = link.children || [];
|
let menuItems = link.children || [];
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import DropDownChild from './DropDownChild';
|
import DropDownChild from './DropDownChild';
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { IconName, Link } from '@grafana/ui';
|
import { IconName, Link } from '@grafana/ui';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
headerText: string;
|
headerText: string;
|
||||||
@ -21,17 +21,13 @@ const SideMenuDropDown = ({
|
|||||||
reverseDirection = false,
|
reverseDirection = false,
|
||||||
subtitleText,
|
subtitleText,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const resetButtonStyles = css`
|
|
||||||
background-color: transparent;
|
|
||||||
font-size: inherit;
|
|
||||||
`;
|
|
||||||
const headerContent = <span className="sidemenu-item-text">{headerText}</span>;
|
const headerContent = <span className="sidemenu-item-text">{headerText}</span>;
|
||||||
const header = headerUrl ? (
|
const header = headerUrl ? (
|
||||||
<Link href={headerUrl} onClick={onHeaderClick} className="side-menu-header-link">
|
<Link href={headerUrl} onClick={onHeaderClick} className="side-menu-header-link">
|
||||||
{headerContent}
|
{headerContent}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<button onClick={onHeaderClick} className={cx(resetButtonStyles, 'side-menu-header-link')}>
|
<button onClick={onHeaderClick} className="side-menu-header-link">
|
||||||
{headerContent}
|
{headerContent}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import React, { ReactNode } from 'react';
|
|||||||
import SideMenuDropDown from './SideMenuDropDown';
|
import SideMenuDropDown from './SideMenuDropDown';
|
||||||
import { Link } from '@grafana/ui';
|
import { Link } from '@grafana/ui';
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { css, cx } from '@emotion/css';
|
import { cx } from '@emotion/css';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -25,10 +25,6 @@ const SideMenuItem = ({
|
|||||||
target,
|
target,
|
||||||
url,
|
url,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const resetButtonStyles = css`
|
|
||||||
background-color: transparent;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const anchor = url ? (
|
const anchor = url ? (
|
||||||
<Link
|
<Link
|
||||||
className="sidemenu-link"
|
className="sidemenu-link"
|
||||||
@ -41,7 +37,7 @@ const SideMenuItem = ({
|
|||||||
<span className="icon-circle sidemenu-icon">{children}</span>
|
<span className="icon-circle sidemenu-icon">{children}</span>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<button className={cx(resetButtonStyles, 'sidemenu-link')} onClick={onClick} aria-label={label}>
|
<button className="sidemenu-link" onClick={onClick} aria-label={label}>
|
||||||
<span className="icon-circle sidemenu-icon">{children}</span>
|
<span className="icon-circle sidemenu-icon">{children}</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import { SignIn } from './SignIn';
|
|
||||||
import { Router } from 'react-router-dom';
|
|
||||||
import { locationService } from '@grafana/runtime';
|
|
||||||
|
|
||||||
describe('Render', () => {
|
|
||||||
it('should render component', async () => {
|
|
||||||
render(
|
|
||||||
<Router history={locationService.getHistory()}>
|
|
||||||
<SignIn url="/whatever" />
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
|
|
||||||
const link = await screen.getByText('Sign In');
|
|
||||||
expect(link).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,26 +0,0 @@
|
|||||||
import React, { FC } from 'react';
|
|
||||||
import { Icon } from '@grafana/ui';
|
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { getForcedLoginUrl } from './utils';
|
|
||||||
|
|
||||||
export const SignIn: FC<any> = () => {
|
|
||||||
const location = useLocation();
|
|
||||||
const forcedLoginUrl = getForcedLoginUrl(location.pathname + location.search);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="sidemenu-item">
|
|
||||||
<a href={forcedLoginUrl} className="sidemenu-link" target="_self">
|
|
||||||
<span className="icon-circle sidemenu-icon">
|
|
||||||
<Icon name="signout" size="xl" />
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a href={forcedLoginUrl} target="_self">
|
|
||||||
<ul className="dropdown-menu dropdown-menu--sidemenu" role="menu">
|
|
||||||
<li className="side-menu-header">
|
|
||||||
<span className="sidemenu-item-text">Sign In</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -85,6 +85,7 @@ $mobile-menu-breakpoint: md;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidemenu-link {
|
.sidemenu-link {
|
||||||
|
background-color: transparent;
|
||||||
color: $side-menu-icon-color !important;
|
color: $side-menu-icon-color !important;
|
||||||
line-height: 42px;
|
line-height: 42px;
|
||||||
padding: 0px 10px 0px 10px;
|
padding: 0px 10px 0px 10px;
|
||||||
@ -132,8 +133,10 @@ $mobile-menu-breakpoint: md;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.side-menu-header-link {
|
.side-menu-header-link {
|
||||||
color: $side-menu-header-color !important;
|
background-color: transparent;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
|
color: $side-menu-header-color !important;
|
||||||
|
font-size: inherit;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user