login drawer
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
// export const actionTypes = {
|
||||
// FAILURE: 'FAILURE',
|
||||
// INCREMENT: 'INCREMENT',
|
||||
// DECREMENT: 'DECREMENT',
|
||||
// RESET: 'RESET',
|
||||
// LOAD_DATA: 'LOAD_DATA',
|
||||
// LOAD_DATA_SUCCESS: 'LOAD_DATA_SUCCESS',
|
||||
// START_CLOCK: 'START_CLOCK',
|
||||
// TICK_CLOCK: 'TICK_CLOCK'
|
||||
// }
|
||||
|
||||
// export function failure (error) {
|
||||
// return {
|
||||
// type: actionTypes.FAILURE,
|
||||
// error
|
||||
// }
|
||||
// }
|
||||
|
||||
// export function increment () {
|
||||
// return { type: actionTypes.INCREMENT }
|
||||
// }
|
||||
|
||||
// export function decrement () {
|
||||
// return { type: actionTypes.DECREMENT }
|
||||
// }
|
||||
|
||||
// export function reset () {
|
||||
// return { type: actionTypes.RESET }
|
||||
// }
|
||||
|
||||
// export function loadData () {
|
||||
// return { type: actionTypes.LOAD_DATA }
|
||||
// }
|
||||
|
||||
// export function loadDataSuccess (data) {
|
||||
// return {
|
||||
// type: actionTypes.LOAD_DATA_SUCCESS,
|
||||
// data
|
||||
// }
|
||||
// }
|
||||
|
||||
// export function startClock () {
|
||||
// return { type: actionTypes.START_CLOCK }
|
||||
// }
|
||||
|
||||
// export function tickClock (isServer) {
|
||||
// return {
|
||||
// type: actionTypes.TICK_CLOCK,
|
||||
// light: !isServer,
|
||||
// ts: Date.now()
|
||||
// }
|
||||
// }
|
||||
+11
-5
@@ -1,20 +1,26 @@
|
||||
import { USER_LOGGED_IN, USER_LOGGED_OUT, REQUEST_LOGIN, REQUEST_LOGIN_FAILURE,
|
||||
REQUEST_OAUTH_LOGIN, REQUEST_OAUTH_LOGIN_FAILURE
|
||||
REQUEST_OAUTH_LOGIN, REQUEST_OAUTH_LOGIN_FAILURE,
|
||||
REQUEST_LOGOUT
|
||||
} from "../types";
|
||||
|
||||
export const requestLogin = data => ({
|
||||
type: REQUEST_LOGIN,
|
||||
data
|
||||
});
|
||||
|
||||
export const userLoggedIn = user => ({
|
||||
type: USER_LOGGED_IN,
|
||||
user
|
||||
});
|
||||
|
||||
export const requestLogout = data => ({
|
||||
type: REQUEST_LOGOUT,
|
||||
});
|
||||
|
||||
export const userLoggedOut = () => ({
|
||||
type: USER_LOGGED_OUT
|
||||
});
|
||||
|
||||
export const requestLogin = data => ({
|
||||
type: REQUEST_LOGIN,
|
||||
data
|
||||
});
|
||||
|
||||
export const requestLoginFailure = errors => ({
|
||||
type: REQUEST_LOGIN_FAILURE,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import {
|
||||
CREATE_USER_REQUEST,
|
||||
CREATE_USER_FAILURE,
|
||||
FETCH_CURRENT_USER_REQUEST,
|
||||
FETCH_CURRENT_USER_SUCCESS,
|
||||
FETCH_CURRENT_USER_FAILURE,
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import SvgIcon from '@material-ui/core/SvgIcon';
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
},
|
||||
grow: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
sectionDesktop: {
|
||||
justifyContent: 'center',
|
||||
display: 'flex',
|
||||
},
|
||||
sectionMobile: {
|
||||
// display: 'flex',
|
||||
},
|
||||
});
|
||||
|
||||
class BottomToolBar extends React.Component {
|
||||
state = {
|
||||
anchorEl: null,
|
||||
mobileMoreAnchorEl: null,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar position="relative">
|
||||
<Toolbar className={classes.sectionDesktop}>
|
||||
<div >
|
||||
<IconButton aria-label="TT">
|
||||
<SvgIcon>
|
||||
<path d="M15.94,10.179l-2.437-0.325l1.62-7.379c0.047-0.235-0.132-0.458-0.372-0.458H5.25c-0.241,0-0.42,0.223-0.373,0.458l1.634,7.376L4.06,10.179c-0.312,0.041-0.446,0.425-0.214,0.649l2.864,2.759l-0.724,3.947c-0.058,0.315,0.277,0.554,0.559,0.401l3.457-1.916l3.456,1.916c-0.419-0.238,0.56,0.439,0.56-0.401l-0.725-3.947l2.863-2.759C16.388,10.604,16.254,10.22,15.94,10.179M10.381,2.778h3.902l-1.536,6.977L12.036,9.66l-1.655-3.546V2.778z M5.717,2.778h3.903v3.335L7.965,9.66L7.268,9.753L5.717,2.778zM12.618,13.182c-0.092,0.088-0.134,0.217-0.11,0.343l0.615,3.356l-2.938-1.629c-0.057-0.03-0.122-0.048-0.184-0.048c-0.063,0-0.128,0.018-0.185,0.048l-2.938,1.629l0.616-3.356c0.022-0.126-0.019-0.255-0.11-0.343l-2.441-2.354l3.329-0.441c0.128-0.017,0.24-0.099,0.295-0.215l1.435-3.073l1.435,3.073c0.055,0.116,0.167,0.198,0.294,0.215l3.329,0.441L12.618,13.182z" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
<IconButton aria-label="TT">
|
||||
<SvgIcon>
|
||||
<path d="M18.303,4.742l-1.454-1.455c-0.171-0.171-0.475-0.171-0.646,0l-3.061,3.064H2.019c-0.251,0-0.457,0.205-0.457,0.456v9.578c0,0.251,0.206,0.456,0.457,0.456h13.683c0.252,0,0.457-0.205,0.457-0.456V7.533l2.144-2.146C18.481,5.208,18.483,4.917,18.303,4.742 M15.258,15.929H2.476V7.263h9.754L9.695,9.792c-0.057,0.057-0.101,0.13-0.119,0.212L9.18,11.36h-3.98c-0.251,0-0.457,0.205-0.457,0.456c0,0.253,0.205,0.456,0.457,0.456h4.336c0.023,0,0.899,0.02,1.498-0.127c0.312-0.077,0.55-0.137,0.55-0.137c0.08-0.018,0.155-0.059,0.212-0.118l3.463-3.443V15.929z M11.241,11.156l-1.078,0.267l0.267-1.076l6.097-6.091l0.808,0.808L11.241,11.156z" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
<IconButton aria-label="TT">
|
||||
<SvgIcon>
|
||||
<path d="M12.075,10.812c1.358-0.853,2.242-2.507,2.242-4.037c0-2.181-1.795-4.618-4.198-4.618S5.921,4.594,5.921,6.775c0,1.53,0.884,3.185,2.242,4.037c-3.222,0.865-5.6,3.807-5.6,7.298c0,0.23,0.189,0.42,0.42,0.42h14.273c0.23,0,0.42-0.189,0.42-0.42C17.676,14.619,15.297,11.677,12.075,10.812 M6.761,6.775c0-2.162,1.773-3.778,3.358-3.778s3.359,1.616,3.359,3.778c0,2.162-1.774,3.778-3.359,3.778S6.761,8.937,6.761,6.775 M3.415,17.69c0.218-3.51,3.142-6.297,6.704-6.297c3.562,0,6.486,2.787,6.705,6.297H3.415z" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
<IconButton aria-label="TT">
|
||||
<SvgIcon>
|
||||
<path d="M15.684,16.959L10.879,8.52c0.886-0.343,1.517-1.193,1.517-2.186c0-1.296-1.076-2.323-2.396-2.323S7.604,5.037,7.604,6.333c0,0.993,0.63,1.843,1.517,2.186l-4.818,8.439c-0.189,0.311,0.038,0.708,0.412,0.708h10.558C15.645,17.667,15.871,17.27,15.684,16.959 M8.562,6.333c0-0.778,0.645-1.382,1.438-1.382s1.438,0.604,1.438,1.382c0,0.779-0.645,1.412-1.438,1.412S8.562,7.113,8.562,6.333 M5.55,16.726L10,8.91l4.435,7.815H5.55z M15.285,9.62c1.26-2.046,1.26-4.525,0-6.572c-0.138-0.223-0.064-0.512,0.162-0.646c0.227-0.134,0.521-0.063,0.658,0.16c1.443,2.346,1.443,5.2,0,7.546c-0.236,0.382-0.641,0.17-0.658,0.159C15.221,10.131,15.147,9.842,15.285,9.62 M13.395,8.008c0.475-1.063,0.475-2.286,0-3.349c-0.106-0.238,0.004-0.515,0.246-0.62c0.242-0.104,0.525,0.004,0.632,0.242c0.583,1.305,0.583,2.801,0,4.106c-0.214,0.479-0.747,0.192-0.632,0.242C13.398,8.523,13.288,8.247,13.395,8.008 M3.895,10.107c-1.444-2.346-1.444-5.2,0-7.546c0.137-0.223,0.431-0.294,0.658-0.16c0.226,0.135,0.299,0.424,0.162,0.646c-1.26,2.047-1.26,4.525,0,6.572c0.137,0.223,0.064,0.512-0.162,0.646C4.535,10.277,4.131,10.489,3.895,10.107 M5.728,8.387c-0.583-1.305-0.583-2.801,0-4.106c0.106-0.238,0.39-0.346,0.631-0.242c0.242,0.105,0.353,0.382,0.247,0.62c-0.475,1.063-0.475,2.286,0,3.349c0.106,0.238-0.004,0.515-0.247,0.62c-0.062,0.027-0.128,0.04-0.192,0.04C5.982,8.668,5.807,8.563,5.728,8.387" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
<IconButton aria-label="TT">
|
||||
<SvgIcon>
|
||||
<path d="M6.176,7.241V6.78c0-0.221-0.181-0.402-0.402-0.402c-0.221,0-0.403,0.181-0.403,0.402v0.461C4.79,7.416,4.365,7.955,4.365,8.591c0,0.636,0.424,1.175,1.006,1.35v3.278c0,0.222,0.182,0.402,0.403,0.402c0.222,0,0.402-0.181,0.402-0.402V9.941c0.582-0.175,1.006-0.714,1.006-1.35C7.183,7.955,6.758,7.416,6.176,7.241 M5.774,9.195c-0.332,0-0.604-0.272-0.604-0.604c0-0.332,0.272-0.604,0.604-0.604c0.332,0,0.604,0.272,0.604,0.604C6.377,8.923,6.105,9.195,5.774,9.195 M10.402,10.058V6.78c0-0.221-0.181-0.402-0.402-0.402c-0.222,0-0.402,0.181-0.402,0.402v3.278c-0.582,0.175-1.006,0.714-1.006,1.35c0,0.637,0.424,1.175,1.006,1.351v0.461c0,0.222,0.181,0.402,0.402,0.402c0.221,0,0.402-0.181,0.402-0.402v-0.461c0.582-0.176,1.006-0.714,1.006-1.351C11.408,10.772,10.984,10.233,10.402,10.058M10,12.013c-0.333,0-0.604-0.272-0.604-0.604S9.667,10.805,10,10.805c0.332,0,0.604,0.271,0.604,0.604S10.332,12.013,10,12.013M14.629,8.448V6.78c0-0.221-0.182-0.402-0.403-0.402c-0.221,0-0.402,0.181-0.402,0.402v1.668c-0.581,0.175-1.006,0.714-1.006,1.35c0,0.636,0.425,1.176,1.006,1.351v2.07c0,0.222,0.182,0.402,0.402,0.402c0.222,0,0.403-0.181,0.403-0.402v-2.07c0.581-0.175,1.006-0.715,1.006-1.351C15.635,9.163,15.21,8.624,14.629,8.448 M14.226,10.402c-0.331,0-0.604-0.272-0.604-0.604c0-0.332,0.272-0.604,0.604-0.604c0.332,0,0.604,0.272,0.604,0.604C14.83,10.13,14.558,10.402,14.226,10.402 M17.647,3.962H2.353c-0.221,0-0.402,0.181-0.402,0.402v11.27c0,0.222,0.181,0.402,0.402,0.402h15.295c0.222,0,0.402-0.181,0.402-0.402V4.365C18.05,4.144,17.869,3.962,17.647,3.962 M17.245,15.232H2.755V4.768h14.49V15.232z" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
</div>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
BottomToolBar.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(BottomToolBar);
|
||||
@@ -1,94 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Input from '@material-ui/core/Input';
|
||||
import Badge from '@material-ui/core/Badge';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import { fade } from '@material-ui/core/styles/colorManipulator';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
import AccountCircle from '@material-ui/icons/AccountCircle';
|
||||
import MailIcon from '@material-ui/icons/Mail';
|
||||
import NotificationsIcon from '@material-ui/icons/Notifications';
|
||||
import MoreIcon from '@material-ui/icons/MoreVert';
|
||||
import SvgIcon from '@material-ui/core/SvgIcon';
|
||||
|
||||
import Router from 'next/router'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
grow: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
logo: {
|
||||
width: '48px',
|
||||
height: '48px'
|
||||
},
|
||||
sectionMobile: {
|
||||
display: 'flex',
|
||||
},
|
||||
});
|
||||
|
||||
class PrimarySearchAppBar extends React.Component {
|
||||
state = {
|
||||
anchorEl: null,
|
||||
mobileMoreAnchorEl: null,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar position="fixed">
|
||||
<Toolbar>
|
||||
{
|
||||
this.props.backLink != "" ?
|
||||
|
||||
<IconButton className={classes.menuButton} color="inherit" aria-label="Back" onClick={() => Router.push(this.props.backLink)}>
|
||||
<SvgIcon>
|
||||
<path d="M11.739,13.962c-0.087,0.086-0.199,0.131-0.312,0.131c-0.112,0-0.226-0.045-0.312-0.131l-3.738-3.736c-0.173-0.173-0.173-0.454,0-0.626l3.559-3.562c0.173-0.175,0.454-0.173,0.626,0c0.173,0.172,0.173,0.451,0,0.624l-3.248,3.25l3.425,3.426C11.911,13.511,11.911,13.789,11.739,13.962 M18.406,10c0,4.644-3.763,8.406-8.406,8.406S1.594,14.644,1.594,10S5.356,1.594,10,1.594S18.406,5.356,18.406,10 M17.521,10c0-4.148-3.373-7.521-7.521-7.521c-4.148,0-7.521,3.374-7.521,7.521c0,4.148,3.374,7.521,7.521,7.521C14.147,17.521,17.521,14.148,17.521,10"></path>
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
|
||||
:
|
||||
<IconButton className={classes.menuButton} color="inherit" aria-label="Open drawer" onClick={() => Router.push('/')}>
|
||||
<SvgIcon>
|
||||
<path d="M20 12l-1.41-1.41L13 5.17V4h-2v12.17l-5.58-5.59L1 12l8 8 8-8z" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
|
||||
}
|
||||
<div className={classes.logo}>
|
||||
|
||||
<img src={this.props.logo} />
|
||||
</div>
|
||||
<div className={classes.grow} />
|
||||
<div className={classes.sectionMobile}>
|
||||
<IconButton color="inherit">
|
||||
<Badge className={classes.margin} badgeContent={42} color="secondary">
|
||||
<NotificationsIcon />
|
||||
</Badge>
|
||||
</IconButton>
|
||||
|
||||
</div>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PrimarySearchAppBar.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
backLink: PropTypes.string,
|
||||
logo: PropTypes.string,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(PrimarySearchAppBar);
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
@@ -19,7 +19,11 @@ import AccountCircle from '@material-ui/icons/AccountCircle';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import { ListItemText } from '@material-ui/core';
|
||||
|
||||
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||
import { connect } from 'react-redux'
|
||||
import { fetchCurrentUserRequest } from "../../actions/user";
|
||||
import { requestLogout } from "../../actions/auth";
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -82,6 +86,10 @@ class Header extends React.Component {
|
||||
toggle: true
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
|
||||
toggleDrawer = (side, open) => () => {
|
||||
this.setState({
|
||||
[side]: open,
|
||||
@@ -180,42 +188,87 @@ class Header extends React.Component {
|
||||
role="button"
|
||||
onClick={this.toggleDrawer('right', false)}
|
||||
onKeyDown={this.toggleDrawer('right', false)}
|
||||
>
|
||||
<div className={classes.fullList}>
|
||||
<List>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
>{!!this.props.loading &&
|
||||
(<div className="alert alert-info"><CircularProgress color="secondary" />Chargement...</div>
|
||||
)}
|
||||
{!!!this.props.loading && !!!this.props.fetched
|
||||
&&
|
||||
<div className={classes.fullList}>
|
||||
<List>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
<Link href="/login" prefetch >
|
||||
<a><ListItem>
|
||||
|
||||
<ListItemText primary='Connexion'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
<Link href="/login" prefetch >
|
||||
<a><ListItem>
|
||||
|
||||
<ListItemText primary='Inscription'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
<Divider />
|
||||
<Link href="https://www.talentstube.com/faire-offre-emploi-video" >
|
||||
<a><ListItem>
|
||||
|
||||
<ListItemText primary='Espace recruteurs'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
</List>
|
||||
</div>}
|
||||
{!!!this.props.loading && !!this.props.fetched &&
|
||||
<Fragment>
|
||||
<ListItem>
|
||||
{this.props.user.firstname}
|
||||
{this.props.user.lastname}
|
||||
{this.props.user.email}
|
||||
</ListItem>
|
||||
<Divider />
|
||||
<Link href="/login" prefetch >
|
||||
{/* TODO:real links */}
|
||||
<Link href="/help" prefetch >
|
||||
<a><ListItem>
|
||||
|
||||
<ListItemText primary='Connexion'>
|
||||
<ListItemText primary='Mes candidatures'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
<Link href="/login" prefetch >
|
||||
<Link href="/help" prefetch >
|
||||
<a><ListItem>
|
||||
|
||||
<ListItemText primary='Inscription'>
|
||||
<ListItemText primary='Mon compte'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
<Divider />
|
||||
<Link href="https://www.talentstube.com/faire-offre-emploi-video" >
|
||||
<Link href="/help" prefetch >
|
||||
<a><ListItem>
|
||||
|
||||
<ListItemText primary='Espace recruteurs'>
|
||||
<ListItemText primary='Paramètres'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
</List>
|
||||
</div>
|
||||
|
||||
<ListItem>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.button}
|
||||
onClick={() => this.props.requestLogout()}>Déconnexion</Button>
|
||||
</ListItem>
|
||||
</Fragment>
|
||||
}
|
||||
</div>
|
||||
</Drawer>
|
||||
<AppBar position="static" className={classes.appBar}>
|
||||
@@ -251,5 +304,17 @@ Header.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
||||
console.log("Header")
|
||||
console.log(state)
|
||||
console.log("Header")
|
||||
|
||||
return {
|
||||
user: state.user,
|
||||
fetched: !!state.user.fetched,
|
||||
loading: !!state.user.loading
|
||||
};
|
||||
}
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchCurrentUserRequest, requestLogout })(Header));
|
||||
|
||||
export default withStyles(styles)(Header)
|
||||
@@ -13,11 +13,22 @@ const styles = theme => ({
|
||||
overflow: 'hidden',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
//TODO: great horizontal scrolling
|
||||
//hidding scroll bar
|
||||
//https://stackoverflow.com/questions/53772429/material-ui-how-can-i-style-the-scrollbar-with-css-in-js
|
||||
//https://css-tricks.com/pure-css-horizontal-scrolling/
|
||||
//http://qnimate.com/javascript-scroll-by-dragging/
|
||||
//https://codeburst.io/how-to-create-horizontal-scrolling-containers-d8069651e9c6
|
||||
// -> https://stackoverflow.com/questions/40926181/react-scrolling-a-div-by-dragging-the-mouse
|
||||
gridList: {
|
||||
flexWrap: 'nowrap',
|
||||
// Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS.
|
||||
transform: 'translateZ(0)',
|
||||
height: '400px',
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '0 !important'
|
||||
},
|
||||
'-webkit-overflow-scrolling': 'touch'
|
||||
},
|
||||
gridListTile:{
|
||||
height: '400px',
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// import Link from 'next/link'
|
||||
// import PropTypes from "prop-types";
|
||||
// import { withStyles } from '@material-ui/core/styles'
|
||||
// import PSAB from './PrimarySearchAppBar'
|
||||
|
||||
|
||||
// const styles = theme => ({
|
||||
// root: {
|
||||
// position: 'relative',
|
||||
// height: '10vh'
|
||||
// },
|
||||
// });
|
||||
|
||||
// function Header(props) {
|
||||
// return (
|
||||
// <PSAB backLink={props.backLink}/>
|
||||
// );
|
||||
|
||||
// }
|
||||
// Header.defaultProps = {
|
||||
// backLink : ""
|
||||
// }
|
||||
// Header.propTypes = {
|
||||
// backLink : PropTypes.string
|
||||
// }
|
||||
// export default withStyles(styles)(Header)
|
||||
@@ -1,164 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Input from '@material-ui/core/Input';
|
||||
import Badge from '@material-ui/core/Badge';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import { fade } from '@material-ui/core/styles/colorManipulator';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
import AccountCircle from '@material-ui/icons/AccountCircle';
|
||||
import MailIcon from '@material-ui/icons/Mail';
|
||||
import NotificationsIcon from '@material-ui/icons/Notifications';
|
||||
import MoreIcon from '@material-ui/icons/MoreVert';
|
||||
import SvgIcon from '@material-ui/core/SvgIcon';
|
||||
|
||||
import Router from 'next/router'
|
||||
import WhatshotIcon from '@material-ui/icons/Whatshot';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
const PWAInstallSnack = dynamic(() => import('./PWAInstallSnack.js'), {
|
||||
ssr: false
|
||||
});
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
grow: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
search: {
|
||||
position: 'relative',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: fade(theme.palette.common.white, 0.15),
|
||||
'&:hover': {
|
||||
backgroundColor: fade(theme.palette.common.white, 0.25),
|
||||
},
|
||||
marginRight: theme.spacing(2),
|
||||
marginLeft: 0,
|
||||
width: '100%',
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
marginLeft: theme.spacing(3),
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
searchIcon: {
|
||||
width: theme.spacing(9),
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
pointerEvents: 'none',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
inputRoot: {
|
||||
color: 'inherit',
|
||||
width: '100%',
|
||||
},
|
||||
inputInput: {
|
||||
paddingTop: theme.spacing(1),
|
||||
paddingRight: theme.spacing(1),
|
||||
paddingBottom: theme.spacing(1),
|
||||
paddingLeft: theme.spacing(1),
|
||||
transition: theme.transitions.create('width'),
|
||||
width: '100%',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
width: 500,
|
||||
},
|
||||
},
|
||||
sectionDesktop: {
|
||||
display: 'flex',
|
||||
},
|
||||
sectionMobile: {
|
||||
display: 'flex',
|
||||
},
|
||||
});
|
||||
|
||||
class PrimarySearchAppBar extends React.Component {
|
||||
state = {
|
||||
anchorEl: null,
|
||||
mobileMoreAnchorEl: null,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar position="fixed">
|
||||
<Toolbar>
|
||||
{
|
||||
this.props.backLink != "" ?
|
||||
|
||||
<IconButton className={classes.menuButton} color="inherit" aria-label="Back" onClick={() => Router.push(this.props.backLink)}>
|
||||
<SvgIcon>
|
||||
<path d="M11.739,13.962c-0.087,0.086-0.199,0.131-0.312,0.131c-0.112,0-0.226-0.045-0.312-0.131l-3.738-3.736c-0.173-0.173-0.173-0.454,0-0.626l3.559-3.562c0.173-0.175,0.454-0.173,0.626,0c0.173,0.172,0.173,0.451,0,0.624l-3.248,3.25l3.425,3.426C11.911,13.511,11.911,13.789,11.739,13.962 M18.406,10c0,4.644-3.763,8.406-8.406,8.406S1.594,14.644,1.594,10S5.356,1.594,10,1.594S18.406,5.356,18.406,10 M17.521,10c0-4.148-3.373-7.521-7.521-7.521c-4.148,0-7.521,3.374-7.521,7.521c0,4.148,3.374,7.521,7.521,7.521C14.147,17.521,17.521,14.148,17.521,10"></path>
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
|
||||
:
|
||||
<IconButton className={classes.menuButton} color="inherit" aria-label="Open drawer" onClick={() => Router.push('/')}>
|
||||
<SvgIcon>
|
||||
<path d="M20 12l-1.41-1.41L13 5.17V4h-2v12.17l-5.58-5.59L1 12l8 8 8-8z" />
|
||||
</SvgIcon>
|
||||
</IconButton>
|
||||
|
||||
}
|
||||
|
||||
|
||||
<div className={classes.search}>
|
||||
|
||||
<Input
|
||||
placeholder="Recherche…"
|
||||
disableUnderline
|
||||
classes={{
|
||||
root: classes.inputRoot,
|
||||
input: classes.inputInput,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.grow} />
|
||||
<div className={classes.sectionMobile}>
|
||||
<PWAInstallSnack >
|
||||
{({ initInstall }) =>
|
||||
|
||||
<Button
|
||||
aria-label='install' variant="contained" color="primary" onClick={initInstall}>
|
||||
<WhatshotIcon ></WhatshotIcon>
|
||||
<Typography variant="h6" color="inherit">
|
||||
Installer l'app
|
||||
</Typography>
|
||||
</Button>
|
||||
|
||||
}
|
||||
</PWAInstallSnack>
|
||||
|
||||
</div>
|
||||
<div className={classes.sectionMobile}>
|
||||
<IconButton color="inherit">
|
||||
<Badge className={classes.margin} badgeContent={42} color="secondary">
|
||||
<NotificationsIcon />
|
||||
</Badge>
|
||||
</IconButton>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PrimarySearchAppBar.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
backLink: PropTypes.string,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(PrimarySearchAppBar);
|
||||
@@ -60,7 +60,7 @@ class ShortVideoHooker extends Component {
|
||||
}
|
||||
|
||||
tick() {
|
||||
console.log(this.state)
|
||||
// console.log(this.state)
|
||||
if (new Date() - this.state.startDate >= 8000) {
|
||||
|
||||
if (this.state.i == 2)
|
||||
@@ -82,7 +82,7 @@ class ShortVideoHooker extends Component {
|
||||
render() {
|
||||
let { classes } = this.props;
|
||||
let videoId = videoList[0].vimeoId;
|
||||
console.log(videoId)
|
||||
// console.log(videoId)
|
||||
return (
|
||||
<div className={classes.video}>
|
||||
{/* config at : https://github.com/xDae/react-plyr */}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import DetailAppBar from '../organisms/DetailAppBar'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
height: '100%'
|
||||
},
|
||||
head: {
|
||||
width: '100%',
|
||||
|
||||
height: '56px',
|
||||
background: 'silver',
|
||||
position: 'fixed',
|
||||
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
height: '64px'
|
||||
}
|
||||
|
||||
},
|
||||
content: {
|
||||
top: '56px',
|
||||
height: 'calc(100vh - 56px)',
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
top: '64px',
|
||||
height: 'calc(100vh - 64px)',
|
||||
},
|
||||
position: 'relative',
|
||||
overflow: 'auto',
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
function LayoutDetail(props) {
|
||||
|
||||
const { classes } = props;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<div id="H" className={classes.head}>
|
||||
<div className={classes.inner}>
|
||||
<DetailAppBar backLink={props.backLink} logo={props.logo}/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="C" className={classes.content}>
|
||||
{props.children}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
LayoutDetail.defaultProps = {
|
||||
backLink:"/",
|
||||
logo: "default.svg"
|
||||
}
|
||||
LayoutDetail.propTypes = {
|
||||
backLink : PropTypes.string,
|
||||
logo: PropTypes.string,
|
||||
}
|
||||
|
||||
export default withStyles(styles)(LayoutDetail)
|
||||
@@ -1,26 +0,0 @@
|
||||
import Link from 'next/link'
|
||||
import PropTypes from "prop-types";
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import PSAB from '../organisms/PrimarySearchAppBar'
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
height: '10vh'
|
||||
},
|
||||
});
|
||||
|
||||
function Header(props) {
|
||||
return (
|
||||
<PSAB backLink={props.backLink}/>
|
||||
);
|
||||
|
||||
}
|
||||
Header.defaultProps = {
|
||||
backLink : ""
|
||||
}
|
||||
Header.propTypes = {
|
||||
backLink : PropTypes.string
|
||||
}
|
||||
export default withStyles(styles)(Header)
|
||||
@@ -1,208 +0,0 @@
|
||||
import React from 'react'
|
||||
import Router from 'next/router'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import { Container, Row, Col, Nav, NavItem, Button, Form, NavLink, Collapse,
|
||||
Navbar, NavbarToggler, NavbarBrand, Modal, ModalHeader, ModalBody,
|
||||
ModalFooter, ListGroup, ListGroupItem } from 'reactstrap'
|
||||
import Signin from './signin'
|
||||
import { NextAuth } from 'next-auth/client'
|
||||
import Cookies from 'universal-cookie'
|
||||
|
||||
export default class extends React.Component {
|
||||
|
||||
static propTypes() {
|
||||
return {
|
||||
session: React.PropTypes.object.isRequired,
|
||||
providers: React.PropTypes.object.isRequired,
|
||||
children: React.PropTypes.object.isRequired,
|
||||
fluid: React.PropTypes.boolean,
|
||||
navmenu: React.PropTypes.boolean,
|
||||
signinBtn: React.PropTypes.boolean
|
||||
}
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
navOpen: false,
|
||||
modal: false,
|
||||
providers: null
|
||||
}
|
||||
this.toggleModal = this.toggleModal.bind(this)
|
||||
}
|
||||
|
||||
async toggleModal(e) {
|
||||
if (e) e.preventDefault()
|
||||
|
||||
// Save current URL so user is redirected back here after signing in
|
||||
if (this.state.modal !== true) {
|
||||
const cookies = new Cookies()
|
||||
cookies.set('redirect_url', window.location.pathname, { path: '/' })
|
||||
}
|
||||
|
||||
this.setState({
|
||||
providers: this.state.providers || await NextAuth.providers(),
|
||||
modal: !this.state.modal
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
||||
<MainBody navmenu={this.props.navmenu} fluid={this.props.fluid} container={this.props.container}>
|
||||
{this.props.children}
|
||||
</MainBody>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class MainBody extends React.Component {
|
||||
render() {
|
||||
if (this.props.container === false) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.props.children}
|
||||
</React.Fragment>
|
||||
)
|
||||
} else if (this.props.navmenu === false) {
|
||||
return (
|
||||
<Container fluid={this.props.fluid} style={{marginTop: '1em'}}>
|
||||
{this.props.children}
|
||||
</Container>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Container fluid={this.props.fluid} style={{marginTop: '1em'}}>
|
||||
<Row>
|
||||
<Col xs="12" md="9" lg="10">
|
||||
{this.props.children}
|
||||
</Col>
|
||||
<Col xs="12" md="3" lg="2" style={{paddingTop: '1em'}}>
|
||||
<h5 className="text-muted text-uppercase">Examples</h5>
|
||||
<ListGroup>
|
||||
<ListGroupItem>
|
||||
<Link prefetch href="/examples/authentication"><a href="/examples/authentication" className="d-block">Auth</a></Link>
|
||||
</ListGroupItem>
|
||||
<ListGroupItem>
|
||||
<Link prefetch href="/examples/async"><a href="/examples/async" className="d-block">Async</a></Link>
|
||||
</ListGroupItem>
|
||||
<ListGroupItem>
|
||||
<Link prefetch href="/examples/layout"><a href="/examples/layout" className="d-block">Layout</a></Link>
|
||||
</ListGroupItem>
|
||||
<ListGroupItem>
|
||||
<Link prefetch href="/examples/routing"><a href="/examples/routing" className="d-block">Routing</a></Link>
|
||||
</ListGroupItem>
|
||||
<ListGroupItem>
|
||||
<Link prefetch href="/examples/styling"><a href="/examples/styling" className="d-block">Styling</a></Link>
|
||||
</ListGroupItem>
|
||||
</ListGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class UserMenu extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.handleSignoutSubmit = this.handleSignoutSubmit.bind(this)
|
||||
}
|
||||
|
||||
async handleSignoutSubmit(event) {
|
||||
event.preventDefault()
|
||||
|
||||
// Save current URL so user is redirected back here after signing out
|
||||
const cookies = new Cookies()
|
||||
cookies.set('redirect_url', window.location.pathname, { path: '/' })
|
||||
|
||||
await NextAuth.signout()
|
||||
Router.push('/')
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.session && this.props.session.user) {
|
||||
// If signed in display user dropdown menu
|
||||
const session = this.props.session
|
||||
return (
|
||||
<Nav className="ml-auto" navbar>
|
||||
{/*<!-- Uses .nojs-dropdown CSS to for a dropdown that works without client side JavaScript ->*/}
|
||||
<div tabIndex="2" className="dropdown nojs-dropdown">
|
||||
<div className="nav-item">
|
||||
<span className="dropdown-toggle nav-link d-none d-md-block">
|
||||
<span className="icon ion-md-contact" style={{fontSize: '2em', position: 'absolute', top: -5, left: -25}}></span>
|
||||
</span>
|
||||
<span className="dropdown-toggle nav-link d-block d-md-none">
|
||||
<span className="icon ion-md-contact mr-2"></span>
|
||||
{session.user.name || session.user.email}
|
||||
</span>
|
||||
</div>
|
||||
<div className="dropdown-menu">
|
||||
<Link prefetch href="/account">
|
||||
<a href="/account" className="dropdown-item"><span className="icon ion-md-person mr-1"></span> Your Account</a>
|
||||
</Link>
|
||||
<AdminMenuItem {...this.props}/>
|
||||
<div className="dropdown-divider d-none d-md-block"/>
|
||||
<div className="dropdown-item p-0">
|
||||
<Form id="signout" method="post" action="/auth/signout" onSubmit={this.handleSignoutSubmit}>
|
||||
<input name="_csrf" type="hidden" value={this.props.session.csrfToken}/>
|
||||
<Button type="submit" block className="pl-4 rounded-0 text-left dropdown-item"><span className="icon ion-md-log-out mr-1"></span> Sign out</Button>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Nav>
|
||||
)
|
||||
} if (this.props.signinBtn === false) {
|
||||
// If not signed in, don't display sign in button if disabled
|
||||
return null
|
||||
} else {
|
||||
// If not signed in, display sign in button
|
||||
return (
|
||||
<Nav className="ml-auto" navbar>
|
||||
<NavItem>
|
||||
{/**
|
||||
* @TODO Add support for passing current URL path as redirect URL
|
||||
* so that users without JavaScript are also redirected to the page
|
||||
* they were on before they signed in.
|
||||
**/}
|
||||
<a href="/auth?redirect=/" className="btn btn-outline-primary" onClick={this.props.toggleModal}><span className="icon ion-md-log-in mr-1"></span> Sign up / Sign in</a>
|
||||
</NavItem>
|
||||
</Nav>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class AdminMenuItem extends React.Component {
|
||||
render() {
|
||||
if (this.props.session.user && this.props.session.user.admin === true) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Link prefetch href="/admin">
|
||||
<a href="/admin" className="dropdown-item"><span className="icon ion-md-settings mr-1"></span> Admin</a>
|
||||
</Link>
|
||||
</React.Fragment>
|
||||
)
|
||||
} else {
|
||||
return(<div/>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SigninModal extends React.Component {
|
||||
render() {
|
||||
if (this.props.providers === null) return null
|
||||
|
||||
return (
|
||||
<Modal isOpen={this.props.modal} toggle={this.props.toggleModal} style={{maxWidth: 700}}>
|
||||
<ModalHeader>Sign up / Sign in</ModalHeader>
|
||||
<ModalBody style={{padding: '1em 2em'}}>
|
||||
<Signin session={this.props.session} providers={this.props.providers}/>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import React from 'react'
|
||||
import Layout from './layoutAuth'
|
||||
import { NextAuth } from 'next-auth/client'
|
||||
|
||||
export default class extends React.Component {
|
||||
|
||||
static async getInitialProps({req}) {
|
||||
return {
|
||||
session: await NextAuth.init({req}),// Add this.props.session to all pages
|
||||
lang: 'en'// Add a lang property for accessibility
|
||||
}
|
||||
}
|
||||
|
||||
adminAcccessOnly() {
|
||||
return (
|
||||
<Layout {...this.props} navmenu={false}>
|
||||
<div className="text-center pt-5 pb-5">
|
||||
<h1 className="display-4 mb-5">Access Denied</h1>
|
||||
<p className="lead">You must be signed in as an administrator to access this page.</p>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import React from 'react'
|
||||
import Router from 'next/router'
|
||||
import { Row, Col, Form, Input, Label, Button } from 'reactstrap'
|
||||
import Cookies from 'universal-cookie'
|
||||
import { NextAuth } from 'next-auth/client'
|
||||
|
||||
export default class extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
email: '',
|
||||
session: this.props.session,
|
||||
providers: this.props.providers,
|
||||
submitting: false
|
||||
}
|
||||
this.handleSubmit = this.handleSubmit.bind(this)
|
||||
this.handleEmailChange = this.handleEmailChange.bind(this)
|
||||
|
||||
}
|
||||
|
||||
handleEmailChange(event) {
|
||||
this.setState({
|
||||
email: event.target.value.trim()
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit(event) {
|
||||
event.preventDefault()
|
||||
|
||||
if (!this.state.email) return
|
||||
|
||||
this.setState({
|
||||
submitting: true
|
||||
})
|
||||
|
||||
// Save current URL so user is redirected back here after signing in
|
||||
const cookies = new Cookies()
|
||||
cookies.set('redirect_url', window.location.pathname, { path: '/' })
|
||||
|
||||
NextAuth.signin(this.state.email)
|
||||
.then(() => {
|
||||
Router.push(`/auth/check-email?email=${this.state.email}`)
|
||||
})
|
||||
.catch(err => {
|
||||
Router.push(`/auth/error?action=signin&type=email&email=${this.state.email}`)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.session.user) {
|
||||
return(<div/>)
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<p className="text-center" style={{marginTop: 10, marginBottom: 30}}>{`If you don't have an account, one will be created when you sign in.`}</p>
|
||||
<Row>
|
||||
<Col xs={12} md={6}>
|
||||
<SignInButtons providers={this.props.providers}/>
|
||||
</Col>
|
||||
<Col xs={12} md={6}>
|
||||
<Form id="signin" method="post" action="/auth/email/signin" onSubmit={this.handleSubmit}>
|
||||
<Input name="_csrf" type="hidden" value={this.state.session.csrfToken}/>
|
||||
<p>
|
||||
<Label htmlFor="email">Email address</Label><br/>
|
||||
<Input name="email" disabled={this.state.submitting} type="text" placeholder="j.smith@example.com" id="email" className="form-control" value={this.state.email} onChange={this.handleEmailChange}/>
|
||||
</p>
|
||||
<p className="text-right">
|
||||
<Button id="submitButton" disabled={this.state.submitting} outline color="dark" type="submit">
|
||||
{this.state.submitting === true && <span className="icon icon-spin ion-md-refresh mr-2"/>}
|
||||
Sign in with email
|
||||
</Button>
|
||||
</p>
|
||||
</Form>
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SignInButtons extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{
|
||||
Object.keys(this.props.providers).map((provider, i) => {
|
||||
if (!this.props.providers[provider].signin) return null
|
||||
|
||||
return (
|
||||
<p key={i}>
|
||||
<a className="btn btn-block btn-outline-secondary" href={this.props.providers[provider].signin}>
|
||||
Sign in with {provider}
|
||||
</a>
|
||||
</p>
|
||||
)
|
||||
})
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -9,8 +9,9 @@ export default {
|
||||
axios.post("/api/login_check", { username: credentials.email, password: credentials.password }).then(res => res.data),
|
||||
loginOauth: ({token,type}) =>
|
||||
axios.post("/api/login_check_oauth", {'oauth-token':token,'oauth-type':type}),
|
||||
fetchUser: () =>
|
||||
axios.post("/api/user").then(res => res.data)
|
||||
fetchUser: () =>{
|
||||
console.log("axios /api/user")
|
||||
return axios.get("/api/user").then(res => {console.log(res); return res.data})}
|
||||
|
||||
},
|
||||
ads: {
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
/**
|
||||
* next-auth.config.js Example
|
||||
*
|
||||
* Environment variables for this example:
|
||||
*
|
||||
* PORT=3000
|
||||
* SERVER_URL=http://localhost:3000
|
||||
* MONGO_URI=mongodb://localhost:27017/my-database
|
||||
*
|
||||
* If you wish, you can put these in a `.env` to seperate your environment
|
||||
* specific configuration from your code.
|
||||
**/
|
||||
|
||||
// Load environment variables from a .env file if one exists
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
@@ -8,7 +8,7 @@ import _ from "lodash/string";
|
||||
import Ar from "lodash/array";
|
||||
|
||||
import api from "../data/api"
|
||||
import LayoutDetail from "../components/templates/LayoutDetail";
|
||||
import Layout from "../components/templates/Layout";
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -36,7 +36,7 @@ class Company extends React.Component {
|
||||
const { id } = context.query
|
||||
let res = await api.companies.fetchCompany(id)
|
||||
console.log(res)
|
||||
return {data:res};
|
||||
return { data: res };
|
||||
}
|
||||
|
||||
onVimeoError = (err) => {
|
||||
@@ -46,9 +46,9 @@ class Company extends React.Component {
|
||||
const { classes, data } = this.props;
|
||||
|
||||
return (
|
||||
<LayoutDetail backLink="/Companies">
|
||||
<Fragment>
|
||||
<div className={classes.video}>
|
||||
{ data.presentation_video && (<Plyr autoplay
|
||||
{data.presentation_video && (<Plyr autoplay
|
||||
type="vimeo" // or "vimeo"
|
||||
videoId={Ar.last(_.split(data.presentation_video.cdn_url, '/'))}
|
||||
/>)}
|
||||
@@ -64,7 +64,7 @@ class Company extends React.Component {
|
||||
</Typography>
|
||||
</div>
|
||||
{/* TODO:list of ads */}
|
||||
</LayoutDetail>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/* eslint-disable jsx-a11y/anchor-is-valid */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Link from 'next/link';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
textAlign: 'center',
|
||||
paddingTop: theme.spacing(20),
|
||||
},
|
||||
});
|
||||
|
||||
function Help(props) {
|
||||
const { classes } = props;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Typography variant="display1" gutterBottom>
|
||||
Material-UI
|
||||
</Typography>
|
||||
<Typography variant="subheading" gutterBottom>
|
||||
Help page
|
||||
</Typography>
|
||||
<Typography gutterBottom>
|
||||
<Link href="/">
|
||||
<a>Go to the main page</a>
|
||||
</Link>
|
||||
</Typography>
|
||||
<Button variant="contained" color="primary">
|
||||
Do nothing button
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Help.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(Help);
|
||||
@@ -178,7 +178,7 @@ class LoginPage extends React.Component {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
loading: !!!state.user.loaded,
|
||||
loading: !!state.user.loading,
|
||||
errors: state.user.errors
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import _ from "lodash/string";
|
||||
import Ar from "lodash/array";
|
||||
|
||||
import api from "../data/api"
|
||||
import LayoutDetail from "../components/templates/LayoutDetail";
|
||||
import Layout from "../components/templates/Layout";
|
||||
import { fetchAdRequest } from '../actions/ads'
|
||||
import { AdSelector } from '../reducers/ad'
|
||||
|
||||
@@ -48,7 +48,7 @@ class Offre extends React.Component {
|
||||
const { classes, offre } = this.props;
|
||||
|
||||
return (
|
||||
<LayoutDetail backLink="/Offres">
|
||||
<Layout backLink="/Offres">
|
||||
{offre.video && (<Fragment>
|
||||
<div className={classes.video}>
|
||||
<Plyr autoplay
|
||||
@@ -82,7 +82,7 @@ class Offre extends React.Component {
|
||||
</Typography>
|
||||
</div>
|
||||
</Fragment>)}
|
||||
</LayoutDetail>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
import Recorder from '../Components/organisms/Recorder'
|
||||
import Layout from '../components/templates/LayoutDetail'
|
||||
import Layout from '../components/templates/Layout'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Head from 'next/head'
|
||||
import _ from 'lodash'
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
|
||||
import Layout from "../components/templates/Layout"
|
||||
import { Typography } from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
textAlign: 'center',
|
||||
paddingTop: theme.spacing(20),
|
||||
justifyContent: 'center',
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
class Territoires extends React.Component {
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className={classes.container}>
|
||||
Territoires
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Territoires.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(Territoires);
|
||||
@@ -8,6 +8,8 @@ import Router from 'next/router'
|
||||
import { Provider } from 'react-redux'
|
||||
import withRedux from 'next-redux-wrapper'
|
||||
import withReduxSaga from 'next-redux-saga'
|
||||
import setAuthorizationHeader from "../data/setAuthorizationHeader";
|
||||
import { fetchCurrentUserRequest } from "../actions/user";
|
||||
|
||||
import createStore from '../store'
|
||||
|
||||
@@ -33,6 +35,14 @@ class MyApp extends App {
|
||||
logPageView()
|
||||
Router.router.events.on('routeChangeComplete', logPageView)
|
||||
}
|
||||
|
||||
|
||||
if (localStorage.ttJWT) {
|
||||
setAuthorizationHeader(localStorage.ttJWT)
|
||||
console.log("dispatch(fetchCurrentUserRequest())")
|
||||
this.props.store.dispatch(fetchCurrentUserRequest());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static async getInitialProps({ Component, router, ctx }) {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import React from 'react'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import Router from 'next/router'
|
||||
import Cookies from 'universal-cookie'
|
||||
import { NextAuth } from 'next-auth/client'
|
||||
import Loader from '../../components/templates/loader'
|
||||
|
||||
export default class extends React.Component {
|
||||
|
||||
static async getInitialProps({req}) {
|
||||
const session = await NextAuth.init({force: true, req: req})
|
||||
|
||||
const cookies = new Cookies((req && req.headers.cookie) ? req.headers.cookie : null)
|
||||
|
||||
// If the user is signed in, we look for a redirect URL cookie and send
|
||||
// them to that page, so that people signing in end up back on the page they
|
||||
// were on before signing in. Defaults to '/'.
|
||||
let redirectTo = '/'
|
||||
if (session.user) {
|
||||
// Read redirect URL to redirect to from cookies
|
||||
redirectTo = cookies.get('redirect_url') || redirectTo
|
||||
|
||||
// Allow relative paths only - strip protocol/host/port if they exist.
|
||||
redirectTo = redirectTo.replace( /^[a-zA-Z]{3,5}\:\/{2}[a-zA-Z0-9_.:-]+\//, '')
|
||||
}
|
||||
|
||||
return {
|
||||
session: session,
|
||||
redirectTo: redirectTo
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
// Get latest session data after rendering on client *then* redirect.
|
||||
// The ensures client state is always updated after signing in or out.
|
||||
// (That's why we use a callback page)
|
||||
const session = await NextAuth.init({force: true})
|
||||
Router.push(this.props.redirectTo || '/')
|
||||
}
|
||||
|
||||
render() {
|
||||
// Provide a link for clients without JavaScript as a fallback.
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<meta charSet="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"/>
|
||||
</Head>
|
||||
<a href={this.props.redirectTo}>
|
||||
<Loader fullscreen={true}/>
|
||||
</a>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import React from 'react'
|
||||
import Router from 'next/router'
|
||||
import Page from '../../components/templates/page'
|
||||
import Layout from '../../components/templates/Layout'
|
||||
import { NextAuth } from 'next-auth/client'
|
||||
|
||||
export default class extends Page {
|
||||
|
||||
static async getInitialProps({req, res, query}) {
|
||||
let props = await super.getInitialProps({req})
|
||||
props.session = await NextAuth.init({force: true, req: req})
|
||||
|
||||
// If signed in already, instead of displaying message send to callback page
|
||||
// which should redirect them to whatever page it normally sends clients to
|
||||
if (props.session.user) {
|
||||
if (req) {
|
||||
res.redirect('/auth/callback')
|
||||
} else {
|
||||
Router.push('/auth/callback')
|
||||
}
|
||||
}
|
||||
|
||||
props.email = query.email
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Layout {...this.props} navmenu={false} signinBtn={false}>
|
||||
<div className="text-center pt-5 pb-5">
|
||||
<h1 className="display-4">Check your email</h1>
|
||||
<p className="lead">
|
||||
A sign in link has been sent to { (this.props.email) ? <span className="font-weight-bold">{this.props.email}</span> : <span>your inbox</span> }.
|
||||
</p>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
import React from 'react'
|
||||
import Router from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import { NextAuth } from 'next-auth/client'
|
||||
|
||||
export default class extends React.Component {
|
||||
|
||||
static async getInitialProps({req}) {
|
||||
return {
|
||||
session: await NextAuth.init({req}),
|
||||
linkedAccounts: await NextAuth.linked({req}),
|
||||
providers: await NextAuth.providers({req})
|
||||
}
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
email: '',
|
||||
password: '',
|
||||
session: this.props.session
|
||||
}
|
||||
this.handleEmailChange = this.handleEmailChange.bind(this)
|
||||
this.handlePasswordChange = this.handlePasswordChange.bind(this)
|
||||
this.handleSignInSubmit = this.handleSignInSubmit.bind(this)
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
if (this.props.session.user) {
|
||||
Router.push(`/auth/`)
|
||||
}
|
||||
}
|
||||
|
||||
handleEmailChange(event) {
|
||||
this.setState({
|
||||
email: event.target.value
|
||||
})
|
||||
}
|
||||
|
||||
handlePasswordChange(event) {
|
||||
this.setState({
|
||||
password: event.target.value
|
||||
})
|
||||
}
|
||||
|
||||
handleSignInSubmit(event) {
|
||||
event.preventDefault()
|
||||
|
||||
// An object passed NextAuth.signin will be passed to your signin() function
|
||||
NextAuth.signin({
|
||||
email: this.state.email,
|
||||
password: this.state.password
|
||||
})
|
||||
.then(authenticated => {
|
||||
Router.push(`/auth/callback`)
|
||||
})
|
||||
.catch(() => {
|
||||
alert("Authentication failed.")
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.session.user) {
|
||||
return null
|
||||
} else {
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="text-center">
|
||||
<h1 className="display-4 mt-3 mb-3">NextAuth With Credentials</h1>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-sm-6 mr-auto ml-auto">
|
||||
<p>
|
||||
If you need password based sign in, two factor authentication
|
||||
or another sign in method, you can use a signin() function
|
||||
in <strong>next-auth.functions.js</strong>.
|
||||
</p>
|
||||
<p>
|
||||
You can pass in any properties you need – e.g. username and password,
|
||||
a PIN or 2FA Token – as properties of the object passed to
|
||||
NextAuth.signin() in the front end and they will be passed
|
||||
through to your signin() function.
|
||||
</p>
|
||||
<div className="card mt-3 mb-3">
|
||||
<h4 className="card-header">Sign In</h4>
|
||||
<div className="card-body pb-0">
|
||||
<p className="text-italic text-muted text-center small">
|
||||
<strong>Important!</strong> Enable the signin() function in <strong>next-auth.functions.js</strong> first.
|
||||
</p>
|
||||
<form id="signin" method="post" action="/auth/signin" onSubmit={this.handleSignInSubmit}>
|
||||
<input name="_csrf" type="hidden" value={this.state.session.csrfToken}/>
|
||||
<p>
|
||||
<label htmlFor="email">Email address</label><br/>
|
||||
<input name="email" type="text" placeholder="j.smith@example.com" id="email" className="form-control" value={this.state.email} onChange={this.handleEmailChange}/>
|
||||
</p>
|
||||
<p>
|
||||
<label htmlFor="password">Password</label><br/>
|
||||
<input name="password" type="password" placeholder="" id="password" className="form-control" value={this.state.password} onChange={this.handlePasswordChange}/>
|
||||
</p>
|
||||
<p className="text-right">
|
||||
<button id="submitButton" type="submit" className="btn btn-outline-primary">Sign in</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-center">
|
||||
<Link href="/auth"><a>Back</a></Link>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import Page from '../../components/templates/page'
|
||||
import Layout from '../../components/templates/layoutAuth'
|
||||
export default class extends Page {
|
||||
|
||||
static async getInitialProps({req, query}) {
|
||||
let props = await super.getInitialProps({req})
|
||||
props.action = query.action || null
|
||||
props.type = query.type || null
|
||||
props.service = query.service || null
|
||||
return props
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.action == 'signin' && this.props.type == 'oauth') {
|
||||
return(
|
||||
<Layout {...this.props} navmenu={false}>
|
||||
<div className="text-center mb-5">
|
||||
<h1 className="display-4 mt-5 mb-3">Unable to sign in</h1>
|
||||
<p className="lead">An account associated with your email address already exists.</p>
|
||||
<p className="lead"><Link href="/auth"><a>Sign in with email or another service</a></Link></p>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-sm-8 mr-auto ml-auto mb-5">
|
||||
<div className="text-muted">
|
||||
<h4 className="mb-2">Why am I seeing this?</h4>
|
||||
<p className="mb-2">
|
||||
It looks like you might have already signed up using another service.
|
||||
</p>
|
||||
<p className="mb-3">
|
||||
To protect your account, if you have perviously signed up
|
||||
using another service you must link accounts before you
|
||||
can use a different service to sign in.
|
||||
</p>
|
||||
<h4 className="mb-2">How do I fix this?</h4>
|
||||
<p className="mb-0">
|
||||
To sign in using another service, first sign in using your email address then link accounts.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
} else if (this.props.action == 'signin' && this.props.type == 'token-invalid') {
|
||||
return(
|
||||
<Layout {...this.props} navmenu={false}>
|
||||
<div className="text-center mb-5">
|
||||
<h1 className="display-4 mt-5 mb-2">Link not valid</h1>
|
||||
<p className="lead">This sign in link is no longer valid.</p>
|
||||
<p className="lead"><Link href="/auth"><a>Get a new sign in link</a></Link></p>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
} else {
|
||||
return(
|
||||
<Layout {...this.props} navmenu={false}>
|
||||
<div className="text-center mb-5">
|
||||
<h1 className="display-4 mt-5">Error signing in</h1>
|
||||
<p className="lead">An error occured while trying to sign in.</p>
|
||||
<p className="lead"><Link href="/auth"><a>Sign in with email or another service</a></Link></p>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
-10
@@ -3,33 +3,59 @@ import {
|
||||
USER_LOGGED_OUT,
|
||||
REQUEST_LOGIN_FAILURE,
|
||||
REQUEST_LOGIN,
|
||||
REQUEST_LOGOUT,
|
||||
FETCH_CURRENT_USER_REQUEST,
|
||||
FETCH_CURRENT_USER_SUCCESS,
|
||||
FETCH_CURRENT_USER_FAILURE
|
||||
} from "../types";
|
||||
|
||||
export function user(state = {
|
||||
loaded: false
|
||||
}, action = {}) {
|
||||
switch (action.type) {
|
||||
case REQUEST_LOGIN:
|
||||
return {
|
||||
loaded:false
|
||||
loading: true,
|
||||
fetched: false,
|
||||
}
|
||||
case USER_LOGGED_IN:
|
||||
return {
|
||||
...action.user,
|
||||
loaded: true
|
||||
loading: false,
|
||||
fetched: false,
|
||||
}
|
||||
case REQUEST_LOGOUT:
|
||||
return {
|
||||
loading: true,
|
||||
fetched: false,
|
||||
};
|
||||
case USER_LOGGED_OUT:
|
||||
return {
|
||||
loaded: true,
|
||||
token: "",
|
||||
loading: false,
|
||||
fetched: false,
|
||||
};
|
||||
|
||||
case REQUEST_LOGIN_FAILURE:
|
||||
console.log("REQUEST_LOGIN_FAILURE")
|
||||
return {
|
||||
loaded: true,
|
||||
errors: { ...action },
|
||||
};
|
||||
loading: false,
|
||||
errors: { ...action.data.message },
|
||||
}
|
||||
case FETCH_CURRENT_USER_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
loading: true,
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
case FETCH_CURRENT_USER_SUCCESS:
|
||||
return {
|
||||
loading: false,
|
||||
fetched: true,
|
||||
...action.user,
|
||||
}
|
||||
case FETCH_CURRENT_USER_FAILURE:
|
||||
return {
|
||||
loading: false,
|
||||
fetched: false,
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
+3
-1
@@ -3,12 +3,13 @@
|
||||
import { all, call, delay, put, take, takeLatest } from 'redux-saga/effects'
|
||||
import es6promise from 'es6-promise'
|
||||
|
||||
import { requestLoginSaga, requestUserSaga } from './sagas/userSaga.js'
|
||||
import { requestLoginSaga, requestUserSaga, requestLogoutSaga } from './sagas/userSaga.js'
|
||||
import { requestAdsSaga, requestAdSaga, requestPromotedAdsSaga } from './sagas/offreSaga.js'
|
||||
import {requestCompaniesSaga} from './sagas/companySaga.js'
|
||||
|
||||
import {
|
||||
REQUEST_LOGIN,
|
||||
REQUEST_LOGOUT,
|
||||
FETCH_CURRENT_USER_REQUEST,
|
||||
FETCH_ADS_REQUEST,
|
||||
FETCH_AD_REQUEST,
|
||||
@@ -23,6 +24,7 @@ es6promise.polyfill()
|
||||
function* rootSaga() {
|
||||
yield all([
|
||||
takeLatest(REQUEST_LOGIN, requestLoginSaga),
|
||||
takeLatest(REQUEST_LOGOUT, requestLogoutSaga),
|
||||
takeLatest(FETCH_CURRENT_USER_REQUEST, requestUserSaga),
|
||||
takeLatest(FETCH_ADS_REQUEST, requestAdsSaga),
|
||||
takeLatest(FETCH_AD_REQUEST, requestAdSaga),
|
||||
|
||||
+35
-21
@@ -1,6 +1,7 @@
|
||||
|
||||
import { call, put } from "redux-saga/effects";
|
||||
import { userLoggedIn, requestLoginFailure } from "../actions/auth";
|
||||
import { userLoggedIn, requestLoginFailure,userLoggedOut } from "../actions/auth";
|
||||
import { fetchCurrentUserSuccess, fetchCurrentUserFailure } from "../actions/user";
|
||||
import setAuthorizationHeader from "../data/setAuthorizationHeader";
|
||||
|
||||
import api from "../data/api";
|
||||
@@ -9,8 +10,8 @@ import Router from 'next/router';
|
||||
export function* requestLoginSaga(action) {
|
||||
try {
|
||||
const res = yield call(api.user.login, action.data);
|
||||
console.log("requestLoginSaga")
|
||||
console.log(res)
|
||||
console.log("requestLoginSaga")
|
||||
console.log(res)
|
||||
// console.log(!!res.token)
|
||||
// console.log("---")
|
||||
if (!!res.token) {
|
||||
@@ -27,24 +28,6 @@ export function* requestLoginSaga(action) {
|
||||
} else
|
||||
throw new Error("no token")
|
||||
|
||||
} catch (error) { console.log(error)
|
||||
localStorage.removeItem("ttJWT");
|
||||
setAuthorizationHeader();
|
||||
yield put(requestLoginFailure(error.response));
|
||||
}
|
||||
}
|
||||
|
||||
export function* requestUserSaga(action) {
|
||||
try {
|
||||
const res = yield call(api.user.fetchUser);
|
||||
if (!!res.status === "success") {
|
||||
|
||||
yield put(userLoggedIn(res));
|
||||
//TODO: temporary redirect
|
||||
//Router.push('/Offres');
|
||||
} else
|
||||
throw new Error("no user")
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
localStorage.removeItem("ttJWT");
|
||||
@@ -53,3 +36,34 @@ export function* requestUserSaga(action) {
|
||||
}
|
||||
}
|
||||
|
||||
export function* requestLogoutSaga(action) {
|
||||
console.log("function* requestLogoutSaga")
|
||||
try {
|
||||
localStorage.removeItem("ttJWT")
|
||||
setAuthorizationHeader()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
} finally {
|
||||
yield put(userLoggedOut());
|
||||
}
|
||||
}
|
||||
|
||||
export function* requestUserSaga(action) {
|
||||
try {
|
||||
console.log('function* requestUserSaga')
|
||||
const res = yield call(api.user.fetchUser);
|
||||
console.log(res);
|
||||
if (res.status === "success") {
|
||||
|
||||
yield put(fetchCurrentUserSuccess(res.user));
|
||||
//TODO: temporary redirect
|
||||
//Router.push('/Offres');
|
||||
} else
|
||||
throw new Error("no user")
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
yield put(fetchCurrentUserFailure(error.response));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ function configureStore (initialState = exampleInitialState) {
|
||||
)
|
||||
|
||||
store.sagaTask = sagaMiddleware.run(rootSaga)
|
||||
//console.debug("sagaMiddleware.run(rootSaga)");
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,16 @@ export const USER_LOGGED_IN = "USER_LOGGED_IN";
|
||||
export const USER_LOGGED_OUT = "USER_LOGGED_OUT";
|
||||
|
||||
export const REQUEST_LOGIN = "REQUEST_LOGIN";
|
||||
export const REQUEST_LOGOUT = "REQUEST_LOGOUT";
|
||||
export const REQUEST_LOGIN_FAILURE = "REQUEST_LOGIN_FAILURE";
|
||||
|
||||
export const REQUEST_OAUTH_LOGIN = "REQUEST_OAUTH_LOGIN";
|
||||
export const REQUEST_OAUTH_LOGIN_FAILURE = "REQUEST_OAUTH_LOGIN_FAILURE";
|
||||
|
||||
//USER
|
||||
export const FETCH_CURRENT_USER_REQUEST = "FETCH_CURRENT_USER_REQUEST";
|
||||
export const FETCH_CURRENT_USER_SUCCESS = "FETCH_CURRENT_USER_SUCCESS";
|
||||
export const FETCH_CURRENT_USER_FAILURE = "FETCH_CURRENT_USER_FAILURE";
|
||||
|
||||
//ADS
|
||||
export const FETCH_ADS_REQUEST = "FETCH_ADS_REQUEST";
|
||||
|
||||
+1
-3
@@ -161,6 +161,7 @@ app.prepare()
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
expressApp.get('/push/info/:token', (req, res) => {
|
||||
|
||||
var token = req.params.token
|
||||
@@ -240,7 +241,6 @@ app.prepare()
|
||||
)
|
||||
.catch(err => console.log(err)
|
||||
)
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
@@ -268,7 +268,6 @@ app.prepare()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
expressApp.get('/static/js/*.js', (req, res) => {
|
||||
|
||||
const parsedUrl = parse(req.url, true);
|
||||
@@ -285,7 +284,6 @@ app.prepare()
|
||||
app.serveStatic(req, res, filePath);
|
||||
})
|
||||
|
||||
|
||||
expressApp.get('*', (req, res) => {
|
||||
return handle(req, res)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user