mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-11 00:08:30 +01:00
fix: improve HTML landmarks (#886)
* fix: improve HTML landmarks * refactor: footer headers should use h2 * refactor: fix header order on the feature overview page * fix: make drawer logo clickable * fix: wrap header links in <nav> * fix: label breadcrumbs nav element * refactor: remove unused breadcrumb.jsx * fix: add search role to SearchField * fix: correct heading order on form pages
This commit is contained in:
parent
73c601cc7b
commit
ff0d55b6cc
@ -40,7 +40,10 @@ const BreadcrumbNav = () => {
|
||||
<ConditionallyRender
|
||||
condition={paths.length > 1}
|
||||
show={
|
||||
<Breadcrumbs className={styles.breadcrumbNav}>
|
||||
<Breadcrumbs
|
||||
className={styles.breadcrumbNav}
|
||||
aria-label="Breadcrumbs"
|
||||
>
|
||||
{paths.map((path, index) => {
|
||||
const lastItem = index === paths.length - 1;
|
||||
if (lastItem) {
|
||||
|
@ -84,7 +84,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
|
||||
show={<Loader />}
|
||||
elseShow={
|
||||
<>
|
||||
<h2 className={styles.title}>{title}</h2>
|
||||
<h1 className={styles.title}>{title}</h1>
|
||||
{children}
|
||||
</>
|
||||
}
|
||||
@ -98,14 +98,14 @@ const FormTemplate: React.FC<ICreateProps> = ({
|
||||
documentationLink={documentationLink}
|
||||
documentationLinkLabel={documentationLinkLabel}
|
||||
>
|
||||
<h3 className={styles.subtitle}>
|
||||
<h2 className={styles.subtitle}>
|
||||
API Command{' '}
|
||||
<Tooltip title="Copy command">
|
||||
<IconButton onClick={copyCommand}>
|
||||
<FileCopy className={styles.icon} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</h3>
|
||||
</h2>
|
||||
<Codebox text={formatApiCode()} />
|
||||
</Guidance>
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ const HeaderTitle = ({
|
||||
<div className={styles.headerTitleContainer}>
|
||||
<div className={headerClasses} data-loading>
|
||||
<Typography
|
||||
variant={variant || 'h2'}
|
||||
variant={variant || 'h1'}
|
||||
className={classnames(styles.headerTitle, className)}
|
||||
>
|
||||
{title}
|
||||
|
@ -46,7 +46,7 @@ export const SearchField = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<form className={styles.container} role="search">
|
||||
<div className={classnames(styles.search, className)}>
|
||||
<SearchIcon className={styles.searchIcon} />
|
||||
<InputBase
|
||||
@ -57,6 +57,7 @@ export const SearchField = ({
|
||||
onChange={handleChange}
|
||||
onBlur={updateNow}
|
||||
onKeyPress={handleKeyPress}
|
||||
type="search"
|
||||
/>
|
||||
</div>
|
||||
<ConditionallyRender
|
||||
@ -69,6 +70,6 @@ export const SearchField = ({
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
@ -5,8 +5,9 @@ exports[`renders correctly with one feature 1`] = `
|
||||
<div
|
||||
className="makeStyles-searchBarContainer-3"
|
||||
>
|
||||
<div
|
||||
<form
|
||||
className="makeStyles-container-6"
|
||||
role="search"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-search-7 makeStyles-searchBar-4"
|
||||
@ -28,18 +29,18 @@ exports[`renders correctly with one feature 1`] = `
|
||||
>
|
||||
<input
|
||||
aria-label="search"
|
||||
className="MuiInputBase-input"
|
||||
className="MuiInputBase-input MuiInputBase-inputTypeSearch"
|
||||
onAnimationStart={[Function]}
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
placeholder="Search..."
|
||||
type="text"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<a
|
||||
href="/archive"
|
||||
onClick={[Function]}
|
||||
@ -66,11 +67,11 @@ exports[`renders correctly with one feature 1`] = `
|
||||
className=""
|
||||
data-loading={true}
|
||||
>
|
||||
<h2
|
||||
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h2"
|
||||
<h1
|
||||
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h1"
|
||||
>
|
||||
Features
|
||||
</h2>
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
className="makeStyles-headerActions-16"
|
||||
@ -176,8 +177,9 @@ exports[`renders correctly with one feature without permissions 1`] = `
|
||||
<div
|
||||
className="makeStyles-searchBarContainer-3"
|
||||
>
|
||||
<div
|
||||
<form
|
||||
className="makeStyles-container-6"
|
||||
role="search"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-search-7 makeStyles-searchBar-4"
|
||||
@ -199,18 +201,18 @@ exports[`renders correctly with one feature without permissions 1`] = `
|
||||
>
|
||||
<input
|
||||
aria-label="search"
|
||||
className="MuiInputBase-input"
|
||||
className="MuiInputBase-input MuiInputBase-inputTypeSearch"
|
||||
onAnimationStart={[Function]}
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
placeholder="Search..."
|
||||
type="text"
|
||||
type="search"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<a
|
||||
href="/archive"
|
||||
onClick={[Function]}
|
||||
@ -237,11 +239,11 @@ exports[`renders correctly with one feature without permissions 1`] = `
|
||||
className=""
|
||||
data-loading={true}
|
||||
>
|
||||
<h2
|
||||
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h2"
|
||||
<h1
|
||||
className="MuiTypography-root makeStyles-headerTitle-15 MuiTypography-h1"
|
||||
>
|
||||
Features
|
||||
</h2>
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
className="makeStyles-headerActions-16"
|
||||
|
@ -30,9 +30,9 @@ const FeatureOverviewMetaData = () => {
|
||||
<div className={styles.paddingContainerTop}>
|
||||
<div className={styles.metaDataHeader} data-loading>
|
||||
<IconComponent className={styles.headerIcon} />{' '}
|
||||
<h3 className={styles.header}>
|
||||
<h2 className={styles.header}>
|
||||
{capitalize(type || '')} toggle
|
||||
</h3>
|
||||
</h2>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<span className={styles.bodyItem} data-loading>
|
||||
|
@ -119,12 +119,12 @@ export const FeatureView = () => {
|
||||
<div className={styles.header}>
|
||||
<div className={styles.innerContainer}>
|
||||
<div className={styles.toggleInfoContainer}>
|
||||
<h2
|
||||
<h1
|
||||
className={styles.featureViewHeader}
|
||||
data-loading
|
||||
>
|
||||
{feature.name}{' '}
|
||||
</h2>
|
||||
</h1>
|
||||
<ConditionallyRender
|
||||
condition={!smallScreen}
|
||||
show={<StatusChip stale={feature?.stale} />}
|
||||
|
@ -37,7 +37,7 @@ export const MainLayout = ({ children }: IMainLayoutProps) => {
|
||||
<>
|
||||
<Header />
|
||||
<Grid container className={muiStyles.container}>
|
||||
<div className={classnames(styles.contentWrapper)}>
|
||||
<main className={classnames(styles.contentWrapper)}>
|
||||
<Grid item className={styles.content} xs={12} sm={12}>
|
||||
<div
|
||||
className={muiStyles.contentContainer}
|
||||
@ -61,7 +61,7 @@ export const MainLayout = ({ children }: IMainLayoutProps) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</Grid>
|
||||
</>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { ApiDetails } from '../Footer/ApiDetails/ApiDetails';
|
||||
import { ApiDetails } from 'component/menu/Footer/ApiDetails/ApiDetails';
|
||||
import { render } from 'utils/testRenderer';
|
||||
|
||||
test('renders correctly with empty version', () => {
|
||||
const uiConfig = {
|
||||
@ -10,8 +10,8 @@ test('renders correctly with empty version', () => {
|
||||
version: '',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<ApiDetails uiConfig={uiConfig} />);
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly with ui-config', () => {
|
||||
@ -22,8 +22,8 @@ test('renders correctly with ui-config', () => {
|
||||
version: '1.1.0',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<ApiDetails uiConfig={uiConfig} />);
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly without uiConfig', () => {
|
||||
@ -32,8 +32,8 @@ test('renders correctly without uiConfig', () => {
|
||||
version: '1.1.0',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<ApiDetails uiConfig={uiConfig} />);
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly with versionInfo', () => {
|
||||
@ -48,6 +48,6 @@ test('renders correctly with versionInfo', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<ApiDetails uiConfig={uiConfig} />);
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
@ -5,6 +5,7 @@ import {
|
||||
formatUpdateNotification,
|
||||
IPartialUiConfig,
|
||||
} from './apidetails.helpers';
|
||||
import { FooterTitle } from 'component/menu/Footer/FooterTitle';
|
||||
|
||||
interface IApiDetailsProps {
|
||||
uiConfig: IPartialUiConfig;
|
||||
@ -18,13 +19,13 @@ export const ApiDetails = (props: IApiDetailsProps): ReactElement => {
|
||||
|
||||
return (
|
||||
<section title="API details">
|
||||
<h4>
|
||||
<FooterTitle>
|
||||
{currentVersion}{' '}
|
||||
<ConditionallyRender
|
||||
condition={Boolean(environment)}
|
||||
show={<small>({environment})</small>}
|
||||
/>
|
||||
</h4>
|
||||
</FooterTitle>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(updateNotification)}
|
||||
show={
|
||||
|
@ -0,0 +1,102 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly with empty version 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h2
|
||||
class="makeStyles-title-1"
|
||||
>
|
||||
Unleash
|
||||
|
||||
<small>
|
||||
(
|
||||
test
|
||||
)
|
||||
</small>
|
||||
</h2>
|
||||
<br />
|
||||
<small>
|
||||
We are the best!
|
||||
</small>
|
||||
<br />
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`renders correctly with ui-config 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h2
|
||||
class="makeStyles-title-2"
|
||||
>
|
||||
Unleash 1.1.0
|
||||
|
||||
<small>
|
||||
(
|
||||
test
|
||||
)
|
||||
</small>
|
||||
</h2>
|
||||
<br />
|
||||
<small>
|
||||
We are the best!
|
||||
</small>
|
||||
<br />
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`renders correctly with versionInfo 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h2
|
||||
class="makeStyles-title-4"
|
||||
>
|
||||
Unleash 1.2.3
|
||||
|
||||
</h2>
|
||||
<small>
|
||||
Upgrade available - Latest Enterprise release: 1.2.4
|
||||
<br />
|
||||
</small>
|
||||
<br />
|
||||
<small />
|
||||
<br />
|
||||
<small>
|
||||
1
|
||||
</small>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`renders correctly without uiConfig 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h2
|
||||
class="makeStyles-title-3"
|
||||
>
|
||||
Unleash 1.1.0
|
||||
|
||||
</h2>
|
||||
<br />
|
||||
<small />
|
||||
<br />
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
@ -4,6 +4,7 @@ import { List, ListItem, ListItemText, Grid } from '@material-ui/core';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { ApiDetails } from './ApiDetails/ApiDetails';
|
||||
import { useStyles } from './Footer.styles';
|
||||
import { FooterTitle } from './FooterTitle';
|
||||
|
||||
export const Footer = () => {
|
||||
const styles = useStyles();
|
||||
@ -24,7 +25,7 @@ export const Footer = () => {
|
||||
<Grid container spacing={7} direction="row">
|
||||
<Grid item>
|
||||
<section title="Unleash SDK">
|
||||
<h4>Server SDKs</h4>
|
||||
<FooterTitle>Server SDKs</FooterTitle>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
@ -135,7 +136,7 @@ export const Footer = () => {
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<section title="Unleash SDK">
|
||||
<h4>Frontend SDKs</h4>
|
||||
<FooterTitle>Frontend SDKs</FooterTitle>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
@ -207,7 +208,7 @@ export const Footer = () => {
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<section>
|
||||
<h4>About</h4>
|
||||
<FooterTitle>About</FooterTitle>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
|
11
frontend/src/component/menu/Footer/FooterTitle.styles.ts
Normal file
11
frontend/src/component/menu/Footer/FooterTitle.styles.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
title: {
|
||||
all: 'unset',
|
||||
display: 'block',
|
||||
margin: '1rem 0',
|
||||
fontSize: '1rem',
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
}));
|
12
frontend/src/component/menu/Footer/FooterTitle.tsx
Normal file
12
frontend/src/component/menu/Footer/FooterTitle.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { useStyles } from 'component/menu/Footer/FooterTitle.styles';
|
||||
|
||||
interface IFooterTitleProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const FooterTitle = ({ children }: IFooterTitleProps) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return <h2 className={styles.title}>{children}</h2>;
|
||||
};
|
@ -28,6 +28,11 @@ export const useStyles = makeStyles(theme => ({
|
||||
padding: '0',
|
||||
},
|
||||
},
|
||||
nav: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexGrow: 1,
|
||||
},
|
||||
drawerButton: {
|
||||
color: '#000',
|
||||
},
|
||||
|
@ -59,123 +59,107 @@ const Header = () => {
|
||||
adminRoutes: routes.adminRoutes.filter(filterByFlags(flags)),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppBar className={styles.header} position="static">
|
||||
<Container className={styles.container}>
|
||||
<ConditionallyRender
|
||||
condition={smallScreen}
|
||||
show={
|
||||
<Tooltip title="Menu">
|
||||
<IconButton
|
||||
className={styles.drawerButton}
|
||||
onClick={toggleDrawer}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
}
|
||||
elseShow={
|
||||
<Link
|
||||
to="/"
|
||||
className={commonStyles.flexRow}
|
||||
aria-label="Home"
|
||||
if (smallScreen) {
|
||||
return (
|
||||
<>
|
||||
<AppBar className={styles.header} position="static">
|
||||
<Container className={styles.container}>
|
||||
<Tooltip title="Menu">
|
||||
<IconButton
|
||||
className={styles.drawerButton}
|
||||
onClick={toggleDrawer}
|
||||
aria-controls="header-drawer"
|
||||
aria-expanded={openDrawer}
|
||||
>
|
||||
<UnleashLogo
|
||||
className={styles.logo}
|
||||
aria-label="Unleash logo"
|
||||
/>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<DrawerMenu
|
||||
title={name}
|
||||
flags={flags}
|
||||
links={links}
|
||||
open={openDrawer}
|
||||
toggleDrawer={toggleDrawer}
|
||||
admin={admin}
|
||||
routes={filteredMainRoutes}
|
||||
/>
|
||||
<div className={styles.userContainer}>
|
||||
<UserProfile />
|
||||
</div>
|
||||
</Container>
|
||||
</AppBar>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
<DrawerMenu
|
||||
title={name}
|
||||
flags={flags}
|
||||
links={links}
|
||||
open={openDrawer}
|
||||
toggleDrawer={toggleDrawer}
|
||||
admin={admin}
|
||||
routes={filteredMainRoutes}
|
||||
return (
|
||||
<AppBar className={styles.header} position="static">
|
||||
<Container className={styles.container}>
|
||||
<Link to="/" className={commonStyles.flexRow} aria-label="Home">
|
||||
<UnleashLogo
|
||||
className={styles.logo}
|
||||
aria-label="Unleash logo"
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={!smallScreen}
|
||||
show={
|
||||
<div className={styles.links}>
|
||||
<Link to="/projects">Projects</Link>
|
||||
<Link to="/features">Feature toggles</Link>
|
||||
</Link>
|
||||
<nav className={styles.nav}>
|
||||
<div className={styles.links}>
|
||||
<Link to="/projects">Projects</Link>
|
||||
<Link to="/features">Feature toggles</Link>
|
||||
|
||||
<button
|
||||
className={styles.advancedNavButton}
|
||||
onClick={e =>
|
||||
setAnchorElAdvanced(e.currentTarget)
|
||||
}
|
||||
>
|
||||
Configure
|
||||
<KeyboardArrowDown />
|
||||
</button>
|
||||
<NavigationMenu
|
||||
id="settings-navigation"
|
||||
options={filteredMainRoutes.mainNavRoutes}
|
||||
anchorEl={anchorElAdvanced}
|
||||
handleClose={handleCloseAdvanced}
|
||||
style={{ top: '30px', left: '-55px' }}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<button
|
||||
className={styles.advancedNavButton}
|
||||
onClick={e => setAnchorElAdvanced(e.currentTarget)}
|
||||
>
|
||||
Configure
|
||||
<KeyboardArrowDown />
|
||||
</button>
|
||||
<NavigationMenu
|
||||
id="settings-navigation"
|
||||
options={filteredMainRoutes.mainNavRoutes}
|
||||
anchorEl={anchorElAdvanced}
|
||||
handleClose={handleCloseAdvanced}
|
||||
style={{ top: '30px', left: '-55px' }}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.userContainer}>
|
||||
<Tooltip title="Go to the documentation">
|
||||
<a
|
||||
href="https://docs.getunleash.io/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={styles.docsLink}
|
||||
>
|
||||
<MenuBookIcon className={styles.docsIcon} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<ConditionallyRender
|
||||
condition={!smallScreen}
|
||||
condition={admin}
|
||||
show={
|
||||
<>
|
||||
<Tooltip title="Go to the documentation">
|
||||
<a
|
||||
href="https://docs.getunleash.io/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={styles.docsLink}
|
||||
>
|
||||
<MenuBookIcon
|
||||
className={styles.docsIcon}
|
||||
/>
|
||||
</a>
|
||||
</Tooltip>
|
||||
<ConditionallyRender
|
||||
condition={admin}
|
||||
show={
|
||||
<Tooltip title="Settings">
|
||||
<IconButton
|
||||
onClick={e =>
|
||||
setAnchorEl(
|
||||
e.currentTarget
|
||||
)
|
||||
}
|
||||
>
|
||||
<SettingsIcon
|
||||
className={
|
||||
styles.docsIcon
|
||||
}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Settings">
|
||||
<IconButton
|
||||
onClick={e =>
|
||||
setAnchorEl(e.currentTarget)
|
||||
}
|
||||
/>
|
||||
<NavigationMenu
|
||||
id="admin-navigation"
|
||||
options={filteredMainRoutes.adminRoutes}
|
||||
anchorEl={anchorEl}
|
||||
handleClose={handleClose}
|
||||
style={{ top: '40px', left: '-125px' }}
|
||||
/>
|
||||
</>
|
||||
>
|
||||
<SettingsIcon
|
||||
className={styles.docsIcon}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
<NavigationMenu
|
||||
id="admin-navigation"
|
||||
options={filteredMainRoutes.adminRoutes}
|
||||
anchorEl={anchorEl}
|
||||
handleClose={handleClose}
|
||||
style={{ top: '40px', left: '-125px' }}
|
||||
/>{' '}
|
||||
<UserProfile />
|
||||
</div>
|
||||
</Container>
|
||||
</AppBar>
|
||||
</>
|
||||
</nav>
|
||||
</Container>
|
||||
</AppBar>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,78 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly with empty version 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
Unleash
|
||||
|
||||
<small>
|
||||
(
|
||||
test
|
||||
)
|
||||
</small>
|
||||
</h4>
|
||||
<br />
|
||||
<small>
|
||||
We are the best!
|
||||
</small>
|
||||
<br />
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`renders correctly with ui-config 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
Unleash 1.1.0
|
||||
|
||||
<small>
|
||||
(
|
||||
test
|
||||
)
|
||||
</small>
|
||||
</h4>
|
||||
<br />
|
||||
<small>
|
||||
We are the best!
|
||||
</small>
|
||||
<br />
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`renders correctly with versionInfo 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
Unleash 1.2.3
|
||||
|
||||
</h4>
|
||||
<small>
|
||||
Upgrade available - Latest Enterprise release: 1.2.4
|
||||
<br />
|
||||
</small>
|
||||
<br />
|
||||
<small />
|
||||
<br />
|
||||
<small>
|
||||
1
|
||||
</small>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`renders correctly without uiConfig 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
Unleash 1.1.0
|
||||
|
||||
</h4>
|
||||
<br />
|
||||
<small />
|
||||
<br />
|
||||
</section>
|
||||
`;
|
@ -1,43 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`breadcrumb for /features 1`] = `
|
||||
<span>
|
||||
<span
|
||||
className="headerTitleLink"
|
||||
>
|
||||
Feature Toggles
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`breadcrumb for /features/view/Demo 1`] = `
|
||||
<span>
|
||||
<a
|
||||
className="headerTitleLink"
|
||||
href="/features"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Feature Toggles
|
||||
</a>
|
||||
<span>
|
||||
<span>
|
||||
›
|
||||
</span>
|
||||
<span
|
||||
className="headerTitleLink"
|
||||
>
|
||||
Demo
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`breadcrumb for /strategies 1`] = `
|
||||
<span>
|
||||
<span
|
||||
className="headerTitleLink"
|
||||
>
|
||||
Strategies
|
||||
</span>
|
||||
</span>
|
||||
`;
|
@ -18,10 +18,12 @@ exports[`should render DrawerMenu 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
Unleash 3.x
|
||||
|
||||
</h4>
|
||||
</h2>
|
||||
<br />
|
||||
<small>
|
||||
The enterprise ready feature toggle service.
|
||||
@ -41,9 +43,11 @@ exports[`should render DrawerMenu 1`] = `
|
||||
<section
|
||||
title="Unleash SDK"
|
||||
>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
Server SDKs
|
||||
</h4>
|
||||
</h2>
|
||||
<ul
|
||||
className="MuiList-root makeStyles-list-2 MuiList-dense MuiList-padding"
|
||||
>
|
||||
@ -210,9 +214,11 @@ exports[`should render DrawerMenu 1`] = `
|
||||
<section
|
||||
title="Unleash SDK"
|
||||
>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
Frontend SDKs
|
||||
</h4>
|
||||
</h2>
|
||||
<ul
|
||||
className="MuiList-root makeStyles-list-2 MuiList-dense MuiList-padding"
|
||||
>
|
||||
@ -318,9 +324,11 @@ exports[`should render DrawerMenu 1`] = `
|
||||
className="MuiGrid-root MuiGrid-item"
|
||||
>
|
||||
<section>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
About
|
||||
</h4>
|
||||
</h2>
|
||||
<ul
|
||||
className="MuiList-root makeStyles-list-2 MuiList-dense MuiList-padding"
|
||||
>
|
||||
@ -446,10 +454,12 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
Unleash 3.x
|
||||
|
||||
</h4>
|
||||
</h2>
|
||||
<br />
|
||||
<small>
|
||||
The enterprise ready feature toggle service.
|
||||
@ -469,9 +479,11 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
|
||||
<section
|
||||
title="Unleash SDK"
|
||||
>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
Server SDKs
|
||||
</h4>
|
||||
</h2>
|
||||
<ul
|
||||
className="MuiList-root makeStyles-list-2 MuiList-dense MuiList-padding"
|
||||
>
|
||||
@ -638,9 +650,11 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
|
||||
<section
|
||||
title="Unleash SDK"
|
||||
>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
Frontend SDKs
|
||||
</h4>
|
||||
</h2>
|
||||
<ul
|
||||
className="MuiList-root makeStyles-list-2 MuiList-dense MuiList-padding"
|
||||
>
|
||||
@ -746,9 +760,11 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
|
||||
className="MuiGrid-root MuiGrid-item"
|
||||
>
|
||||
<section>
|
||||
<h4>
|
||||
<h2
|
||||
className="makeStyles-title-4"
|
||||
>
|
||||
About
|
||||
</h4>
|
||||
</h2>
|
||||
<ul
|
||||
className="MuiList-root makeStyles-list-2 MuiList-dense MuiList-padding"
|
||||
>
|
||||
|
@ -1,34 +0,0 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import Breadcrumb from '../breadcrumb';
|
||||
|
||||
test('breadcrumb for /features', () => {
|
||||
const tree = renderer.create(
|
||||
<MemoryRouter initialEntries={['/features']}>
|
||||
<Breadcrumb />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('breadcrumb for /features/view/Demo', () => {
|
||||
const tree = renderer.create(
|
||||
<MemoryRouter initialEntries={['/features/view/Demo']}>
|
||||
<Breadcrumb />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('breadcrumb for /strategies', () => {
|
||||
const tree = renderer.create(
|
||||
<MemoryRouter initialEntries={['/strategies']}>
|
||||
<Breadcrumb />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
@ -1,68 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Link, Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { routes, getRoute } from './routes';
|
||||
|
||||
import styles from '../styles.module.scss';
|
||||
|
||||
const renderDoubleBread = (currentTitle, parentRoute) => {
|
||||
document.title = `${currentTitle} - ${parentRoute.title} - Unleash`;
|
||||
return (
|
||||
<span>
|
||||
<Link className={styles.headerTitleLink} to={parentRoute.path}>
|
||||
{parentRoute.title}
|
||||
</Link>
|
||||
<span>
|
||||
<span> › </span>
|
||||
<span className={styles.headerTitleLink}>{currentTitle}</span>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const renderBread = route => {
|
||||
document.title = `${route.title} - Unleash`;
|
||||
return (
|
||||
<span>
|
||||
<span className={styles.headerTitleLink}>{route.title}</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const renderRoute = (params, route) => {
|
||||
if (!route) {
|
||||
return null;
|
||||
}
|
||||
const title = route.title.startsWith(':')
|
||||
? params[route.title.substring(1)]
|
||||
: route.title;
|
||||
return route.parent
|
||||
? renderDoubleBread(title, getRoute(route.parent))
|
||||
: renderBread(route);
|
||||
};
|
||||
|
||||
/*
|
||||
Render the breadcrumb.
|
||||
|
||||
We only support two levels.
|
||||
|
||||
Examples:
|
||||
- Features
|
||||
- Features > Create
|
||||
- Features > SomeToggle
|
||||
*/
|
||||
const Breadcrumb = () => (
|
||||
<Switch>
|
||||
{routes.map(route => (
|
||||
<Route
|
||||
key={route.path}
|
||||
path={route.path}
|
||||
render={({ match: { params } } = this.props) =>
|
||||
renderRoute(params, route)
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</Switch>
|
||||
);
|
||||
|
||||
export default Breadcrumb;
|
@ -4,9 +4,8 @@ import PropTypes from 'prop-types';
|
||||
import GitHubIcon from '@material-ui/icons/GitHub';
|
||||
import LibraryBooksIcon from '@material-ui/icons/LibraryBooks';
|
||||
import ExitToApp from '@material-ui/icons/ExitToApp';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from './drawer.module.scss';
|
||||
|
||||
import { ReactComponent as LogoIcon } from 'assets/icons/logoBg.svg';
|
||||
import NavigationLink from './Header/NavigationLink/NavigationLink';
|
||||
import ConditionallyRender from 'component/common/ConditionallyRender';
|
||||
@ -49,16 +48,23 @@ export const DrawerMenu = ({
|
||||
<Drawer
|
||||
className={styles.drawer}
|
||||
open={open}
|
||||
anchor={'left'}
|
||||
onClose={() => toggleDrawer()}
|
||||
anchor="left"
|
||||
onClose={toggleDrawer}
|
||||
>
|
||||
<div className={styles.drawerContainer}>
|
||||
<nav id="header-drawer" className={styles.drawerContainer}>
|
||||
<div>
|
||||
<span className={[styles.drawerTitle].join(' ')}>
|
||||
<LogoIcon className={styles.drawerTitleLogo} />
|
||||
|
||||
<Link
|
||||
to="/"
|
||||
className={styles.drawerTitle}
|
||||
aria-label="Home"
|
||||
onClick={() => toggleDrawer()}
|
||||
>
|
||||
<LogoIcon
|
||||
className={styles.drawerTitleLogo}
|
||||
aria-label="Unleash logo"
|
||||
/>
|
||||
<span className={styles.drawerTitleText}>{title}</span>
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
<Divider />
|
||||
<List className={styles.drawerList}>
|
||||
@ -101,7 +107,7 @@ export const DrawerMenu = ({
|
||||
Sign out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
@ -6,6 +6,8 @@
|
||||
.drawerTitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.drawerContainer {
|
||||
|
@ -20,11 +20,11 @@ exports[`renders correctly with one strategy 1`] = `
|
||||
className=""
|
||||
data-loading={true}
|
||||
>
|
||||
<h2
|
||||
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h2"
|
||||
<h1
|
||||
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h1"
|
||||
>
|
||||
Strategies
|
||||
</h2>
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
className="makeStyles-headerActions-8"
|
||||
@ -290,11 +290,11 @@ exports[`renders correctly with one strategy without permissions 1`] = `
|
||||
className=""
|
||||
data-loading={true}
|
||||
>
|
||||
<h2
|
||||
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h2"
|
||||
<h1
|
||||
className="MuiTypography-root makeStyles-headerTitle-7 MuiTypography-h1"
|
||||
>
|
||||
Strategies
|
||||
</h2>
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
className="makeStyles-headerActions-8"
|
||||
|
@ -20,11 +20,11 @@ exports[`renders a list with elements correctly 1`] = `
|
||||
className=""
|
||||
data-loading={true}
|
||||
>
|
||||
<h2
|
||||
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h2"
|
||||
<h1
|
||||
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h1"
|
||||
>
|
||||
Tag Types
|
||||
</h2>
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
className="makeStyles-headerActions-7"
|
||||
@ -96,11 +96,11 @@ exports[`renders an empty list correctly 1`] = `
|
||||
className=""
|
||||
data-loading={true}
|
||||
>
|
||||
<h2
|
||||
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h2"
|
||||
<h1
|
||||
className="MuiTypography-root makeStyles-headerTitle-6 MuiTypography-h1"
|
||||
>
|
||||
Tag Types
|
||||
</h2>
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
className="makeStyles-headerActions-7"
|
||||
|
Loading…
Reference in New Issue
Block a user