Commit da432c6d authored by Oleksii Savran's avatar Oleksii Savran Committed by Matija Obreza
Browse files

Added header and side menu for AdminLayout

parent 8bdeea2c
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 22.7 22.7" style="enable-background:new 0 0 22.7 22.7;" xml:space="preserve">
<style type="text/css">
.st0{fill:#ffffff;}
</style>
<path class="st0" d="M11.3,0C5.1,0,0,5.1,0,11.3c0,6.3,5.1,11.3,11.3,11.3s11.3-5.1,11.3-11.3C22.7,5.1,17.6,0,11.3,0z M11.4,19.7
c0,0.1-0.1,0.2,0,0.2c0,0,0,0.1,0,0.1c0,0.1,0,0.1,0,0.2c0,0,0,0.1-0.1,0.1l-0.1,0.1c-2.2-0.6-4-2.3-5.4-4c-1.5-1.9-2.7-4.2-3.1-6.6
C2.5,8.5,2.5,7.2,3,5.9c2.5,1.6,4.6,3.9,6.2,6.4C10.5,14.5,11.4,17,11.4,19.7C11.4,19.6,11.4,19.6,11.4,19.7z M11.5,11.7
c0,0-0.1,0.1-0.1,0.1c0,0,0,0,0,0c0,0-0.1,0-0.1,0.1c0,0,0,0-0.1,0l-0.1,0c-0.9-1-1.3-2.4-1.5-3.7C9.4,6.9,9.5,5.4,10,4.1
c0.3-0.7,0.7-1.4,1.3-1.9c0.8,1.6,1.2,3.3,1.2,5.1C12.6,8.8,12.3,10.4,11.5,11.7C11.5,11.7,11.5,11.7,11.5,11.7z M17.3,12.6
c-1.2,1.7-2.8,3.2-4.7,4c0,0,0,0,0,0c-0.1,0-0.1,0-0.2,0c0,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0l-0.1-0.1
c-0.2-1.8,0.4-3.7,1.3-5.3c1-1.7,2.3-3.3,4-4.4c0.9-0.6,1.9-1,3-1C19.7,8.3,18.7,10.6,17.3,12.6z"/>
</svg>
......@@ -103,6 +103,8 @@
}
},
"admin": {
"admin": "Admin",
"genesys": "genesys",
"menu": {
"userManagement": "User management",
"users": "Users",
......
......@@ -102,6 +102,8 @@
}
},
"admin": {
"admin": "Admin",
"genesys": "genesys",
"menu": {
"userManagement": "User management",
"users": "Users",
......
import * as React from 'react';
import { translate } from 'react-i18next';
import UsersIcon from '@material-ui/icons/AccessibleForward';
import RequestsIcon from '@material-ui/icons/ShoppingCart';
import RepositoryIcon from '@material-ui/icons/FolderShared';
import ClusterIcon from '@material-ui/icons/DeveloperBoard';
import LogIcon from '@material-ui/icons/FilterList';
import ShowChartIcon from '@material-ui/icons/ShowChart';
import PageLayout from './PageLayout';
import MenuItem from 'ui/common/Menu';
import renderRoutes from 'ui/renderRoutes';
const Menu = ({t}) => (
<div>
<MenuItem label={ t('admin.menu.userManagement') } to="/admin/users" icon={ <UsersIcon /> }>
<MenuItem label={ t('admin.menu.users') } to="/admin/users" />
<MenuItem label={ t('admin.menu.oAuthClients') } to="/admin/oauth" />
</MenuItem>
<MenuItem label="KPI" to="/admin/kpi/" icon={ <ShowChartIcon /> } />
<MenuItem label={ t('admin.menu.requests') } to="/admin/requests" icon={ <RequestsIcon /> } />
<MenuItem label={ t('admin.menu.fileRepository') } to="/admin/repository/f/" icon={ <RepositoryIcon /> } />
<MenuItem label={ t('admin.menu.cluster') } to="/admin/hazelcast" icon={ <ClusterIcon /> }>
<MenuItem label={ t('admin.menu.hazelcast') } to="/admin/hazelcast" />
<MenuItem label={ t('admin.menu.elasticsearch') } to="/admin/elastic" />
<MenuItem label={ t('admin.menu.caches') } to="/admin/cache" />
</MenuItem>
<MenuItem label={ t('admin.menu.loggers') } to="/admin/log" icon={ <LogIcon /> } />
</div>
);
import AdminHeader from 'ui/layout/Header/AdminHeader';
const Layout = ({route, match, t}: { route: any, match: any, t: any}) => (
<PageLayout sidebar={ <Menu t={ t } /> }>
const ADMIN_MENUS = [
{
to: '/admin/users',
label: 'admin.menu.userManagement',
subMenus: [
{
to: '/admin/users',
label: 'admin.menu.userManagement',
},
{
to: '/admin/oauth',
label: 'admin.menu.oAuthClients',
},
],
},
{
to: '/admin/kpi/',
label: 'KPI',
},
{
to: '/admin/requests',
label: 'admin.menu.requests',
},
{
to: '/admin/repository/f/',
label: 'admin.menu.fileRepository',
},
{
to: '/admin/hazelcast',
label: 'admin.menu.cluster',
subMenus: [
{
to: '/admin/hazelcast',
label: 'admin.menu.hazelcast',
},
{
to: '/admin/elastic',
label: 'admin.menu.elasticsearch',
},
{
to: '/admin/cache',
label: 'admin.menu.caches',
},
],
},
{
to: '/admin/log',
label: 'admin.menu.loggers',
},
];
const Layout = ({route, match, t, location}: { route: any, match: any, t: any, location: any}) => (
<div className="admin-layout">
<AdminHeader pathes={ ADMIN_MENUS } location={ location }/>
{ renderRoutes(route.routes, match.path) }
</PageLayout>
</div>
);
export default translate()(Layout);
import * as React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link, withRouter } from 'react-router-dom';
import { translate } from 'react-i18next';
import { loginAppRequest } from 'actions/login';
import { logoutRequest } from 'user/actions/public';
import AppBar from '@material-ui/core/AppBar';
import { withStyles } from '@material-ui/core/styles';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import { ROLE_ADMINISTRATOR, ROLE_USER } from 'constants/userRoles';
import UserLoginMenu from './UserLoginMenu';
import UserMenu from './UserMenu';
import AdminLeftMenu from './AdminLeftMenu';
import LanguageList from './LanguageList';
import AdminHeaderMenu from 'ui/layout/Header/AdminHeaderMenu';
const styleSheet = (theme) => ({
root: {
marginTop: 90,
width: '100%',
},
flex: {
flex: 1,
},
headerRoot: {
backgroundColor: '#fff',
height: 'auto',
[theme.breakpoints.down('md')]: {
height: '3.5rem',
},
},
blockHeader: {
padding: '0',
height: '83px',
[theme.breakpoints.down('md')]: {
alignItems: 'normal' as 'normal',
height: '3.5rem',
},
},
/*tslint:disable*/
underlinedLogo: {
display: 'flex',
flexDirection: 'row' as 'row',
alignItems: 'center' as 'center',
justifyContent: 'space-between' as 'space-between',
borderBottom: 'solid #cacaca 3px',
boxSizing: 'border-box' as 'border-box',
[theme.breakpoints.down('md')]: {
height: '3.5rem',
},
},
mainIcon: {
height: '45px',
},
iconBack: {
marginTop: '5px',
marginBottom: '5px',
fontSize: '8.5px',
fontWeight: 'bold' as 'bold',
textAlign: 'center' as 'center',
color: '#fff',
},
iconBackground: {
backgroundColor: '#88B941',
height: '80px',
width: '85px',
display: 'flex' as 'flex',
flexDirection: 'column' as 'column',
justifyContent: 'flex-end' as 'flex-end',
[theme.breakpoints.down('md')]: {
justifyContent: 'center' as 'center',
},
},
logoIcon: {
height: '27px',
display: 'inline-block',
verticalAlign: 'middle',
},
admin: {
fontSize: '2rem',
fontWeight: 'bold' as 'bold',
display: 'inline-block',
verticalAlign: 'middle',
color: '#000000',
margin: '0 40px 0 20px',
userSelect: 'none' as 'none',
[theme.breakpoints.down('md')]: {
fontSize: '1.5rem',
},
[theme.breakpoints.down('xs')]: {
margin: '0 20px 0 10px',
},
},
menuBtn: {
'&:hover': {
backgroundColor: 'transparent' as 'transparent',
}
},
menuWrapper: {
borderBottom: 'solid #cacaca 3px',
backgroundColor: '#88B941',
width: '3.6rem',
height: '3.5rem',
boxSizing: 'border-box' as 'border-box',
},
mobileHidden: {
[theme.breakpoints.down('md')]: {
display: 'none'
},
},
navWrapper: {
display: 'flex' as 'flex',
flexDirection: 'row' as 'row',
justifyContent: 'space-between' as 'space-between',
alignItems: 'center' as 'center',
height: '100%',
borderBottom: 'solid #999488 3px',
boxSizing: 'border-box' as 'border-box',
paddingLeft: '120px',
paddingRight: '20px',
[theme.breakpoints.down('md')]: {
height: '3.5rem',
justifyContent: 'flex-end' as 'flex-end',
},
[theme.breakpoints.down('xs')]: {
paddingLeft: '20px',
},
},
headerMargin: {
marginBottom: '83px',
[theme.breakpoints.down('md')]: {
marginBottom: '49px',
},
},
/* tslint:enable */
});
interface IHeaderProps extends React.ClassAttributes<any> {
login: any;
logoutRequest: () => Promise<any>;
loginAppRequest: () => Promise<any>;
history: any;
classes?: any;
t: any;
pathes: object[];
location: string;
}
class AdminHeader extends React.Component<IHeaderProps | any, any> {
public constructor(props: any) {
super(props);
this.state = {
open: false,
};
}
private logout = () => {
this.props.logoutRequest()
.then(() => this.props.loginAppRequest())
.then((data) => {
this.props.history.push('/login');
});
}
private hasRole = (roles: string[]): boolean => {
return this.props.login.authorities
.map((e) => roles.indexOf(e) > -1)
.reduce((p, c) => p || c);
}
private renderLogin = (roles: string[]) => {
if (this.hasRole(roles)) {
return <UserMenu userName={ this.props.login.user_name } logoutRequest={ this.logout } color="default"/>;
} else {
return <UserLoginMenu/>;
}
}
private toggleDrawer = (flag) => {
this.setState({open: flag});
}
private handleLeftMenuClose = () => this.toggleDrawer(false);
private handleLeftMenuOpen = () => this.toggleDrawer(true);
public render() {
const {classes, t, pathes, location} = this.props;
return (
<div className={ `header-bar ${ classes.headerMargin }` }>
<AppBar position="fixed" className={ classes.headerRoot }>
<Toolbar className={ classes.blockHeader }>
<div className="mobile-navigation-block">
<div className={ classes.menuWrapper }>
<IconButton className={ classes.menuBtn } aria-label="Menu" color="secondary"
onClick={ this.handleLeftMenuOpen }>
<img src="images/GENESYS-ICON_white.svg" className={ classes.logoIcon }/>
</IconButton>
</div>
<AdminLeftMenu open={ this.state.open } closeMenu={ this.handleLeftMenuClose } pathes={ pathes }
location={ location }/>
</div>
<div className={ classes.underlinedLogo }>
<Link to="/admin" className={ `${this.props.classes.navLogo} ${classes.mobileHidden}` }>
<div className={ classes.iconBackground }>
<img src="images/GENESYS-ICON_white.svg" className={ classes.mainIcon }/>
<div className={ classes.iconBack }>{ t('common:action.backTo', { where: t('admin.genesys') }).toUpperCase() }</div>
</div>
</Link>
<div className={ classes.admin }>{ t('admin.admin') }</div>
</div>
<div className={ `${classes.flex} ${this.props.classes.navWrapper}` }>
<AdminHeaderMenu t={ t } location={ location } pathes={ pathes }/>
<div
className={ `float-right` }>{ this.renderLogin([ROLE_USER, ROLE_ADMINISTRATOR]) }</div>
<div>
<LanguageList color="default"/>
</div>
</div>
</Toolbar>
</AppBar>
</div>
);
}
}
const mapStateToProps = (state) => ({
login: state.login,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loginAppRequest,
logoutRequest,
}, dispatch);
export default translate()(withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styleSheet)(AdminHeader))));
import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import MenuItem from 'ui/layout/Header/AdminHeaderMenuItem';
const styleSheet = (theme) => ({
/* tslint:disable */
nav: {
display: 'flex' as 'flex',
flexDirection: 'row' as 'row',
width: '100%',
height: '100%',
[theme.breakpoints.down('md')]: {
display: 'none'
},
},
/* tslint:enable */
});
interface IMenuProps extends React.ClassAttributes<any> {
classes: any;
t: any;
location: any;
pathes: object[];
}
class AdminHeaderMenu extends React.Component<IMenuProps, any> {
private renderMenu = (path: any) => {
const {t} = this.props;
return (
path.subMenus ? (
<MenuItem
label={ t(path.label) }
to={ path.to }
active={ location.pathname === path.to || path.subMenus.some((subMenu) => subMenu.to === location.pathname) }
key={ path.to }
children={ path.subMenus.map(this.renderSubMenu) }
/>
) : (
<MenuItem
label={ t(path.label) }
to={ path.to }
active={ location.pathname === path.to }
key={ path.to }
/>
)
);
}
private renderSubMenu = (path: any) => {
const {t} = this.props;
return (
<MenuItem
label={ t(path.label) }
to={ path.to }
activeSub={ location.pathname === path.to }
key={ path.to }
/>
);
}
public render() {
const {classes, location, pathes} = this.props;
console.log(location.pathname);
return (
<nav className={ classes.nav }>
{ pathes.map(this.renderMenu) }
</nav>
);
}
}
export default withStyles(styleSheet)(AdminHeaderMenu);
import * as React from 'react';
import { translate } from 'react-i18next';
import { withStyles } from '@material-ui/core/styles';
import { Link } from 'react-router-dom';
import Collapse from '@material-ui/core/Collapse/Collapse';
/*tslint:disable*/
const style = (theme) => ({
menuItem: {
backgroundColor: '#fff',
height: '100%',
position: 'relative' as 'relative',
overflowX: 'visible' as 'visible',
boxSizing: 'border-box' as 'border-box',
borderTop: 'solid 4px transparent',
borderBottom: 'solid 4px transparent',
transition: 'all 0.1s',
},
hover: {
backgroundColor: '#eeede7',
borderBottom: 'solid 4px #929292',
},
menuLink: {
width: 'auto' as 'auto',
height: '100%',
boxSizing: 'border-box' as 'border-box',
display: 'flex' as 'flex',
alignItems: 'center',
padding: '0 1.42rem',
outline: 'none',
},
linkContent: {
height: '1.5rem',
display: 'flex' as 'flex',
alignItems: 'center' as 'center',
color: 'black',
},
linkLabel: {
fontSize: '1.25rem',
fontWeight: 'bold' as 'bold',
},
children: {
'& > div > a > div > span': {
fontSize: '1.14rem',
},
'& > div': {
height: '3rem',
borderTop: 'solid 1px transparent',
borderBottom: 'solid 1px #929292',
backgroundColor: '#eeede7',
transition: 'all 0.1s',
'&:hover': {
backgroundColor: '#c3c0b0',
},
},
borderBottom: 'solid 2px #b7b5b2',
},
collapsed: {
minWidth: '100%',
marginTop: '4px',
position: 'absolute' as 'absolute'
},
active: {
borderBottom: 'solid 4px #5a9d32',
},
activeSub: {
backgroundColor: '#c3c0b0!important',
'&:hover': {
backgroundColor: '#938f81!important'
}
},
});
/*tslint:enable*/
interface IMenuItemProps extends React.ClassAttributes<any> {
classes?: any;
children?: any;
label: any;
to: string;
t?: any;
active?: boolean;
activeSub?: boolean;
}
class MenuItem extends React.Component<IMenuItemProps, any> {
public constructor(props: any) {
super(props);
this.state = {
open: false,
};
}
private toggleDrawer = (flag) => {
this.setState({open: flag});
}
private openMenu = () => this.toggleDrawer(true);
private closeMenu = () => this.toggleDrawer(false);
public render() {
const {to, label, children, classes, t, activeSub, active} = this.props;
return (
<div
className={ `${classes.menuItem} ${this.state.open && classes.hover} ${ active && classes.active } ${ activeSub && classes.activeSub}` }
onMouseEnter={ this.openMenu } onMouseLeave={ this.closeMenu }
>
<Link to={ to } className={ `${ classes.menuLink }` }>
<div className={ classes.linkContent }>
<span className={ classes.linkLabel }>{ typeof label === 'string' ? t(label) : label }</span>
</div>
</Link>
{ children &&
<Collapse className={ classes.collapsed } in={ this.state.open }>
<div className={ `${classes.children} ${this.state.open && classes.open}` }>
{ children }
</div>
</Collapse>
}
</div>
);
}
}
export default translate()(withStyles(style)(MenuItem));
import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import withWidth from '@material-ui/core/withWidth';
import { translate } from 'react-i18next';
import Drawer from '@material-ui/core/Drawer';
import { NavLink } from 'react-router-dom';