1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-03-09 00:18:26 +01: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 => ({
contentSpacingY: {
'& > *': {
margin: '0.5rem 0',
marginTop: '0.5rem !important',
marginBottom: '0.5rem !important',
},
},
contentSpacingYLarge: {
'& > *': {
margin: '1.5rem 0',
marginTop: '1.5rem !important',
marginBottom: '1.5rem !important',
},
},
contentSpacingX: {
'& > *': {
margin: '0 0.8rem',
marginRight: '0.8rem !important',
marginLeft: '0.8rem !important',
},
},
divider: {

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,18 @@ export const useStyles = makeStyles(theme => ({
},
searchBarContainer: {
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: {
border: `2px dashed ${theme.palette.borders.main}`,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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