1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

Fix/routing (#325)

* fix: filter routes

* fix: add archive link to feature toggles list

* fix: strategy card name

* fix: add breadcrumb keys

* fix: update tests

* fix: menu placement

* fix: remove dot

* fix: handle 401 error

* fix: add important to styles

* fix: adjust positioning

* fix: remove unused imports
This commit is contained in:
Fredrik Strand Oseberg 2021-08-19 13:54:28 +02:00 committed by GitHub
parent 5febe31e71
commit b83418f410
15 changed files with 159 additions and 66 deletions

View File

@ -3,17 +3,20 @@ import { makeStyles } from '@material-ui/styles';
export const useCommonStyles = makeStyles(theme => ({ export const useCommonStyles = makeStyles(theme => ({
contentSpacingY: { contentSpacingY: {
'& > *': { '& > *': {
margin: '0.5rem 0', marginTop: '0.5rem !important',
marginBottom: '0.5rem !important',
}, },
}, },
contentSpacingYLarge: { contentSpacingYLarge: {
'& > *': { '& > *': {
margin: '1.5rem 0', marginTop: '1.5rem !important',
marginBottom: '1.5rem !important',
}, },
}, },
contentSpacingX: { contentSpacingX: {
'& > *': { '& > *': {
margin: '0 0.8rem', marginRight: '0.8rem !important',
marginLeft: '0.8rem !important',
}, },
}, },
divider: { divider: {

View File

@ -40,6 +40,7 @@ const BreadcrumbNav = () => {
if (lastItem) { if (lastItem) {
return ( return (
<p <p
key={path}
className={ className={
styles.breadcrumbNavParagraph styles.breadcrumbNavParagraph
} }
@ -50,6 +51,7 @@ const BreadcrumbNav = () => {
} }
return ( return (
<Link <Link
key={path}
className={styles.breadcrumbLink} className={styles.breadcrumbLink}
to={`/${path}`} to={`/${path}`}
> >

View File

@ -58,7 +58,7 @@ const Dialogue = ({
condition={onClose} condition={onClose}
show={ show={
<Button onClick={onClose}> <Button onClick={onClose}>
{secondaryButtonText || 'No take me back.'}{' '} {secondaryButtonText || 'No take me back'}{' '}
</Button> </Button>
} }
/> />

View File

@ -37,6 +37,7 @@ const FeatureToggleList = ({
const { hasAccess } = useContext(AccessContext); const { hasAccess } = useContext(AccessContext);
const styles = useStyles(); const styles = useStyles();
const smallScreen = useMediaQuery('(max-width:800px)'); const smallScreen = useMediaQuery('(max-width:800px)');
const mobileView = useMediaQuery('(max-width:600px)');
useLayoutEffect(() => { useLayoutEffect(() => {
fetcher(); fetcher();
@ -120,6 +121,10 @@ const FeatureToggleList = ({
skeleton: loading, skeleton: loading,
})} })}
/> />
<ConditionallyRender
condition={!mobileView}
show={<Link to="/archive">Archive</Link>}
/>
</div> </div>
<PageContent <PageContent

View File

@ -7,11 +7,11 @@ exports[`renders correctly with one feature 1`] = `
> >
<div> <div>
<div <div
className="makeStyles-search-5" className="makeStyles-search-6 makeStyles-searchBar-4"
> >
<svg <svg
aria-hidden={true} aria-hidden={true}
className="MuiSvgIcon-root makeStyles-searchIcon-6" className="MuiSvgIcon-root makeStyles-searchIcon-7"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
> >
@ -20,7 +20,7 @@ exports[`renders correctly with one feature 1`] = `
/> />
</svg> </svg>
<div <div
className="MuiInputBase-root makeStyles-inputRoot-7" className="MuiInputBase-root makeStyles-inputRoot-8"
onClick={[Function]} onClick={[Function]}
onKeyPress={[Function]} onKeyPress={[Function]}
> >
@ -38,6 +38,12 @@ exports[`renders correctly with one feature 1`] = `
</div> </div>
</div> </div>
</div> </div>
<a
href="/archive"
onClick={[Function]}
>
Archive
</a>
</div> </div>
<div <div
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded" className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
@ -49,29 +55,29 @@ exports[`renders correctly with one feature 1`] = `
} }
> >
<div <div
className="makeStyles-headerContainer-8" className="makeStyles-headerContainer-9"
> >
<div <div
className="makeStyles-headerTitleContainer-12" className="makeStyles-headerTitleContainer-13"
> >
<div <div
className="" className=""
data-loading={true} data-loading={true}
> >
<h2 <h2
className="MuiTypography-root makeStyles-headerTitle-13 MuiTypography-h2" className="MuiTypography-root makeStyles-headerTitle-14 MuiTypography-h2"
> >
Feature toggles Feature toggles
</h2> </h2>
</div> </div>
<div <div
className="makeStyles-headerActions-14" className="makeStyles-headerActions-15"
> >
<div <div
className="makeStyles-actionsContainer-1" className="makeStyles-actionsContainer-1"
> >
<div <div
className="makeStyles-actions-15" className="makeStyles-actions-16"
> >
<p <p
className="MuiTypography-root MuiTypography-body2" className="MuiTypography-root MuiTypography-body2"
@ -217,7 +223,7 @@ exports[`renders correctly with one feature 1`] = `
</div> </div>
</div> </div>
<div <div
className="makeStyles-bodyContainer-9" className="makeStyles-bodyContainer-10"
> >
<ul <ul
className="MuiList-root MuiList-padding" className="MuiList-root MuiList-padding"
@ -250,11 +256,11 @@ exports[`renders correctly with one feature without permissions 1`] = `
> >
<div> <div>
<div <div
className="makeStyles-search-5" className="makeStyles-search-6 makeStyles-searchBar-4"
> >
<svg <svg
aria-hidden={true} aria-hidden={true}
className="MuiSvgIcon-root makeStyles-searchIcon-6" className="MuiSvgIcon-root makeStyles-searchIcon-7"
focusable="false" focusable="false"
viewBox="0 0 24 24" viewBox="0 0 24 24"
> >
@ -263,7 +269,7 @@ exports[`renders correctly with one feature without permissions 1`] = `
/> />
</svg> </svg>
<div <div
className="MuiInputBase-root makeStyles-inputRoot-7" className="MuiInputBase-root makeStyles-inputRoot-8"
onClick={[Function]} onClick={[Function]}
onKeyPress={[Function]} onKeyPress={[Function]}
> >
@ -281,6 +287,12 @@ exports[`renders correctly with one feature without permissions 1`] = `
</div> </div>
</div> </div>
</div> </div>
<a
href="/archive"
onClick={[Function]}
>
Archive
</a>
</div> </div>
<div <div
className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded" className="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"
@ -292,29 +304,29 @@ exports[`renders correctly with one feature without permissions 1`] = `
} }
> >
<div <div
className="makeStyles-headerContainer-8" className="makeStyles-headerContainer-9"
> >
<div <div
className="makeStyles-headerTitleContainer-12" className="makeStyles-headerTitleContainer-13"
> >
<div <div
className="" className=""
data-loading={true} data-loading={true}
> >
<h2 <h2
className="MuiTypography-root makeStyles-headerTitle-13 MuiTypography-h2" className="MuiTypography-root makeStyles-headerTitle-14 MuiTypography-h2"
> >
Feature toggles Feature toggles
</h2> </h2>
</div> </div>
<div <div
className="makeStyles-headerActions-14" className="makeStyles-headerActions-15"
> >
<div <div
className="makeStyles-actionsContainer-1" className="makeStyles-actionsContainer-1"
> >
<div <div
className="makeStyles-actions-15" className="makeStyles-actions-16"
> >
<p <p
className="MuiTypography-root MuiTypography-body2" className="MuiTypography-root MuiTypography-body2"
@ -466,7 +478,7 @@ exports[`renders correctly with one feature without permissions 1`] = `
</div> </div>
</div> </div>
<div <div
className="makeStyles-bodyContainer-9" className="makeStyles-bodyContainer-10"
> >
<ul <ul
className="MuiList-root MuiList-padding" className="MuiList-root MuiList-padding"

View File

@ -10,6 +10,18 @@ export const useStyles = makeStyles(theme => ({
}, },
searchBarContainer: { searchBarContainer: {
marginBottom: '2rem', marginBottom: '2rem',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
[theme.breakpoints.down('xs')]: {
display: 'block',
},
},
searchBar: {
minWidth: '450px',
[theme.breakpoints.down('xs')]: {
minWidth: '100%',
},
}, },
emptyStateListItem: { emptyStateListItem: {
border: `2px dashed ${theme.palette.borders.main}`, border: `2px dashed ${theme.palette.borders.main}`,

View File

@ -25,12 +25,14 @@ const StrategyCardHeader = ({
}} }}
title={ title={
<> <>
<Tooltip title={name}>
<Typography <Typography
variant="subtitle1" variant="subtitle1"
className={styles.strategyCardHeaderTitle} className={styles.strategyCardHeaderTitle}
> >
{name} {name}
</Typography> </Typography>
</Tooltip>
<div className={styles.strategyCardHeaderActions}> <div className={styles.strategyCardHeaderActions}>
<Tooltip title="Edit strategy"> <Tooltip title="Edit strategy">
<IconButton onClick={editStrategy}> <IconButton onClick={editStrategy}>

View File

@ -15,6 +15,10 @@ export const useStyles = makeStyles(theme => ({
}, },
strategyCardHeaderTitle: { strategyCardHeaderTitle: {
fontSize: theme.fontSizes.subHeader, fontSize: theme.fontSizes.subHeader,
maxWidth: '70%',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
}, },
strategyCardHeaderActions: { strategyCardHeaderActions: {
display: 'flex', display: 'flex',

View File

@ -94,6 +94,7 @@ const Header = () => {
condition={flags?.P} condition={flags?.P}
show={<Link to="/projects">Projects</Link>} show={<Link to="/projects">Projects</Link>}
/> />
<Link to="/features">Feature toggles</Link>
<button <button
className={styles.advancedNavButton} className={styles.advancedNavButton}
@ -101,7 +102,7 @@ const Header = () => {
setAnchorElAdvanced(e.currentTarget) setAnchorElAdvanced(e.currentTarget)
} }
> >
Navigate Advanced
<KeyboardArrowDown /> <KeyboardArrowDown />
</button> </button>
<NavigationMenu <NavigationMenu
@ -109,6 +110,7 @@ const Header = () => {
options={filteredMainRoutes.mainNavRoutes} options={filteredMainRoutes.mainNavRoutes}
anchorEl={anchorElAdvanced} anchorEl={anchorElAdvanced}
handleClose={handleCloseAdvanced} handleClose={handleCloseAdvanced}
style={{ top: '30px', left: '-55px' }}
/> />
</div> </div>
} }
@ -150,6 +152,7 @@ const Header = () => {
options={routes.adminRoutes} options={routes.adminRoutes}
anchorEl={anchorEl} anchorEl={anchorEl}
handleClose={handleClose} handleClose={handleClose}
style={{ top: '40px', left: '-125px' }}
/> />
</> </>
} }

View File

@ -6,6 +6,7 @@ interface INavigationMenuProps {
id: string; id: string;
anchorEl: any; anchorEl: any;
handleClose: () => void; handleClose: () => void;
style: Object;
} }
const NavigationMenu = ({ const NavigationMenu = ({
@ -13,6 +14,7 @@ const NavigationMenu = ({
id, id,
handleClose, handleClose,
anchorEl, anchorEl,
style,
}: INavigationMenuProps) => { }: INavigationMenuProps) => {
return ( return (
<Popover <Popover
@ -21,7 +23,7 @@ const NavigationMenu = ({
anchorEl={anchorEl} anchorEl={anchorEl}
open={Boolean(anchorEl)} open={Boolean(anchorEl)}
onMouseLeave={handleClose} onMouseLeave={handleClose}
style={{ top: '30px', left: '-90px' }} style={style}
> >
<List> <List>
{options.map(option => { {options.map(option => {

View File

@ -5,6 +5,7 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {},
"path": "/features", "path": "/features",
"title": "Feature Toggles", "title": "Feature Toggles",
"type": "protected", "type": "protected",
@ -12,6 +13,9 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {
"advanced": true,
},
"path": "/strategies", "path": "/strategies",
"title": "Strategies", "title": "Strategies",
"type": "protected", "type": "protected",
@ -19,6 +23,9 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {
"adminSettings": true,
},
"path": "/history", "path": "/history",
"title": "Event History", "title": "Event History",
"type": "protected", "type": "protected",
@ -26,6 +33,7 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {},
"path": "/archive", "path": "/archive",
"title": "Archived Toggles", "title": "Archived Toggles",
"type": "protected", "type": "protected",
@ -33,6 +41,9 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {
"advanced": true,
},
"path": "/applications", "path": "/applications",
"title": "Applications", "title": "Applications",
"type": "protected", "type": "protected",
@ -41,6 +52,9 @@ Array [
"component": [Function], "component": [Function],
"flag": "C", "flag": "C",
"layout": "main", "layout": "main",
"menu": Object {
"advanced": true,
},
"path": "/context", "path": "/context",
"title": "Context Fields", "title": "Context Fields",
"type": "protected", "type": "protected",
@ -49,6 +63,7 @@ Array [
"component": [Function], "component": [Function],
"flag": "P", "flag": "P",
"layout": "main", "layout": "main",
"menu": Object {},
"path": "/projects", "path": "/projects",
"title": "Projects", "title": "Projects",
"type": "protected", "type": "protected",
@ -56,6 +71,9 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {
"advanced": true,
},
"path": "/tag-types", "path": "/tag-types",
"title": "Tag types", "title": "Tag types",
"type": "protected", "type": "protected",
@ -64,6 +82,9 @@ Array [
"component": [Function], "component": [Function],
"hidden": false, "hidden": false,
"layout": "main", "layout": "main",
"menu": Object {
"advanced": true,
},
"path": "/addons", "path": "/addons",
"title": "Addons", "title": "Addons",
"type": "protected", "type": "protected",
@ -71,6 +92,9 @@ Array [
Object { Object {
"component": [Function], "component": [Function],
"layout": "main", "layout": "main",
"menu": Object {
"advanced": true,
},
"path": "/reporting", "path": "/reporting",
"title": "Reporting", "title": "Reporting",
"type": "protected", "type": "protected",
@ -79,6 +103,7 @@ Array [
"component": [Function], "component": [Function],
"hidden": false, "hidden": false,
"layout": "main", "layout": "main",
"menu": Object {},
"path": "/admin", "path": "/admin",
"title": "Admin", "title": "Admin",
"type": "protected", "type": "protected",

View File

@ -49,6 +49,7 @@ export const routes = [
component: CreateFeatureToggle, component: CreateFeatureToggle,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/features/copy/:copyToggle', path: '/features/copy/:copyToggle',
@ -57,6 +58,7 @@ export const routes = [
component: CopyFeatureToggle, component: CopyFeatureToggle,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/features/:activeTab/:name', path: '/features/:activeTab/:name',
@ -65,6 +67,7 @@ export const routes = [
component: ViewFeatureToggle, component: ViewFeatureToggle,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/features', path: '/features',
@ -72,6 +75,7 @@ export const routes = [
component: Features, component: Features,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
// Strategies // Strategies
@ -82,6 +86,7 @@ export const routes = [
component: CreateStrategies, component: CreateStrategies,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/strategies/:activeTab/:strategyName', path: '/strategies/:activeTab/:strategyName',
@ -90,6 +95,7 @@ export const routes = [
component: StrategyView, component: StrategyView,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/strategies', path: '/strategies',
@ -97,6 +103,7 @@ export const routes = [
component: Strategies, component: Strategies,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { advanced: true },
}, },
// History // History
@ -107,6 +114,7 @@ export const routes = [
component: HistoryTogglePage, component: HistoryTogglePage,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/history', path: '/history',
@ -114,6 +122,7 @@ export const routes = [
component: HistoryPage, component: HistoryPage,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { adminSettings: true },
}, },
// Archive // Archive
@ -124,6 +133,7 @@ export const routes = [
component: ShowArchive, component: ShowArchive,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/archive', path: '/archive',
@ -131,6 +141,7 @@ export const routes = [
component: Archive, component: Archive,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
// Applications // Applications
@ -141,6 +152,7 @@ export const routes = [
component: ApplicationView, component: ApplicationView,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/applications', path: '/applications',
@ -148,6 +160,7 @@ export const routes = [
component: Applications, component: Applications,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { advanced: true },
}, },
// Context // Context
@ -158,6 +171,7 @@ export const routes = [
component: CreateContextField, component: CreateContextField,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/context/edit/:name', path: '/context/edit/:name',
@ -166,6 +180,7 @@ export const routes = [
component: EditContextField, component: EditContextField,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/context', path: '/context',
@ -174,6 +189,7 @@ export const routes = [
type: 'protected', type: 'protected',
flag: C, flag: C,
layout: 'main', layout: 'main',
menu: { advanced: true },
}, },
// Project // Project
@ -184,6 +200,7 @@ export const routes = [
component: CreateProject, component: CreateProject,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/projects/edit/:id', path: '/projects/edit/:id',
@ -192,6 +209,7 @@ export const routes = [
component: EditProject, component: EditProject,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/projects/view/:id', path: '/projects/view/:id',
@ -200,6 +218,7 @@ export const routes = [
component: ViewProject, component: ViewProject,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/projects/:id/access', path: '/projects/:id/access',
@ -208,6 +227,7 @@ export const routes = [
component: EditProjectAccess, component: EditProjectAccess,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/projects/:id', path: '/projects/:id',
@ -217,6 +237,7 @@ export const routes = [
flag: P, flag: P,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/projects', path: '/projects',
@ -225,6 +246,7 @@ export const routes = [
flag: P, flag: P,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
@ -234,6 +256,7 @@ export const routes = [
component: CreateTagType, component: CreateTagType,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/tag-types/edit/:name', path: '/tag-types/edit/:name',
@ -242,6 +265,7 @@ export const routes = [
component: EditTagType, component: EditTagType,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/tag-types', path: '/tag-types',
@ -249,6 +273,7 @@ export const routes = [
component: ListTagTypes, component: ListTagTypes,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { advanced: true },
}, },
{ {
@ -258,6 +283,7 @@ export const routes = [
component: CreateTag, component: CreateTag,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/tags', path: '/tags',
@ -266,6 +292,7 @@ export const routes = [
hidden: true, hidden: true,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
// Addons // Addons
@ -276,6 +303,7 @@ export const routes = [
component: AddonsCreate, component: AddonsCreate,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/addons/edit/:id', path: '/addons/edit/:id',
@ -284,6 +312,7 @@ export const routes = [
component: AddonsEdit, component: AddonsEdit,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/addons', path: '/addons',
@ -292,6 +321,7 @@ export const routes = [
hidden: false, hidden: false,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { advanced: true },
}, },
{ {
path: '/reporting', path: '/reporting',
@ -299,6 +329,7 @@ export const routes = [
component: Reporting, component: Reporting,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { advanced: true },
}, },
// Admin // Admin
{ {
@ -308,6 +339,7 @@ export const routes = [
component: AdminApi, component: AdminApi,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { advanced: true, adminSettings: true },
}, },
{ {
path: '/admin/users', path: '/admin/users',
@ -316,6 +348,7 @@ export const routes = [
component: AdminUsers, component: AdminUsers,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { adminSettings: true },
}, },
{ {
path: '/admin/auth', path: '/admin/auth',
@ -324,6 +357,7 @@ export const routes = [
component: AdminAuth, component: AdminAuth,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { adminSettings: true },
}, },
{ {
path: '/admin-invoices', path: '/admin-invoices',
@ -332,6 +366,7 @@ export const routes = [
hidden: true, hidden: true,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: { adminSettings: true },
}, },
{ {
path: '/admin', path: '/admin',
@ -340,6 +375,7 @@ export const routes = [
hidden: false, hidden: false,
type: 'protected', type: 'protected',
layout: 'main', layout: 'main',
menu: {},
}, },
{ {
path: '/login', path: '/login',
@ -348,6 +384,7 @@ export const routes = [
type: 'unprotected', type: 'unprotected',
hidden: true, hidden: true,
layout: 'standalone', layout: 'standalone',
menu: {},
}, },
{ {
path: '/new-user', path: '/new-user',
@ -356,6 +393,7 @@ export const routes = [
component: NewUser, component: NewUser,
type: 'unprotected', type: 'unprotected',
layout: 'standalone', layout: 'standalone',
menu: {},
}, },
{ {
path: '/reset-password', path: '/reset-password',
@ -364,6 +402,7 @@ export const routes = [
component: ResetPassword, component: ResetPassword,
type: 'unprotected', type: 'unprotected',
layout: 'standalone', layout: 'standalone',
menu: {},
}, },
{ {
path: '/forgotten-password', path: '/forgotten-password',
@ -372,6 +411,7 @@ export const routes = [
component: ForgottenPassword, component: ForgottenPassword,
type: 'unprotected', type: 'unprotected',
layout: 'standalone', layout: 'standalone',
menu: {},
}, },
]; ];
@ -382,27 +422,12 @@ export const baseRoutes = routes
.filter(route => !route.parent); .filter(route => !route.parent);
const computeRoutes = () => { const computeRoutes = () => {
const apiAccess = routes.find(route => route.path === '/admin/api'); const mainNavRoutes = baseRoutes.filter(route => route.menu.advanced);
const mainNavRoutes = const adminRoutes = routes.filter(route => route.menu.adminSettings);
baseRoutes.filter(
route =>
route.path !== '/admin' &&
route.path !== '/logout' &&
route.path !== '/history'
) || [];
mainNavRoutes.push(apiAccess);
const computedRoutes = { const computedRoutes = {
mainNavRoutes, mainNavRoutes,
adminRoutes: adminRoutes,
routes.filter(
route =>
(route.path.startsWith('/admin') &&
route.path !== '/admin-invoices' &&
route.path !== '/admin') ||
route.path === '/history'
) || [],
}; };
return () => { return () => {
return computedRoutes; return computedRoutes;

View File

@ -1,7 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, TextField, Typography } from '@material-ui/core'; import { Button, TextField } from '@material-ui/core';
import ConditionallyRender from '../../common/ConditionallyRender'; import ConditionallyRender from '../../common/ConditionallyRender';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import { useCommonStyles } from '../../../common.styles'; import { useCommonStyles } from '../../../common.styles';
@ -9,6 +9,7 @@ import { useStyles } from './PasswordAuth.styles';
import useQueryParams from '../../../hooks/useQueryParams'; import useQueryParams from '../../../hooks/useQueryParams';
import AuthOptions from '../common/AuthOptions/AuthOptions'; import AuthOptions from '../common/AuthOptions/AuthOptions';
import DividerText from '../../common/DividerText/DividerText'; import DividerText from '../../common/DividerText/DividerText';
import { Alert } from '@material-ui/lab';
const PasswordAuth = ({ authDetails, passwordLogin }) => { const PasswordAuth = ({ authDetails, passwordLogin }) => {
const commonStyles = useCommonStyles(); const commonStyles = useCommonStyles();
@ -57,6 +58,10 @@ const PasswordAuth = ({ authDetails, passwordLogin }) => {
})); }));
setPassword(''); setPassword('');
setUsername(''); setUsername('');
} else if (error.statusCode === 401) {
setErrors({
apiError: 'Invalid password and username combination.',
});
} else { } else {
setErrors({ setErrors({
apiError: 'Unknown error while trying to authenticate.', apiError: 'Unknown error while trying to authenticate.',
@ -70,9 +75,15 @@ const PasswordAuth = ({ authDetails, passwordLogin }) => {
return ( return (
<form onSubmit={handleSubmit} action={authDetails.path}> <form onSubmit={handleSubmit} action={authDetails.path}>
<Typography variant="subtitle2" className={styles.apiError}> <ConditionallyRender
condition={apiError}
show={
<Alert severity="error" className={styles.apiError}>
{apiError} {apiError}
</Typography> </Alert>
}
/>
<div <div
className={classnames( className={classnames(
styles.contentContainer, styles.contentContainer,

View File

@ -14,5 +14,6 @@ export const useStyles = makeStyles(theme => ({
}, },
apiError: { apiError: {
color: theme.palette.error.main, color: theme.palette.error.main,
marginBottom: '0.5rem',
}, },
})); }));

View File

@ -9,14 +9,12 @@ import {
Select, Select,
InputLabel, InputLabel,
} from '@material-ui/core'; } from '@material-ui/core';
import { Link } from 'react-router-dom';
import classnames from 'classnames'; import classnames from 'classnames';
import { useStyles } from './UserProfileContent.styles'; import { useStyles } from './UserProfileContent.styles';
import { useCommonStyles } from '../../../../common.styles'; import { useCommonStyles } from '../../../../common.styles';
import { Alert } from '@material-ui/lab'; import { Alert } from '@material-ui/lab';
import EditProfile from '../EditProfile/EditProfile'; import EditProfile from '../EditProfile/EditProfile';
import legacyStyles from '../../user.module.scss'; import legacyStyles from '../../user.module.scss';
import usePermissions from '../../../../hooks/usePermissions';
import { getBasePath } from '../../../../utils/format-path'; import { getBasePath } from '../../../../utils/format-path';
const UserProfileContent = ({ const UserProfileContent = ({
@ -32,7 +30,6 @@ const UserProfileContent = ({
const [updatedPassword, setUpdatedPassword] = useState(false); const [updatedPassword, setUpdatedPassword] = useState(false);
const [edititingProfile, setEditingProfile] = useState(false); const [edititingProfile, setEditingProfile] = useState(false);
const styles = useStyles(); const styles = useStyles();
const { isAdmin } = usePermissions();
const setLocale = value => { const setLocale = value => {
updateSettingLocation('locale', value); updateSettingLocation('locale', value);
@ -131,17 +128,6 @@ const UserProfileContent = ({
</FormControl> </FormControl>
</div> </div>
<div className={commonStyles.divider} /> <div className={commonStyles.divider} />
<ConditionallyRender
condition={isAdmin()}
show={
<Link
to="/admin-invoices"
className={styles.link}
>
Account and billing
</Link>
}
/>
<a <a
className={styles.link} className={styles.link}
href="https://www.getunleash.io/privacy-policy" href="https://www.getunleash.io/privacy-policy"