Commit b8908798 authored by Oleksii Savran's avatar Oleksii Savran Committed by Viacheslav Pavlov

User and language menu update

Changed login menu

Changed login actions

changed UserLoginMenu behavior

Added "No redirect on log in/out" behavior
parent 0f0eb05f
......@@ -73,7 +73,9 @@ export const createPureApiCaller = (method) => {
} else {
log(`Call failed. Err: ${err}`);
dispatch(showSnackbar(`API error: ${err.message} ${err.response.data.error || ''}`));
throw new Error(`API error: ${err}`);
const errorMessage = (err.response && err.response.data && err.response.data.error_description) ?
err.response.data.error_description : `API error ${err}`;
throw new Error(errorMessage);
}
});
};
......
import { COLLAPSE_SIDEBAR } from 'constants/layout';
import { COLLAPSE_SIDEBAR, LOGIN_MENU_FOCUS } from 'constants/layout';
export const collapseSidebar = (isOpen: boolean) => (dispatch) => {
dispatch({type: COLLAPSE_SIDEBAR, payload: isOpen});
};
export const loginMenuFocus = (isFocused: boolean) => (dispatch) => {
dispatch({type: LOGIN_MENU_FOCUS, payload: isFocused});
};
export const COLLAPSE_SIDEBAR = 'COLLAPSE_SIDEBAR';
export const LOGIN_MENU_FOCUS = 'LOGIN_MENU_FOCUS';
......@@ -4,17 +4,16 @@ import { withStyles} from '@material-ui/core/styles';
import languages from 'data/Languages';
import { withRouter } from 'react-router-dom';
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
import { translate } from 'react-i18next';
import { LinkMenuItem, CollapsibleMenu } from 'ui/layout/headers/v1/MenuItem';
interface ILanguageListProps extends React.ClassAttributes<any> {
classes: any;
i18n: any;
location: any;
color?: any;
theme?: any;
}
const styles = {
......@@ -22,12 +21,13 @@ const styles = {
langMenuBtn: {
minWidth: '48px',
fontSize: '1.14rem',
height: '100%',
paddingRight: 0,
textTransform: 'capitalize' as 'capitalize',
'&:hover': {
background: 'inherit',
color: '#88ba42',
// color: '#88ba42',
textDecoration: 'none',
},
'html[dir="rtl"] &' : {
......@@ -35,42 +35,19 @@ const styles = {
paddingRight: '16px !important',
},
},
menu: {
'& > div+div': {
top: '3.57rem !important',
'html[dir="ltr"] &' : {
left: 'auto !important',
right: '1.43rem',
},
'html[dir="rtl"] &' : {
right: 'auto !important',
left: '1.43rem',
},
},
'& ul': {
padding: '0.71rem 0',
'& a:focus': {
outline: 'none',
textDecoration: 'none',
background: '#e7e5df',
},
'& li': {
paddingLeft: '1.43rem',
fontFamily: 'Roboto-Regular',
fontSize: '1rem',
color: '#2B2924',
'&:hover, &:focus': {
background: '#e7e5df',
},
},
},
root: {
height: '100%',
position: 'relative' as 'relative',
overflowX: 'visible' as 'visible',
},
menuPosition: {
right: 0,
marginTop: 0,
'html[dir="rtl"] &' : {
left: 0,
right: 'auto',
},
}
};
class LanguageList extends React.Component<ILanguageListProps, any> {
......@@ -79,22 +56,24 @@ class LanguageList extends React.Component<ILanguageListProps, any> {
super(props);
this.state = {
anchorEl: null,
open: false,
};
}
public handleClick = (event) => {
this.setState({ open: true, anchorEl: event.currentTarget });
}
private toggleDrawer = (flag) => {
this.setState({open: flag});
};
private openMenu = () => this.toggleDrawer(true);
public handleRequestClose = () => {
this.setState({ open: false });
private closeMenu = () => this.toggleDrawer(false);
private handleClick = () => {
this.state.open ? this.closeMenu() : this.openMenu();
}
public render() {
const { classes, i18n, color, location } = this.props;
const { classes, i18n, color, location, theme } = this.props;
let currentLang = i18n.language;
languages.some((item, i, arr) => {
if (item.short === i18n.language) {
......@@ -108,31 +87,32 @@ class LanguageList extends React.Component<ILanguageListProps, any> {
};
return (
<div>
<div
className={classes.root}
onMouseEnter={ this.openMenu } onMouseLeave={ this.closeMenu }
onClick={ this.handleClick }
>
<Button
className={ classes.langMenuBtn }
color={ color ? color : 'secondary' }
aria-owns={ this.state.open ? 'lang-list' : null }
aria-haspopup="true"
onClick={ this.handleClick }
>
{ currentLang }
<ArrowDropDown style={ arrow } viewBox="0 0 16 24"/>
</Button>
<Menu
className={ classes.menu }
id="lang-list"
anchorEl={ this.state.anchorEl }
open={ this.state.open }
onClose={ this.handleRequestClose }
>
<CollapsibleMenu className={ classes.menuPosition } open={ this.state.open } theme={ theme }>
{
// Using <a href="ru/" will reload app from server
languages.map((lang, index) => (
<a key={ (lang.short) } href={ `${lang.short === 'en' ? '' : lang.short}${location.pathname}` }><MenuItem>{ `${lang.label}` }</MenuItem></a>
languages.map((lang) => (
<LinkMenuItem
key={ (lang.short) }
href={ `${lang.short === 'en' ? '' : lang.short}${location.pathname}` }
label={ lang.label }
theme={ theme }
/>
))
}
</Menu>
</CollapsibleMenu>
</div>
);
}
......
import * as React from 'react';
import {withStyles} from '@material-ui/core/styles';
import {translate} from 'react-i18next';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { loginAction, googleLogin } from 'user/actions/public';
import { loginMenuFocus } from 'actions/layout';
import {Link} from 'react-router-dom';
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
import { LinkMenuItem, CollapsibleMenu } from 'ui/layout/headers/v1/MenuItem';
import LoginForm from 'user/ui/c/LoginForm';
interface IUserLoginMenuProps extends React.ClassAttributes<any> {
classes: any;
t: any;
theme: any;
loginAction: (u, p) => Promise<any>;
googleLogin: (aT) => Promise<any>;
history: any;
googleClientId: string;
loginMenuIsFocused: boolean;
loginMenuFocus?: (isFocused: boolean) => void;
}
const styles = {
......@@ -18,7 +29,7 @@ const styles = {
userMenuBtn: {
padding: 0,
minWidth: '48px',
height: '100%',
'&:hover': {
background: 'inherit',
},
......@@ -32,94 +43,109 @@ const styles = {
textDecoration: 'none',
},
},
menu: {
'& > div+div': {
top: '3.57rem !important',
'html[dir="ltr"] &': {
left: 'auto !important',
right: '1.43rem',
},
'html[dir="rtl"] &': {
right: 'auto !important',
left: '1.43rem',
},
},
'& ul': {
padding: '0.71rem 0',
'& a:focus': {
outline: 'none',
textDecoration: 'none',
},
'& li': {
paddingLeft: '1.43rem',
fontFamily: 'Roboto-Regular',
fontSize: '1rem',
color: '#2B2924',
'&:hover, &:focus': {
background: '#E7E5DF',
},
},
},
root: {
height: '100%',
position: 'relative' as 'relative',
overflowX: 'visible' as 'visible',
},
menuPosition: {
right: 0,
marginTop: 0,
'html[dir="rtl"] &' : {
left: 0,
},
}
};
class UserLoginMenu extends React.Component<IUserLoginMenuProps, any> {
public handleClick = (event) => {
this.setState({open: true, anchorEl: event.currentTarget});
};
public handleRequestClose = () => {
this.setState({open: false});
};
public constructor(props: any) {
super(props);
this.state = {
anchorEl: null,
open: false,
mouseIn: false,
};
}
private toggleDrawer = (flag) => {
this.setState({open: flag});
}
private openMenu = () => this.toggleDrawer(true);
private closeMenu = () => this.toggleDrawer(false);
private handleClick = () => {
this.state.open ? this.closeMenu() : this.openMenu();
}
private onMouseLeave = () => {
this.setState({mouseIn: false});
if ( !this.props.loginMenuIsFocused) {
this.closeMenu();
}
}
private onMouseEnter = () => {
this.setState({mouseIn: true});
this.openMenu();
}
public render() {
const {classes, t} = this.props;
const { classes, t, theme, loginAction, googleLogin, loginMenuFocus, loginMenuIsFocused } = this.props;
const arrow = {
verticalAlign: 'middle',
};
return (
<div>
<div
className={classes.root}
onMouseEnter={ this.onMouseEnter }
onMouseLeave={ this.onMouseLeave }
>
<Button
className={ `${classes.userMenuBtn} ${classes.linkLogin} mr-10 ml-10` }
color="secondary"
aria-owns={this.state.open ? 'user-menu' : null}
aria-haspopup="true"
onClick={this.handleClick}
onClick={ this.handleClick }
>
{t('common.menu.login')}
<ArrowDropDown style={arrow} viewBox="0 0 16 24"/>
</Button>
<Menu
className={classes.menu}
id="user-menu"
anchorEl={this.state.anchorEl}
open={this.state.open}
onClose={this.handleRequestClose}
onClick={this.handleRequestClose}
<CollapsibleMenu
className={ classes.menuPosition }
open={ this.state.open && ( loginMenuIsFocused || this.state.mouseIn ) }
theme={ theme }
>
<Link to="/login"><MenuItem>{t('common.menu.login')}</MenuItem></Link>
<Link to="/registration"><MenuItem>{t('common.menu.register')}</MenuItem></Link>
</Menu>
<LoginForm
loginMenuFocus={ loginMenuFocus }
onTryLogin={ loginAction }
onTryGoogleLogin={ googleLogin }
googleClientId={ this.props.googleClientId }
theme={theme}
inMenu
/>
<LinkMenuItem label="common.menu.register" to="/registration" theme={ theme }/>
</CollapsibleMenu>
</div>
);
}
}
export default translate()(withStyles(styles)(UserLoginMenu));
const mapStateToProps = (state) => ({
login: state.login,
googleClientId: state.applicationConfig.googleClientId,
loginMenuIsFocused: state.user.public.loginMenuIsFocused,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loginAction,
googleLogin,
loginMenuFocus
}, dispatch);
export default translate()(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(UserLoginMenu)));
......@@ -2,13 +2,11 @@ import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import { translate } from 'react-i18next';
import { Link } from 'react-router-dom';
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import AccountCircle from '@material-ui/icons/AccountCircle';
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
import Authorize from 'ui/common/authorized/Authorize';
import { LinkMenuItem, CollapsibleMenu, ActionMenuItem } from 'ui/layout/headers/v1/MenuItem';
interface IUserMenuProps extends React.ClassAttributes<any> {
classes: any;
......@@ -16,53 +14,33 @@ interface IUserMenuProps extends React.ClassAttributes<any> {
userName: string;
t: any;
color?: any;
theme?: any;
}
const styles = {
/* tslint:disable */
userMenuBtn: {
padding: 0,
height: '100%',
minWidth: '48px',
'&:hover': {
background: 'inherit',
},
},
menu: {
'& > div+div': {
top: '3.57rem !important',
'html[dir="ltr"] &' : {
left: 'auto !important',
right: '1.43rem',
},
'html[dir="rtl"] &' : {
right: 'auto !important',
left: '1.43rem',
},
},
'& ul': {
padding: '0.71rem 0',
'& a:focus': {
outline: 'none',
textDecoration: 'none',
},
'& li': {
paddingLeft: '1.43rem',
fontFamily: 'Roboto-Regular',
fontSize: '1rem',
color: '#2B2924',
'&:hover, &:focus': {
background: '#E7E5DF',
},
},
},
root: {
height: '100%',
position: 'relative' as 'relative',
overflowX: 'visible' as 'visible',
},
menuPosition: {
right: 0,
marginTop: 0,
'html[dir="rtl"] &' : {
left: 0,
right: 'auto',
},
}
};
class UserMenu extends React.Component<IUserMenuProps, any> {
......@@ -71,52 +49,50 @@ class UserMenu extends React.Component<IUserMenuProps, any> {
super(props);
this.state = {
anchorEl: null,
open: false,
};
}
public handleClick = (event) => {
this.setState({ open: true, anchorEl: event.currentTarget });
}
private toggleDrawer = (flag) => {
this.setState({open: flag});
};
public handleRequestClose = () => {
this.setState({ open: false });
private openMenu = () => this.toggleDrawer(true);
private closeMenu = () => this.toggleDrawer(false);
private handleClick = () => {
this.state.open ? this.closeMenu() : this.openMenu();
}
public render() {
const { logoutRequest, classes, t, color } = this.props;
const { logoutRequest, classes, color, theme } = this.props;
const arrow = {
verticalAlign: 'middle',
};
return (
<div>
<div
className={classes.root}
onMouseEnter={ this.openMenu } onMouseLeave={ this.closeMenu }
onClick={ this.handleClick }
>
<Button
className={ classes.userMenuBtn }
color={ color ? color : 'secondary' }
aria-owns={ this.state.open ? 'user-menu' : null }
aria-haspopup="true"
onClick={ this.handleClick }
>
<AccountCircle/>
<ArrowDropDown style={ arrow } viewBox="0 0 16 24"/>
</Button>
<Menu
className={ classes.menu }
id="user-menu"
anchorEl={ this.state.anchorEl }
open={ this.state.open }
onClose={ this.handleRequestClose }
onClick={ this.handleRequestClose }
>
<CollapsibleMenu className={ classes.menuPosition } open={ this.state.open } theme={ theme }>
<Authorize role={ "ROLE_ADMINISTRATOR" }>
<Link to="/admin/"><MenuItem>{ t('common.menu.Admin') }</MenuItem></Link>
<LinkMenuItem label="common.menu.Admin" to="/admin/" theme={ theme }/>
</Authorize>
<Link to="/dashboard"><MenuItem>{ t('common.menu.My Dashboard') }</MenuItem></Link>
<MenuItem onClick={ logoutRequest } >{ t('common:action.logout') }</MenuItem>
</Menu>
<LinkMenuItem label="common.menu.My Dashboard" to="/dashboard" theme={ theme }/>
<ActionMenuItem label="common:action.logout" action={ logoutRequest } theme={ theme }/>
</CollapsibleMenu>
</div>
);
}
......
......@@ -39,15 +39,27 @@ const style = (theme) => ({
fontSize: '1.25rem',
fontWeight: 'bold' as 'bold',
},
action: {
display: 'flex',
alignItems: 'center',
padding: '0 1.42rem',
outline: 'none',
fontSize: '1.14rem',
fontWeight: 'bold' as 'bold',
cursor: 'pointer' as 'pointer',
userSelect: 'none' as 'none',
},
children: {
'& > div > a > div > span': {
fontSize: '1.14rem',
},
'& > div': {
backgroundColor: 'rgba(0, 0, 0, 0.07)', // '#eeede7',
},
'& > div, & > form > div': {
height: '3rem',
borderTop: 'solid 1px transparent',
borderBottom: 'solid 1px #929292',
backgroundColor: 'rgba(0, 0, 0, 0.07)', // '#eeede7',
transition: 'all 0.1s',
'&:hover': {
backgroundColor: 'rgba(0, 0, 0, 0.245)', //'#c3c0b0',
......@@ -120,11 +132,9 @@ class MenuItem extends React.Component<IMenuItemProps, any> {
</div>
</Link>
{ children &&
<Collapse className={ classes.collapsed } in={ this.state.open }>
<div className={ `${classes.children} ${this.state.open && classes.open}` } style={ {backgroundColor: `${theme.subItem}`, color: theme.subItemText} }>
{ children }
</div>
</Collapse>
<CollapsibleMenuWrapper classes={ classes } open={ this.state.open } theme={ theme }>
{ children }
</CollapsibleMenuWrapper>
}
</div>
</Authorize>
......@@ -132,4 +142,51 @@ class MenuItem extends React.Component<IMenuItemProps, any> {
}
}
const LinkItem = ({ classes, t, to, label, theme, href }: {classes: any, t: any, to?: string, label: string, theme: any, href