Removes a set of folders outside SRC and implements the changes needed to fix #7
No files matched your search
@@ -1,51 +0,0 @@
|
||||
import React from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
class About extends React.Component {
|
||||
state = {
|
||||
open: true
|
||||
}
|
||||
|
||||
handleClickOpen = () => {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose = () => {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='alert-dialog-title'
|
||||
aria-describedby='alert-dialog-description'>
|
||||
<DialogTitle id='alert-dialog-title'>
|
||||
{"Section under development."}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id='alert-dialog-description'>
|
||||
The functionality of this section has not been developed yet. We expect to have it for November 2018. Thanks for your understanding.
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary' autoFocus>
|
||||
Close
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default About
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react'
|
||||
import UserList from './UserList'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
const Browse = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<UserList />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
export default Browse
|
||||
@@ -1,52 +0,0 @@
|
||||
import React from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
class Contact extends React.Component {
|
||||
state = {
|
||||
open: true
|
||||
}
|
||||
|
||||
handleClickOpen = () => {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose = () => {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='alert-dialog-title'
|
||||
aria-describedby='alert-dialog-description'>
|
||||
<DialogTitle id='alert-dialog-title'>
|
||||
{"Section under development."}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id='alert-dialog-description'>
|
||||
The functionality of this section has not been developed yet. We expect to have it for November 2018. Thanks for your understanding.
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary' autoFocus>
|
||||
Close
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Contact
|
||||
@@ -1,258 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {graphql, compose} from 'react-apollo'
|
||||
import {getDescendentsQuery} from '../queries/queries'
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardActionArea from '@material-ui/core/CardActionArea'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
|
||||
// Material UI Nestled Lists
|
||||
import ListSubheader from '@material-ui/core/ListSubheader';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import Collapse from '@material-ui/core/Collapse';
|
||||
import ExpandLess from '@material-ui/icons/ExpandLess';
|
||||
import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||
import StarBorder from '@material-ui/icons/StarBorder';
|
||||
|
||||
// Images
|
||||
import PortraitImage from '../img/portrait.jpg'
|
||||
|
||||
const styles = theme => ({
|
||||
card: {
|
||||
maxWidth: 300,
|
||||
minWidth: 300,
|
||||
paddingTop: '30'
|
||||
},
|
||||
media: {
|
||||
height: 0,
|
||||
paddingTop: '56.25%', // 16:9,
|
||||
marginTop: '30',
|
||||
minWidth: 300
|
||||
},
|
||||
typography: {
|
||||
maxWidth: 345,
|
||||
minWidth: 300,
|
||||
paddingTop: '30'
|
||||
},
|
||||
appBar: {
|
||||
position: 'relative'
|
||||
},
|
||||
flex: {
|
||||
flex: 1
|
||||
},
|
||||
grid: {
|
||||
paddingTop: '30',
|
||||
marginTop: 30
|
||||
},
|
||||
list: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 25
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit,
|
||||
marginTop: theme.spacing.unit * 3
|
||||
},
|
||||
nested: {
|
||||
paddingLeft: theme.spacing.unit * 4,
|
||||
},
|
||||
})
|
||||
|
||||
class DescendentsTree extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
id: '',
|
||||
open: true
|
||||
}
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.setState(state => ({ open: !state.open }));
|
||||
};
|
||||
|
||||
displayIcons(amount) {
|
||||
|
||||
switch (amount) {
|
||||
case 1: return (
|
||||
<div>
|
||||
<ListItemIcon>
|
||||
<StarBorder />
|
||||
</ListItemIcon>
|
||||
</div>
|
||||
)
|
||||
case 2: return (
|
||||
<div>
|
||||
<ListItemIcon>
|
||||
<StarBorder />
|
||||
</ListItemIcon>
|
||||
<ListItemIcon>
|
||||
<StarBorder />
|
||||
</ListItemIcon>
|
||||
</div>
|
||||
)
|
||||
case 3: return (
|
||||
<div>
|
||||
<ListItemIcon>
|
||||
<StarBorder />
|
||||
</ListItemIcon>
|
||||
<ListItemIcon>
|
||||
<StarBorder />
|
||||
</ListItemIcon>
|
||||
<ListItemIcon>
|
||||
<StarBorder />
|
||||
</ListItemIcon>
|
||||
</div>
|
||||
)
|
||||
default: return(<div/>)
|
||||
}
|
||||
}
|
||||
|
||||
displayNestedListItems(node, level) {
|
||||
|
||||
const { classes } = this.props
|
||||
return node.descendents.map(descendent => {
|
||||
return (
|
||||
<div key={descendent.alias}>
|
||||
<ListItem button className={classes.nested}>
|
||||
{this.displayIcons(level)}
|
||||
<Card className={classes.card}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.media}
|
||||
image={PortraitImage}
|
||||
title='User Profile'
|
||||
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
{descendent.alias}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Grid container justify='center' spacing={8}>
|
||||
<Grid item />
|
||||
</Grid>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</ListItem>
|
||||
{this.displayNestedList(descendent, level)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
displayNestedList(descendent, level) {
|
||||
const primaryText = "Children of " + descendent.alias
|
||||
if (descendent.descendents !== undefined) {
|
||||
if (descendent.descendents.length > 0) {
|
||||
return(
|
||||
<List component="div" disablePadding>
|
||||
<ListItem button onClick={ () => {
|
||||
this.setState(state => ({ [descendent.alias]: !state[descendent.alias] }));
|
||||
}
|
||||
}>
|
||||
<ListItemText inset primary={primaryText} />
|
||||
{this.state[descendent.alias] ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItem>
|
||||
<Collapse in={this.state[descendent.alias]} timeout="auto" unmountOnExit>
|
||||
{this.displayNestedListItems(descendent, level + 1)}
|
||||
</Collapse>
|
||||
</List>
|
||||
)
|
||||
} else {
|
||||
return (<div/>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
displayTopList () {
|
||||
let data = this.props.data
|
||||
const { classes } = this.props
|
||||
|
||||
if (data.loading) {
|
||||
return (<div> Loading Descendents... </div>)
|
||||
} else {
|
||||
if (data.users_Descendents === undefined) {
|
||||
return (<div> No Descendents to Display </div>)
|
||||
} else {
|
||||
return data.users_Descendents.map(descendent => {
|
||||
return (
|
||||
<div key={descendent.alias}>
|
||||
|
||||
<ListItem button>
|
||||
{this.displayIcons(1)}
|
||||
<Card className={classes.card}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.media}
|
||||
image={PortraitImage}
|
||||
title='User Profile'
|
||||
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant='headline' component='h2'>
|
||||
{descendent.alias}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Grid container justify='center' spacing={8}>
|
||||
<Grid item />
|
||||
</Grid>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</ListItem>
|
||||
|
||||
{this.displayNestedList(descendent, 1)}
|
||||
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<div>
|
||||
<List
|
||||
component="nav"
|
||||
subheader={<ListSubheader component="div"></ListSubheader>}
|
||||
className={classes.list}
|
||||
>
|
||||
{this.displayTopList()}
|
||||
</List>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(getDescendentsQuery, { // What follows is the way to pass a parameter to a query.
|
||||
options: (props) => {
|
||||
return {
|
||||
variables: {
|
||||
name: 'getDescendentsQuery',
|
||||
id: props.userId
|
||||
}
|
||||
}
|
||||
}}),
|
||||
withStyles(styles)
|
||||
)(DescendentsTree) // This technique binds more than one query to a single component.
|
||||
@@ -1,104 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import { compose } from 'recompose'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
padding: 100
|
||||
},
|
||||
grid: {
|
||||
margin: theme.spacing.unit,
|
||||
width: '50%'
|
||||
},
|
||||
typography: {
|
||||
width: '100%',
|
||||
marginTop: 20,
|
||||
marginBottom: 20
|
||||
},
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
[theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 900,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
}
|
||||
})
|
||||
|
||||
class Home extends Component {
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<main className={classes.layout}>
|
||||
<div className={classes.heroContent}>
|
||||
<Typography
|
||||
variant='display3'
|
||||
align='center'
|
||||
color='textPrimary'
|
||||
gutterBottom
|
||||
>
|
||||
Collaborate. Innovate. Evolve.
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='title'
|
||||
align='center'
|
||||
color='textSecondary'
|
||||
component='h3'
|
||||
>
|
||||
Welcome to Advanced Algos Users Module
|
||||
</Typography>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Grid container justify='center' spacing={24}>
|
||||
<Grid className={classes.grid} item>
|
||||
<Typography className={classes.typography} gutterBottom variant='headline' component='h2'>
|
||||
Intro
|
||||
</Typography>
|
||||
<Typography className={classes.typography} component='p'>
|
||||
This module is responsible for managing users across the Advanced Algos system. Here you can browse the Users Directory, search for users and get to their profiles. You can create your own User profile if you sign up, or manage it if you already have one by logging in.
|
||||
</Typography>
|
||||
<Typography className={classes.typography} gutterBottom variant='headline' component='h2'>
|
||||
Development Status
|
||||
</Typography>
|
||||
<Typography className={classes.typography} component='p'>
|
||||
This module is is currently under development. Implementation started 1st of September 2018 and this is the result of the 3rd sprint of 2 weeks of work each.
|
||||
</Typography>
|
||||
<Typography className={classes.typography} gutterBottom variant='headline' component='h2'>
|
||||
What can you do?
|
||||
</Typography>
|
||||
<Typography className={classes.typography} component='p'>
|
||||
Currently you can use the Browse section to list all registered users. At the Search page you can searh for users by name. Clicking on View Profile you can see some more info about that user. You can signup with your Github account and manage your profile information while logged in. While loggedin, you can edit your profile info, define your referrer and view your descendants. You will find all features under develpment with a dialog indicating it is not ready.
|
||||
</Typography>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withStyles(styles)
|
||||
)(Home)
|
||||
@@ -1,135 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {graphql, compose} from 'react-apollo'
|
||||
import {getUserByAuthIdQuery} from '../queries/queries'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import Button from '@material-ui/core/Button'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
|
||||
// icons
|
||||
import UserIcon from '@material-ui/icons/Person'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const UserLink = props => <Link to='/users/user' {...props} />
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
flex: {
|
||||
flexGrow: 1,
|
||||
marginLeft: 30
|
||||
},
|
||||
menuButton: {
|
||||
marginLeft: -12,
|
||||
marginRight: 20
|
||||
},
|
||||
cssRoot: {
|
||||
color: '#FFFFFF',
|
||||
backgroundColor: theme.palette.secondary,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.dark
|
||||
},
|
||||
whiteSpace: 'nowrap',
|
||||
paddingRight: 2 * theme.spacing.unit,
|
||||
paddingLeft: 2 * theme.spacing.unit
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit
|
||||
},
|
||||
leftIcon: {
|
||||
marginRight: theme.spacing.unit
|
||||
},
|
||||
rightIcon: {
|
||||
marginLeft: theme.spacing.unit
|
||||
},
|
||||
iconSmall: {
|
||||
fontSize: 20
|
||||
}
|
||||
})
|
||||
|
||||
class LoggedInUser extends Component {
|
||||
|
||||
displayLoggedInUser () {
|
||||
const user = this.props.data.users_UserByAuthId
|
||||
const { classes, match } = this.props
|
||||
|
||||
if (user) {
|
||||
let displayName = 'No Display Name'
|
||||
|
||||
if (
|
||||
user.alias !== null &&
|
||||
user.alias !== ''
|
||||
) { displayName = user.alias }
|
||||
|
||||
if (
|
||||
user.firstName !== null &&
|
||||
user.firstName !== ''
|
||||
) { displayName = user.firstName }
|
||||
|
||||
if (
|
||||
user.firstName !== null &&
|
||||
user.firstName !== '' &&
|
||||
user.lastName !== null &&
|
||||
user.lastName !== ''
|
||||
) { displayName = user.firstName + ' ' + user.lastName }
|
||||
|
||||
let authArray = this.props.authId.split('|')
|
||||
let identityProvider = authArray[0]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
variant='text'
|
||||
size='small'
|
||||
className={classNames(classes.button, classes.cssRoot)}
|
||||
title='Manage Your Profile'
|
||||
component={UserLink}
|
||||
to={`${match.url}/user`}>
|
||||
<UserIcon className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Your Profile
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
|
||||
}
|
||||
|
||||
render () {
|
||||
if (this.loggedInUserStored !== true) {
|
||||
let user = this.props.data.users_UserByAuthId
|
||||
|
||||
if (user !== undefined) {
|
||||
localStorage.setItem('loggedInUser', JSON.stringify(this.props.data.users_UserByAuthId))
|
||||
this.loggedInUserStored = true
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{this.displayLoggedInUser()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(getUserByAuthIdQuery, { // What follows is the way to pass a parameter to a query.
|
||||
options: (props) => {
|
||||
return {
|
||||
variables: {
|
||||
authId: props.authId
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
withStyles(styles)
|
||||
)(LoggedInUser)
|
||||
@@ -1,151 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import classNames from 'classnames'
|
||||
import AppBar from '@material-ui/core/AppBar'
|
||||
import Toolbar from '@material-ui/core/Toolbar'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Button from '@material-ui/core/Button'
|
||||
|
||||
// icons
|
||||
import UsersIcon from '@material-ui/icons/People'
|
||||
import BrowseIcon from '@material-ui/icons/ImportContacts'
|
||||
import SearchIcon from '@material-ui/icons/Search'
|
||||
import ContactIcon from '@material-ui/icons/ContactMail'
|
||||
import AboutIcon from '@material-ui/icons/FormatShapes'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
// components
|
||||
import LoggedInUser from './LoggedInUser'
|
||||
|
||||
const HomeLink = props => <Link to='/users' {...props} />
|
||||
const BrowseLink = props => <Link to='/users/browse' {...props} />
|
||||
const SearchLink = props => <Link to='/users/search' {...props} />
|
||||
const AboutLink = props => <Link to='/users/about' {...props} />
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1
|
||||
},
|
||||
flex: {
|
||||
flexGrow: 1,
|
||||
marginLeft: 30
|
||||
},
|
||||
menuButton: {
|
||||
marginLeft: -12,
|
||||
marginRight: 20
|
||||
},
|
||||
cssRoot: {
|
||||
color: '#FFFFFF',
|
||||
backgroundColor: theme.palette.secondary,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.dark
|
||||
},
|
||||
whiteSpace: 'nowrap',
|
||||
paddingRight: 2 * theme.spacing.unit,
|
||||
paddingLeft: 2 * theme.spacing.unit
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit
|
||||
},
|
||||
leftIcon: {
|
||||
marginRight: theme.spacing.unit
|
||||
},
|
||||
rightIcon: {
|
||||
marginLeft: theme.spacing.unit
|
||||
},
|
||||
iconSmall: {
|
||||
fontSize: 20
|
||||
}
|
||||
})
|
||||
|
||||
class NavBar extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
authId: null
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
let user = localStorage.getItem('user')
|
||||
let authId
|
||||
|
||||
if (user !== null && user !== undefined && user !== 'undefined') {
|
||||
user = JSON.parse(user)
|
||||
authId = user.authId
|
||||
}
|
||||
|
||||
if (authId !== null && authId !== undefined && authId !== 'undefined') {
|
||||
this.setState({ authId: authId })
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes, user, match } = this.props
|
||||
console.log('NavBar: ', user, match)
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar position='static' color='secondary'>
|
||||
<Toolbar>
|
||||
<Typography variant='h5' color='inherit' className={classes.flex}>
|
||||
Users Module
|
||||
</Typography>
|
||||
<Button
|
||||
variant='text'
|
||||
size='small'
|
||||
className={classNames(classes.button, classes.cssRoot)}
|
||||
title='Users Home'
|
||||
component={HomeLink}
|
||||
to={`${match.url}`}>
|
||||
<UsersIcon className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Home
|
||||
</Button>
|
||||
<Button
|
||||
variant='text'
|
||||
size='small'
|
||||
className={classNames(classes.button, classes.cssRoot)}
|
||||
title='Browse the Users Directory'
|
||||
component={BrowseLink}
|
||||
to={`${match.url}/browse`}>
|
||||
<BrowseIcon className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Directory
|
||||
</Button>
|
||||
<Button
|
||||
variant='text'
|
||||
size='small'
|
||||
className={classNames(classes.button, classes.cssRoot)}
|
||||
title='Search Users'
|
||||
component={SearchLink}
|
||||
to={`${match.url}/search`}>
|
||||
<SearchIcon className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Search
|
||||
</Button>
|
||||
<Button
|
||||
variant='text'
|
||||
size='small'
|
||||
className={classNames(classes.button, classes.cssRoot)}
|
||||
title='About the Users Module'
|
||||
component={AboutLink}
|
||||
to={`${match.url}/about`}>
|
||||
<AboutIcon className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
About
|
||||
</Button>
|
||||
<LoggedInUser {...this.props} authId={this.state.authId} />
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
NavBar.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
user: PropTypes.object,
|
||||
match: PropTypes.object
|
||||
}
|
||||
|
||||
export default withStyles(styles)(NavBar)
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import React from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
class Contact extends React.Component {
|
||||
state = {
|
||||
open: true
|
||||
}
|
||||
|
||||
handleClickOpen = () => {
|
||||
this.setState({ open: true })
|
||||
}
|
||||
|
||||
handleClose = () => {
|
||||
this.setState({ open: false })
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<Dialog
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
aria-labelledby='alert-dialog-title'
|
||||
aria-describedby='alert-dialog-description'>
|
||||
<DialogTitle id='alert-dialog-title'>
|
||||
{"Section under development."}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id='alert-dialog-description'>
|
||||
The functionality of this section has not been developed yet. We expect to have it for November 2018. Thanks for your understanding.
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleClose} color='primary' autoFocus>
|
||||
Close
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Contact
|
||||
@@ -1,497 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {graphql, compose} from 'react-apollo'
|
||||
import {getRolesQuery, updateUserMutation, getUsersQuery} from '../queries/queries'
|
||||
|
||||
// Material-ui
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import InputLabel from '@material-ui/core/InputLabel'
|
||||
import Input from '@material-ui/core/Input'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
import Checkbox from '@material-ui/core/Checkbox'
|
||||
import FormGroup from '@material-ui/core/FormGroup'
|
||||
import Select from '@material-ui/core/Select'
|
||||
import FormHelperText from '@material-ui/core/FormHelperText'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
// Images
|
||||
import GithubLogo from '../img/github-logo.png'
|
||||
import Auth0Logo from '../img/auth0-logo.png'
|
||||
import AALogo from '../img/aa-logo.png'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '50%',
|
||||
flexGrow: 1,
|
||||
padding: 10,
|
||||
marginLeft: '25%',
|
||||
marginTop: '2%'
|
||||
},
|
||||
inputField: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 25
|
||||
},
|
||||
typography: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 40
|
||||
},
|
||||
checkbox: {
|
||||
width: 150,
|
||||
marginLeft: '0%',
|
||||
marginTop: 20
|
||||
},
|
||||
selectEmpty: {
|
||||
marginTop: theme.spacing.unit * 2
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit,
|
||||
marginTop: theme.spacing.unit * 3
|
||||
},
|
||||
img: {
|
||||
display: 'block',
|
||||
marginTop: 20,
|
||||
maxWidth: 120,
|
||||
maxHeight: 24
|
||||
}
|
||||
})
|
||||
|
||||
class ProfileSheet extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.defaultValuesSet = false
|
||||
|
||||
this.state = {
|
||||
id: '',
|
||||
firstName: '',
|
||||
middleName: '',
|
||||
lastName: '',
|
||||
bio: '',
|
||||
email: '',
|
||||
emailVerified: 0,
|
||||
isDeveloper: 0,
|
||||
isTrader: 0,
|
||||
isDataAnalyst: 0,
|
||||
roleId: '1',
|
||||
firstNameError: false,
|
||||
middleNameError: false,
|
||||
lastNameError: false,
|
||||
bioError: false
|
||||
}
|
||||
}
|
||||
|
||||
displayRoles () {
|
||||
var data = this.props.getRolesQuery // When there is more than one query binded to a single componente 'data' is replaced by thename of the query given below at the binding operation.
|
||||
if (data.loading) {
|
||||
return (
|
||||
<MenuItem><em>Loading roles</em></MenuItem>
|
||||
)
|
||||
} else {
|
||||
return data.users_Roles.map(role => {
|
||||
return (
|
||||
<MenuItem key={role.id} value={role.id}>{ role.name }</MenuItem>
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
submitForm (e) {
|
||||
e.preventDefault()
|
||||
this.props.updateUserMutation({
|
||||
variables: {
|
||||
firstName: this.state.firstName,
|
||||
middleName: this.state.middleName,
|
||||
lastName: this.state.lastName,
|
||||
bio: this.state.bio,
|
||||
isDeveloper: this.state.isDeveloper,
|
||||
isTrader: this.state.isTrader,
|
||||
isDataAnalyst: this.state.isDataAnalyst,
|
||||
roleId: this.state.roleId
|
||||
},
|
||||
refetchQueries: [{ query: getUsersQuery}] // This allow us to re run whatever queries are necesary after the mutation.
|
||||
})
|
||||
|
||||
/* Before we are done, we need to update the state of the local storage. */
|
||||
|
||||
let user = JSON.parse(localStorage.getItem('loggedInUser'))
|
||||
|
||||
user.firstName = this.state.firstName
|
||||
user.middleName = this.state.middleName
|
||||
user.lastName = this.state.lastName
|
||||
user.bio = this.state.bio
|
||||
user.isDeveloper = this.state.isDeveloper
|
||||
user.isTrader = this.state.isTrader
|
||||
user.isDataAnalyst = this.state.isDataAnalyst
|
||||
user.role.id = this.state.roleId
|
||||
|
||||
localStorage.setItem('loggedInUser', JSON.stringify(user))
|
||||
}
|
||||
|
||||
handleCheckBoxes (e) {
|
||||
let fieldValue
|
||||
if (e.target.checked === true) {
|
||||
fieldValue = 1
|
||||
} else {
|
||||
fieldValue = 0
|
||||
|
||||
/* When the user unchecks one of the checkboxes, we need to make sure that that Role is not the one selected at the SELECT,
|
||||
and if it is, then we need to automatically select another one */
|
||||
|
||||
switch (e.target.id) {
|
||||
case 'isDeveloper':
|
||||
if (this.state.roleId === '2') {
|
||||
this.setState({ roleId: '1'})
|
||||
}
|
||||
break
|
||||
|
||||
case 'isTrader':
|
||||
if (this.state.roleId === '3') {
|
||||
this.setState({ roleId: '1'})
|
||||
}
|
||||
break
|
||||
|
||||
case 'isDataAnalyst':
|
||||
if (this.state.roleId === '4') {
|
||||
this.setState({ roleId: '1'})
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
this.setState({ [e.target.id]: fieldValue})
|
||||
}
|
||||
|
||||
handleSelect (e) {
|
||||
/*
|
||||
Whenever the select component changes its value, we need to activate the type of role selected.
|
||||
To do so, we change the state of the corresponding type of role here.
|
||||
*/
|
||||
|
||||
switch (e.target.value) {
|
||||
case '2':
|
||||
this.setState({ isDeveloper: 1})
|
||||
break
|
||||
case '3':
|
||||
this.setState({ isTrader: 1})
|
||||
break
|
||||
case '4':
|
||||
this.setState({ isDataAnalyst: 1})
|
||||
break
|
||||
default:
|
||||
}
|
||||
|
||||
this.setState({ roleId: e.target.value })
|
||||
}
|
||||
|
||||
handleTextField (e) {
|
||||
/*
|
||||
We will do some basic input validations here. If something is wrong we will turn on the error sign on the textfield.
|
||||
*/
|
||||
|
||||
let value = e.target.value
|
||||
|
||||
switch (e.target.id) {
|
||||
case 'firstName':
|
||||
if (value.length > 30) {
|
||||
this.setState({firstNameError: true})
|
||||
} else {
|
||||
this.setState({firstNameError: false, firstName: value})
|
||||
}
|
||||
break
|
||||
case 'middleName':
|
||||
if (value.length > 30) {
|
||||
this.setState({middleNameError: true})
|
||||
} else {
|
||||
this.setState({middleNameError: false, middleName: value})
|
||||
}
|
||||
break
|
||||
case 'lastName':
|
||||
if (value.length > 50) {
|
||||
this.setState({lastNameError: true})
|
||||
} else {
|
||||
this.setState({lastNameError: false, lastName: value})
|
||||
}
|
||||
break
|
||||
case 'bio':
|
||||
if (value.length > 250) {
|
||||
this.setState({bioError: true})
|
||||
} else {
|
||||
this.setState({bioError: false, bio: value})
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
rightCheckboxValue (stateValue) {
|
||||
if (stateValue === 1) {
|
||||
return true
|
||||
} else { return false }
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
if (this.defaultValuesSet === false) {
|
||||
let authId = localStorage.getItem('authId')
|
||||
let userData = localStorage.getItem('loggedInUser')
|
||||
|
||||
if (userData === 'undefined' || userData === null) { return }
|
||||
|
||||
let user = JSON.parse(userData)
|
||||
this.defaultValuesSet = true
|
||||
|
||||
/* To avoid console warning, we need to take care of the fields that are null. */
|
||||
|
||||
if (user.firstName === null) { user.firstName = '' }
|
||||
if (user.middleName === null) { user.middleName = '' }
|
||||
if (user.lastName === null) { user.lastName = '' }
|
||||
if (user.bio === null) { user.bio = '' }
|
||||
|
||||
/* Now we are ready to set the initial state. */
|
||||
|
||||
this.setState({
|
||||
id: user.id,
|
||||
alias: user.alias,
|
||||
email: user.email,
|
||||
emailVerified: user.emailVerified,
|
||||
firstName: user.firstName,
|
||||
middleName: user.middleName,
|
||||
lastName: user.lastName,
|
||||
bio: user.bio,
|
||||
isDeveloper: user.isDeveloper,
|
||||
isTrader: user.isTrader,
|
||||
isDataAnalyst: user.isDataAnalyst,
|
||||
roleId: user.role.id,
|
||||
authId: authId
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
displayIdentityProvider () {
|
||||
const { classes } = this.props
|
||||
let authId = this.state.authId
|
||||
|
||||
if (authId !== undefined && authId !== null) {
|
||||
let authArray = this.state.authId.split('|')
|
||||
let identityProvider = authArray[0]
|
||||
|
||||
switch (identityProvider) {
|
||||
case 'github':
|
||||
return (
|
||||
<img className={classes.img} src={GithubLogo} alt='Github' />
|
||||
)
|
||||
break
|
||||
case 'auth0':
|
||||
return (
|
||||
<img className={classes.img} src={Auth0Logo} alt='Auth0' />
|
||||
)
|
||||
break
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<Paper className={classes.root}>
|
||||
<Typography className={classes.typography} variant='headline' gutterBottom>
|
||||
Profile Sheet
|
||||
</Typography>
|
||||
<form onSubmit={this.submitForm.bind(this)}>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
Use this form to control the information you keep at the Advanced Algos system about yourself.
|
||||
</Typography>
|
||||
|
||||
<Grid container justify='center' >
|
||||
<Grid item>
|
||||
{this.displayIdentityProvider()}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
This is your basic information we have gotten from the identity provider you used to sign up. This information can not be changed.
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
id='alias'
|
||||
type='text'
|
||||
value={this.state.alias}
|
||||
label='Alias'
|
||||
className={classes.inputField}
|
||||
disabled />
|
||||
|
||||
<TextField
|
||||
id='email'
|
||||
type='text'
|
||||
value={this.state.email}
|
||||
label='Email'
|
||||
className={classes.inputField}
|
||||
disabled />
|
||||
|
||||
<FormControlLabel
|
||||
disabled
|
||||
className={classes.inputField}
|
||||
control={
|
||||
<Checkbox
|
||||
id='emailVerified'
|
||||
checked={this.rightCheckboxValue(this.state.emailVerified)}
|
||||
color='primary'
|
||||
/>
|
||||
}
|
||||
label='Email Verified'
|
||||
/>
|
||||
|
||||
<Grid container justify='center' >
|
||||
<Grid item>
|
||||
<img className={classes.img} src={AALogo} alt='Advanced Algos' />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
Complete your profile with the following optional information. Providing your real name might help other users trust you more.
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
error={this.state.firstNameError}
|
||||
id='firstName'
|
||||
type='text'
|
||||
value={this.state.firstName}
|
||||
label='First Name'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
error={this.state.middleNameError}
|
||||
id='middleName'
|
||||
type='text'
|
||||
value={this.state.middleName}
|
||||
label='Middle Name'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
error={this.state.lastNameError}
|
||||
id='lastName'
|
||||
type='text'
|
||||
value={this.state.lastName}
|
||||
label='Last Name'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
If you wish, you can add a short paragraph with your Bio or anything you would like to communicate to whoever finds your user profile.
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
error={this.state.bioError}
|
||||
id='bio'
|
||||
type='text'
|
||||
value={this.state.bio}
|
||||
label='Bio'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
Check the following options to enable specialized tools designed for each role. You can allways come back and change these settings later.
|
||||
</Typography>
|
||||
|
||||
<FormGroup row className={classes.inputField}>
|
||||
<Grid container justify='center' >
|
||||
<Grid item>
|
||||
<FormControlLabel
|
||||
className={classes.checkbox}
|
||||
control={
|
||||
<Checkbox
|
||||
id='isDeveloper'
|
||||
onChange={this.handleCheckBoxes.bind(this)}
|
||||
checked={this.rightCheckboxValue(this.state.isDeveloper)}
|
||||
color='secondary'
|
||||
/>
|
||||
}
|
||||
label='Developer'
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<FormControlLabel
|
||||
className={classes.checkbox}
|
||||
control={
|
||||
<Checkbox
|
||||
id='isTrader'
|
||||
onChange={this.handleCheckBoxes.bind(this)}
|
||||
checked={this.rightCheckboxValue(this.state.isTrader)}
|
||||
color='secondary'
|
||||
/>
|
||||
}
|
||||
label='Trader'
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<FormControlLabel
|
||||
className={classes.checkbox}
|
||||
control={
|
||||
<Checkbox
|
||||
id='isDataAnalyst'
|
||||
onChange={this.handleCheckBoxes.bind(this)}
|
||||
checked={this.rightCheckboxValue(this.state.isDataAnalyst)}
|
||||
color='secondary'
|
||||
/>
|
||||
}
|
||||
label='Data Analyst'
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</FormGroup>
|
||||
|
||||
<p className={classes.typography}>Your current role determines how the system is going to optimize its user interface to best serves your current needs.</p>
|
||||
|
||||
<FormControl className={classes.inputField}>
|
||||
<InputLabel shrink htmlFor='select'>
|
||||
Current Role
|
||||
</InputLabel>
|
||||
<Select
|
||||
id='select'
|
||||
ref='select'
|
||||
value={this.state.roleId}
|
||||
onChange={this.handleSelect.bind(this)}
|
||||
input={<Input name='Role' id='role-label-placeholder' />}
|
||||
displayEmpty
|
||||
name='select'
|
||||
className={classes.selectEmpty}
|
||||
>
|
||||
{ this.displayRoles() }
|
||||
</Select>
|
||||
<FormHelperText>Select from the list your current role</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<Grid container justify='center' >
|
||||
<Grid item>
|
||||
<Button variant='contained' color='secondary' className={classes.button} onClick={this.submitForm.bind(this)}>Update</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
</Paper>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(getRolesQuery, {name: 'getRolesQuery'}),
|
||||
graphql(updateUserMutation, {name: 'updateUserMutation'}),
|
||||
withStyles(styles)
|
||||
)(ProfileSheet) // This technique binds more than one query to a single component.
|
||||
@@ -1,37 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import UserSearch from './UserSearch'
|
||||
import {compose} from 'react-apollo'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
padding: 60,
|
||||
margin: 2
|
||||
}
|
||||
})
|
||||
|
||||
class Search extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<UserSearch />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withStyles(styles)
|
||||
)(Search)
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react'
|
||||
import UserTabs from './UserTabs'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
|
||||
const User = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<CssBaseline />
|
||||
<UserTabs />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
export default User
|
||||
@@ -1,185 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import {graphql, compose} from 'react-apollo';
|
||||
import {getUsersQuery} from '../queries/queries';
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActionArea from '@material-ui/core/CardActionArea';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import CardMedia from '@material-ui/core/CardMedia';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
|
||||
// Full screen dialog imports (still Material UI)
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
|
||||
import CloseIcon from '@material-ui/icons/Close';
|
||||
import Slide from '@material-ui/core/Slide';
|
||||
|
||||
// components
|
||||
import UserProfile from './UserProfile';
|
||||
|
||||
// Images
|
||||
import PortraitImage from '../img/portrait.jpg'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
padding: 60,
|
||||
margin: 2,
|
||||
},
|
||||
card: {
|
||||
maxWidth: 345,
|
||||
minWidth: 300,
|
||||
paddingTop:'30'
|
||||
},
|
||||
media: {
|
||||
height: 0,
|
||||
paddingTop: '56.25%', // 16:9,
|
||||
marginTop:'30',
|
||||
minWidth: 300
|
||||
},
|
||||
typography: {
|
||||
maxWidth: 345,
|
||||
minWidth: 300,
|
||||
paddingTop:'30'
|
||||
},
|
||||
appBar: {
|
||||
position: 'relative',
|
||||
},
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
grid: {
|
||||
paddingTop: 30,
|
||||
marginTop:'30'
|
||||
},
|
||||
});
|
||||
|
||||
function Transition(props) {
|
||||
return <Slide direction="up" {...props} />;
|
||||
}
|
||||
|
||||
class UserList extends Component {
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
selected: null,
|
||||
open: false
|
||||
}
|
||||
}
|
||||
|
||||
handleClickOpen = () => {
|
||||
this.setState({ open: true });
|
||||
};
|
||||
|
||||
handleClose = () => {
|
||||
this.setState({ open: false });
|
||||
};
|
||||
|
||||
displayUsers(){
|
||||
|
||||
let data = this.props.getUsersQuery;
|
||||
const { classes } = this.props;
|
||||
|
||||
if(data.loading){
|
||||
return ( <div> Loading Users... </div>);
|
||||
} else {
|
||||
return data.users_Users.map(user => {
|
||||
|
||||
return (
|
||||
|
||||
<Grid key={user.id} item>
|
||||
<Card className={classes.card} onClick={ (e) => {
|
||||
this.setState({ selected: user.id});
|
||||
}
|
||||
}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.media}
|
||||
image={PortraitImage}
|
||||
title="User Profile"
|
||||
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant="h5" component="h2">
|
||||
{user.alias}
|
||||
</Typography>
|
||||
<Typography className={classes.typography} gutterBottom>
|
||||
{user.bio}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Grid container justify="center" spacing={8}>
|
||||
<Grid item>
|
||||
<Button onClick={this.handleClickOpen}>User Profile</Button>
|
||||
<Dialog
|
||||
fullScreen
|
||||
open={this.state.open}
|
||||
onClose={this.handleClose}
|
||||
TransitionComponent={Transition}
|
||||
>
|
||||
<AppBar className={classes.appBar}>
|
||||
<Toolbar>
|
||||
<IconButton color="inherit" onClick={this.handleClose} aria-label="Close">
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" color="inherit" className={classes.flex}>
|
||||
User Profile
|
||||
</Typography>
|
||||
<Button color="inherit" onClick={this.handleClose}>
|
||||
Close
|
||||
</Button>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Paper className={classes.root}>
|
||||
<UserProfile userId={this.state.selected}/>
|
||||
</Paper>
|
||||
</Dialog>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Button disabled color="primary">
|
||||
Extended Profile
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid container justify="center" spacing={24} className={classes.root}>
|
||||
{this.displayUsers()}
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
UserList.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default compose(
|
||||
graphql(getUsersQuery, {name: "getUsersQuery"}),
|
||||
withStyles(styles)
|
||||
) (UserList); // This technique binds more than one query to a single component.
|
||||
@@ -1,112 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {graphql, compose} from 'react-apollo'
|
||||
import {getUserProfileQuery} from '../queries/queries'
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardActionArea from '@material-ui/core/CardActionArea'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
|
||||
// Images
|
||||
import PortraitImage from '../img/portrait.jpg'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
padding: 60,
|
||||
margin: 2
|
||||
},
|
||||
card: {
|
||||
width: '80%',
|
||||
paddingTop: '30'
|
||||
},
|
||||
media: {
|
||||
height: 0,
|
||||
paddingTop: '56.25%', // 16:9,
|
||||
marginTop: '30',
|
||||
minWidth: '80%'
|
||||
},
|
||||
grid: {
|
||||
paddingTop: '30',
|
||||
marginTop: '30'
|
||||
},
|
||||
typography: {
|
||||
width: '100%',
|
||||
marginTop: 20,
|
||||
marginBottom: 20
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
class UserProfile extends Component {
|
||||
|
||||
displayUserProfile () {
|
||||
const user = this.props.data.users_User
|
||||
const { classes } = this.props
|
||||
|
||||
if (user) {
|
||||
return (
|
||||
<Grid key={user.id} item>
|
||||
|
||||
<Card className={classes.card} onClick={(e) => {
|
||||
this.setState({ selected: user.id})
|
||||
}
|
||||
}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.media}
|
||||
image={PortraitImage}
|
||||
title='User Profile'
|
||||
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography className={classes.typography} gutterBottom variant='h5' component='h2'>
|
||||
{ user.firstName } { user.lastName } ( {user.alias} )
|
||||
</Typography>
|
||||
<Divider />
|
||||
|
||||
<Typography className={classes.typography} align='left' gutterBottom variant='subtitle1' component='h2'>
|
||||
{ user.role.name }
|
||||
</Typography>
|
||||
<Divider />
|
||||
|
||||
<Typography className={classes.typography} component='p'>
|
||||
{ user.bio }
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
} else {
|
||||
return (<div>No User selected...</div>)
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Grid container justify='center' spacing={24}>
|
||||
{this.displayUserProfile()}
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(getUserProfileQuery, { // What follows is the way to pass a parameter to a query.
|
||||
options: (props) => {
|
||||
return {
|
||||
variables: {
|
||||
name: 'getUserProfileQuery',
|
||||
id: props.userId
|
||||
}
|
||||
}
|
||||
}}),
|
||||
withStyles(styles)
|
||||
)(UserProfile) // This technique binds more than one query to a single component.
|
||||
@@ -1,267 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {graphql, compose} from 'react-apollo'
|
||||
import {getUsersBySearchFields} from '../queries/queries'
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import CardActionArea from '@material-ui/core/CardActionArea'
|
||||
import CardActions from '@material-ui/core/CardActions'
|
||||
import CardContent from '@material-ui/core/CardContent'
|
||||
import CardMedia from '@material-ui/core/CardMedia'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
|
||||
// Images
|
||||
import PortraitImage from '../img/portrait.jpg'
|
||||
|
||||
const styles = theme => ({
|
||||
card: {
|
||||
maxWidth: 150,
|
||||
minWidth: 150,
|
||||
paddingTop: '30',
|
||||
marginBottom: 40
|
||||
},
|
||||
media: {
|
||||
height: 0,
|
||||
paddingTop: '56.25%', // 16:9,
|
||||
marginTop: '30',
|
||||
minWidth: 300
|
||||
},
|
||||
typography: {
|
||||
maxWidth: 345,
|
||||
minWidth: 300,
|
||||
paddingTop: '30'
|
||||
},
|
||||
appBar: {
|
||||
position: 'relative'
|
||||
},
|
||||
flex: {
|
||||
flex: 1
|
||||
},
|
||||
grid: {
|
||||
paddingTop: '30',
|
||||
marginTop: 30
|
||||
},
|
||||
inputField: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 25
|
||||
},
|
||||
formTypography: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 40
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit,
|
||||
marginTop: theme.spacing.unit * 3
|
||||
}
|
||||
})
|
||||
|
||||
class UserSearch extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
alias: '',
|
||||
firstName: '',
|
||||
middleName: '',
|
||||
lastName: ''
|
||||
}
|
||||
}
|
||||
|
||||
submitForm (e) {
|
||||
e.preventDefault()
|
||||
|
||||
this.props.getUsersBySearchFields.variables.alias = this.state.alias
|
||||
this.props.getUsersBySearchFields.variables.firstName = this.state.firstName
|
||||
this.props.getUsersBySearchFields.variables.middleName = this.state.middleName
|
||||
this.props.getUsersBySearchFields.variables.lastName = this.state.lastName
|
||||
|
||||
this.props.getUsersBySearchFields.refetch({})
|
||||
}
|
||||
|
||||
handleTextField (e) {
|
||||
/*
|
||||
We will do some basic input validations here. If something is wrong we will turn on the error sign on the textfield.
|
||||
*/
|
||||
|
||||
let value = e.target.value
|
||||
|
||||
switch (e.target.id) {
|
||||
case 'alias':
|
||||
if (value.length > 30) {
|
||||
this.setState({aliasError: true})
|
||||
} else {
|
||||
this.setState({aliasError: false, alias: value})
|
||||
}
|
||||
break
|
||||
case 'firstName':
|
||||
if (value.length > 30) {
|
||||
this.setState({firstNameError: true})
|
||||
} else {
|
||||
this.setState({firstNameError: false, firstName: value})
|
||||
}
|
||||
break
|
||||
case 'middleName':
|
||||
if (value.length > 30) {
|
||||
this.setState({middleNameError: true})
|
||||
} else {
|
||||
this.setState({middleNameError: false, middleName: value})
|
||||
}
|
||||
break
|
||||
case 'lastName':
|
||||
if (value.length > 50) {
|
||||
this.setState({lastNameError: true})
|
||||
} else {
|
||||
this.setState({lastNameError: false, lastName: value})
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
selectText () {
|
||||
if (this.props.selectButton === true) {
|
||||
return (<span>{this.props.selectText}</span>)
|
||||
} else {
|
||||
return (<span />)
|
||||
}
|
||||
}
|
||||
|
||||
selectButton (user) {
|
||||
if (this.props.selectButton === true) {
|
||||
return (
|
||||
<Button id={user.id} ref={user.id} color='primary' onClick={() => {
|
||||
this.props.onSelect(user) // This sends the user to the parent component
|
||||
}}>
|
||||
Select
|
||||
</Button>
|
||||
)
|
||||
} else {
|
||||
return (<div />)
|
||||
}
|
||||
}
|
||||
|
||||
displayUsers () {
|
||||
let data = this.props.getUsersBySearchFields
|
||||
const { classes } = this.props
|
||||
|
||||
if (data.loading) {
|
||||
return (<div> Loading Users... </div>)
|
||||
} else {
|
||||
if (data.users_UsersSearch === undefined) {
|
||||
return (<div> No Users to Display </div>)
|
||||
} else {
|
||||
return data.users_UsersSearch.map(user => {
|
||||
return (
|
||||
|
||||
<Grid key={user.id} item>
|
||||
<Card className={classes.card} onClick={(e) => {
|
||||
this.setState({ selected: user.id})
|
||||
}
|
||||
}>
|
||||
<CardActionArea>
|
||||
<CardMedia
|
||||
className={classes.media}
|
||||
image={PortraitImage}
|
||||
title='User Profile'
|
||||
|
||||
/>
|
||||
<CardContent>
|
||||
<Typography gutterBottom variant='h5' component='h2'>
|
||||
{user.alias}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
<CardActions>
|
||||
<Grid container justify='center' spacing={8}>
|
||||
<Grid item>
|
||||
{this.selectButton(user)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.submitForm.bind(this)}>
|
||||
|
||||
<Typography className={classes.formTypography} variant='body2' gutterBottom align='left'>
|
||||
Use any of these fileds to search for users. {this.selectText()}
|
||||
</Typography>
|
||||
|
||||
<TextField
|
||||
error={this.state.aliasError}
|
||||
id='alias'
|
||||
type='text'
|
||||
value={this.state.alias}
|
||||
label='Alias'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
error={this.state.firstNameError}
|
||||
id='firstName'
|
||||
type='text'
|
||||
value={this.state.firstName}
|
||||
label='First Name'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
error={this.state.middleNameError}
|
||||
id='middleName'
|
||||
type='text'
|
||||
value={this.state.middleName}
|
||||
label='Middle Name'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
error={this.state.lastNameError}
|
||||
id='lastName'
|
||||
type='text'
|
||||
value={this.state.lastName}
|
||||
label='Last Name'
|
||||
className={classes.inputField}
|
||||
onChange={this.handleTextField.bind(this)}
|
||||
/>
|
||||
|
||||
<Grid container justify='center' >
|
||||
<Grid item>
|
||||
<Button variant='contained' color='secondary' className={classes.button} onClick={this.submitForm.bind(this)}>Search</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
|
||||
<Grid container className={classes.grid} justify='center' spacing={24}>
|
||||
{this.displayUsers()}
|
||||
</Grid>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(getUsersBySearchFields, {name: 'getUsersBySearchFields'}),
|
||||
withStyles(styles)
|
||||
)(UserSearch) // This technique binds more than one query to a single component.
|
||||
@@ -1,85 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Tabs from '@material-ui/core/Tabs';
|
||||
import Tab from '@material-ui/core/Tab';
|
||||
import ProfileSheetIcon from '@material-ui/icons/Create';
|
||||
import ProfileImagesIcon from '@material-ui/icons/Wallpaper';
|
||||
import YourReferrerIcon from '@material-ui/icons/AccessibilityNew';
|
||||
import DescendentsIcon from '@material-ui/icons/DeviceHub';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
||||
// Components
|
||||
|
||||
import ProfileSheet from './ProfileSheet';
|
||||
import ProfileImages from './ProfileImages';
|
||||
import YourReferrer from './YourReferrer';
|
||||
import YourDescendents from './YourDescendents';
|
||||
|
||||
function TabContainer(props) {
|
||||
return (
|
||||
<Typography component="div" style={{ padding: 8 * 3 }}>
|
||||
{props.children}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
TabContainer.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
},
|
||||
});
|
||||
|
||||
class UserTabs extends React.Component {
|
||||
state = {
|
||||
value: 0
|
||||
};
|
||||
|
||||
handleChange = (event, value) => {
|
||||
this.setState({ value });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { value } = this.state;
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<AppBar position="static" color="default">
|
||||
<Tabs
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
scrollable
|
||||
scrollButtons="off"
|
||||
indicatorColor="primary"
|
||||
textColor="primary"
|
||||
>
|
||||
<Tab label="Profile Sheet" icon={<ProfileSheetIcon />} />
|
||||
<Tab label="Profile Images" icon={<ProfileImagesIcon />} />
|
||||
<Tab label="Your Referrer" icon={<YourReferrerIcon />} />
|
||||
<Tab label="Your Descendents" icon={<DescendentsIcon />} />
|
||||
</Tabs>
|
||||
</AppBar>
|
||||
{value === 0 && <TabContainer><ProfileSheet/></TabContainer>}
|
||||
{value === 1 && <TabContainer><ProfileImages/></TabContainer>}
|
||||
{value === 2 && <TabContainer><YourReferrer/></TabContainer>}
|
||||
{value === 3 && <TabContainer><YourDescendents/></TabContainer>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
UserTabs.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(UserTabs);
|
||||
@@ -1,86 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {compose} from 'react-apollo'
|
||||
|
||||
// Materia UI
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
|
||||
// components
|
||||
import DescendentsTree from './DescendentsTree'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '50%',
|
||||
flexGrow: 1,
|
||||
padding: 10,
|
||||
marginLeft: '25%',
|
||||
marginTop: '2%'
|
||||
},
|
||||
typography: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 40,
|
||||
marginBottom: 40
|
||||
},
|
||||
grid: {
|
||||
paddingTop: '30',
|
||||
marginTop: 30
|
||||
}
|
||||
})
|
||||
|
||||
class YourDescendents extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.defaultValuesSet = false
|
||||
|
||||
this.state = {
|
||||
id: ''
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
if (this.defaultValuesSet === false) {
|
||||
let userData = localStorage.getItem('loggedInUser')
|
||||
|
||||
if (userData === 'undefined') { return }
|
||||
|
||||
let user = JSON.parse(userData)
|
||||
this.defaultValuesSet = true
|
||||
|
||||
/* Now we are ready to set the initial state. */
|
||||
this.setState({
|
||||
id: user.id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
|
||||
return (
|
||||
<Paper className={classes.root}>
|
||||
<Typography className={classes.typography} variant='headline' gutterBottom>
|
||||
Your Descendents
|
||||
</Typography>
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
These are your decendents within the project. Your children referred you as the one who brought them to the project, while
|
||||
your grandchildren referred your children and so on. In order to be able to see your descendents, the users who you referred
|
||||
must first point to you as your referrer.
|
||||
</Typography>
|
||||
|
||||
<DescendentsTree userId={this.state.id} />
|
||||
<Grid container className={classes.grid} justify='center' spacing={24} />
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withStyles(styles)
|
||||
)(YourDescendents) // This technique binds more than one query to a single component.
|
||||
@@ -1,145 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {graphql, compose} from 'react-apollo'
|
||||
import {updateReferrerMutation} from '../queries/queries'
|
||||
|
||||
// components
|
||||
|
||||
import UserSearch from './UserSearch'
|
||||
import UserProfile from './UserProfile'
|
||||
|
||||
// Material-ui
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '50%',
|
||||
flexGrow: 1,
|
||||
padding: 10,
|
||||
marginLeft: '25%',
|
||||
marginTop: '2%'
|
||||
},
|
||||
typography: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 40,
|
||||
marginBottom: 40
|
||||
},
|
||||
button: {
|
||||
margin: theme.spacing.unit,
|
||||
marginTop: theme.spacing.unit * 3
|
||||
},
|
||||
inputField: {
|
||||
width: '80%',
|
||||
marginLeft: '10%',
|
||||
marginTop: 25
|
||||
}
|
||||
})
|
||||
|
||||
class YourReferrer extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.defaultValuesSet = false
|
||||
|
||||
this.state = {
|
||||
id: '',
|
||||
referrerId: '',
|
||||
firstNameError: false,
|
||||
middleNameError: false,
|
||||
lastNameError: false,
|
||||
aliasError: false
|
||||
}
|
||||
}
|
||||
|
||||
userSelected (referrerUser) {
|
||||
this.setState({referrerId: referrerUser.id})
|
||||
|
||||
this.props.updateReferrerMutation({
|
||||
variables: {
|
||||
referrerId: referrerUser.id
|
||||
}
|
||||
})
|
||||
|
||||
/* Before we are done, we need to update the state of the local storage. */
|
||||
|
||||
let user = JSON.parse(localStorage.getItem('loggedInUser'))
|
||||
|
||||
user.referrerId = referrerUser.id
|
||||
|
||||
localStorage.setItem('loggedInUser', JSON.stringify(user))
|
||||
}
|
||||
|
||||
renderMode () {
|
||||
const { classes } = this.props
|
||||
|
||||
if (this.state.referrerId !== null) {
|
||||
return (
|
||||
<div>
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
This is the user who introduced you to the project.
|
||||
</Typography>
|
||||
|
||||
<UserProfile userId={this.state.referrerId} />
|
||||
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
This information can not be changed.
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<Typography className={classes.typography} variant='body1' gutterBottom align='left'>
|
||||
We know that a group often becomes more intelligent when the number of people in the group increases.
|
||||
To incentivize members of the community to invite more people to join we have developed this referral
|
||||
program in which you can specify who referred you to the project, and see the members who pointed at
|
||||
you as their referrer. Later this information will be available at your user profile and add to your
|
||||
overall reputation within the project.
|
||||
</Typography>
|
||||
|
||||
<UserSearch selectButton onSelect={this.userSelected.bind(this)} selectText="After that press the 'Select' button on the desired user to set it as your referrer. Bear in mind that this action can not be undone." />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
if (this.defaultValuesSet === false) {
|
||||
let userData = localStorage.getItem('loggedInUser')
|
||||
|
||||
if (userData === 'undefined') { return }
|
||||
|
||||
let user = JSON.parse(userData)
|
||||
this.defaultValuesSet = true
|
||||
|
||||
/* Now we are ready to set the initial state. */
|
||||
|
||||
this.setState({
|
||||
id: user.id,
|
||||
referrerId: user.referrerId
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<Paper className={classes.root}>
|
||||
<Typography className={classes.typography} variant='headline' gutterBottom>
|
||||
Your Referrer
|
||||
</Typography>
|
||||
|
||||
{this.renderMode()}
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(updateReferrerMutation, {name: 'updateReferrerMutation'}),
|
||||
withStyles(styles)
|
||||
)(YourReferrer) // This technique binds more than one query to a single component.
|
||||
|
Before Width: | Height: | Size: 801 B |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 472 B |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,86 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Route, BrowserRouter, Switch } from 'react-router-dom'
|
||||
import { hot } from 'react-hot-loader'
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
// Components
|
||||
import NavBar from './components/NavBar'
|
||||
import Home from './components/Home'
|
||||
import User from './components/User'
|
||||
import Browse from './components/Browse'
|
||||
import Search from './components/Search'
|
||||
import About from './components/About'
|
||||
import Contact from './components/Contact'
|
||||
|
||||
import { getItem } from './utils/local-storage'
|
||||
import {
|
||||
globalStyles
|
||||
} from './theme'
|
||||
|
||||
class App extends Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
user: null
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidMount () {
|
||||
let user = await getItem('user')
|
||||
|
||||
if (user !== null && user !== undefined && user !== 'undefined') {
|
||||
user = JSON.parse(user)
|
||||
this.setState({ user: user })
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { match } = this.props
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div className='App'>
|
||||
<NavBar match={match} user={this.state.user} />
|
||||
<Switch>
|
||||
<Route exact path={`${match.path}`} component={Home} />
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/users`}
|
||||
render={props => <Home {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/user`}
|
||||
render={props => <User {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/browse`}
|
||||
render={props => <Browse {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/search`}
|
||||
render={props => <Search {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/about`}
|
||||
render={props => <About {...props} auth={this.props.auth} />}
|
||||
/>
|
||||
<Route path='/browse/:slug' component={Browse} />
|
||||
</Switch>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
App.propTypes = {
|
||||
auth: PropTypes.object
|
||||
}
|
||||
|
||||
const StyledApp = withStyles(globalStyles)(App)
|
||||
export default hot(module)(StyledApp)
|
||||
|
Before Width: | Height: | Size: 758 B |
@@ -1,57 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<style>
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<link href="https://fonts.googleapis.com/css?family=Saira+Condensed:300,600|Saira:300,600&subset=latin-ext,vietnamese" rel="stylesheet">
|
||||
<!-- font awesome -->
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
|
||||
<!-- default font of Material-UI -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
|
||||
<!-- In order to use the font Icon component of Material-UI -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<title>Advanced Algos - Users Module</title>
|
||||
<!-- Material-UI is developed mobile first -->
|
||||
<meta
|
||||
name="viewport"
|
||||
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const getUsersQuery = gql`
|
||||
{
|
||||
users_Users {
|
||||
id
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
bio
|
||||
role {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
const getUserProfileQuery = gql`
|
||||
query($id: ID){
|
||||
users_User (id: $id){
|
||||
id
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
bio
|
||||
avatarHandle
|
||||
role {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
const getUserByAuthIdQuery = gql`
|
||||
query($authId: String){
|
||||
users_UserByAuthId (authId: $authId){
|
||||
id
|
||||
referrerId
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
bio
|
||||
email
|
||||
emailVerified
|
||||
isDeveloper
|
||||
isDataAnalyst
|
||||
isTrader
|
||||
avatarHandle
|
||||
avatarChangeDate
|
||||
role {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
const getUsersBySearchFields = gql`
|
||||
query(
|
||||
$alias: String,
|
||||
$firstName: String,
|
||||
$middleName: String,
|
||||
$lastName: String
|
||||
){
|
||||
users_UsersSearch (alias: $alias, firstName: $firstName, middleName: $middleName, lastName: $lastName){
|
||||
id
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
}
|
||||
}
|
||||
`
|
||||
const getDescendentsQuery = gql`
|
||||
query(
|
||||
$id: String
|
||||
){
|
||||
users_Descendents (id: $id){
|
||||
id
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
referrerId
|
||||
descendents {
|
||||
id
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
referrerId
|
||||
descendents {
|
||||
id
|
||||
alias
|
||||
firstName
|
||||
middleName
|
||||
lastName
|
||||
referrerId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
const getRolesQuery = gql`
|
||||
{
|
||||
users_Roles {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`
|
||||
const updateUserMutation = gql`
|
||||
mutation(
|
||||
$firstName:String,
|
||||
$middleName:String,
|
||||
$lastName:String,
|
||||
$bio:String,
|
||||
$isDeveloper:Int,
|
||||
$isTrader:Int,
|
||||
$isDataAnalyst:Int,
|
||||
$roleId:String!
|
||||
)
|
||||
{
|
||||
users_UpdateUser (
|
||||
firstName:$firstName,
|
||||
middleName: $middleName,
|
||||
lastName: $lastName,
|
||||
bio: $bio,
|
||||
isDeveloper: $isDeveloper,
|
||||
isTrader: $isTrader,
|
||||
isDataAnalyst: $isDataAnalyst,
|
||||
roleId: $roleId
|
||||
)
|
||||
{
|
||||
id
|
||||
alias
|
||||
}
|
||||
}
|
||||
`
|
||||
const updateReferrerMutation = gql`
|
||||
mutation(
|
||||
$referrerId:String!
|
||||
)
|
||||
{
|
||||
users_UpdateUserReferrer (
|
||||
referrerId:$referrerId
|
||||
)
|
||||
{
|
||||
id
|
||||
referrerId
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export {
|
||||
getUsersQuery,
|
||||
getUserByAuthIdQuery,
|
||||
getRolesQuery,
|
||||
getUserProfileQuery,
|
||||
getUsersBySearchFields,
|
||||
getDescendentsQuery,
|
||||
updateUserMutation,
|
||||
updateReferrerMutation
|
||||
}
|
||||
@@ -108,7 +108,6 @@ class ProfileSheet extends Component {
|
||||
e.preventDefault()
|
||||
this.props.updateUserMutation({
|
||||
variables: {
|
||||
id: this.state.id,
|
||||
firstName: this.state.firstName,
|
||||
middleName: this.state.middleName,
|
||||
lastName: this.state.lastName,
|
||||
|
||||
@@ -60,7 +60,6 @@ class YourReferrer extends Component {
|
||||
|
||||
this.props.updateReferrerMutation({
|
||||
variables: {
|
||||
id: this.state.id,
|
||||
referrerId: referrerUser.id
|
||||
}
|
||||
})
|
||||
|
||||
@@ -112,7 +112,6 @@ const getRolesQuery = gql`
|
||||
`
|
||||
const updateUserMutation = gql`
|
||||
mutation(
|
||||
$id: ID!,
|
||||
$firstName:String,
|
||||
$middleName:String,
|
||||
$lastName:String,
|
||||
@@ -124,7 +123,6 @@ mutation(
|
||||
)
|
||||
{
|
||||
users_UpdateUser (
|
||||
id: $id,
|
||||
firstName:$firstName,
|
||||
middleName: $middleName,
|
||||
lastName: $lastName,
|
||||
@@ -142,12 +140,10 @@ mutation(
|
||||
`
|
||||
const updateReferrerMutation = gql`
|
||||
mutation(
|
||||
$id: ID!,
|
||||
$referrerId:String!
|
||||
)
|
||||
{
|
||||
users_UpdateUserReferrer (
|
||||
id: $id,
|
||||
referrerId:$referrerId
|
||||
)
|
||||
{
|
||||
@@ -156,24 +152,6 @@ mutation(
|
||||
}
|
||||
}
|
||||
`
|
||||
const updateUserImagesMutation = gql`
|
||||
mutation(
|
||||
$id: ID!,
|
||||
$avatarHandle:String,
|
||||
$avatarChangeDate:String
|
||||
)
|
||||
{
|
||||
users_UpdateUserImages (
|
||||
id: $id,
|
||||
avatarHandle:$avatarHandle,
|
||||
avatarChangeDate: $avatarChangeDate
|
||||
)
|
||||
{
|
||||
id
|
||||
alias
|
||||
}
|
||||
}
|
||||
`
|
||||
export {
|
||||
getUsersQuery,
|
||||
getUserByAuthIdQuery,
|
||||
@@ -182,6 +160,5 @@ export {
|
||||
getUsersBySearchFields,
|
||||
getDescendentsQuery,
|
||||
updateUserMutation,
|
||||
updateReferrerMutation,
|
||||
updateUserImagesMutation
|
||||
updateReferrerMutation
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { createMuiTheme } from '@material-ui/core/styles'
|
||||
|
||||
export const theme = createMuiTheme({
|
||||
palette: {
|
||||
primary: { main: '#303036' }, // DARK.
|
||||
secondary: { main: '#CC5835' } // RUSTED_RED.
|
||||
},
|
||||
typography: {
|
||||
fontFamily: '"Saira","Saira Condenses", sans-serif'
|
||||
},
|
||||
overrides: {
|
||||
Paper: {
|
||||
root: {
|
||||
backgroundColor: '#ffffff'
|
||||
},
|
||||
elevation: 0,
|
||||
square: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const globalStyles = theme => ({
|
||||
'@global': {
|
||||
body: {
|
||||
backgroundColor: theme.palette.common.white
|
||||
}
|
||||
},
|
||||
appBar: {
|
||||
position: 'relative'
|
||||
},
|
||||
toolbarTitle: {
|
||||
flex: 1
|
||||
},
|
||||
layout: {
|
||||
width: 'auto',
|
||||
marginLeft: theme.spacing.unit * 3,
|
||||
marginRight: theme.spacing.unit * 3,
|
||||
[theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: {
|
||||
width: 900,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto'
|
||||
}
|
||||
},
|
||||
heroContent: {
|
||||
maxWidth: 600,
|
||||
margin: '0 auto',
|
||||
padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
|
||||
},
|
||||
cardHeader: {
|
||||
backgroundColor: theme.palette.grey[200]
|
||||
},
|
||||
cardPricing: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'baseline',
|
||||
marginBottom: theme.spacing.unit * 2
|
||||
},
|
||||
cardActions: {
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
paddingBottom: theme.spacing.unit * 2
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default theme
|
||||
@@ -30,10 +30,15 @@ app.get('/graphql', graphqlHTTP({
|
||||
graphiql: true
|
||||
}))
|
||||
|
||||
app.post('/graphql', graphqlHTTP({
|
||||
schema,
|
||||
graphiql: false,
|
||||
context: req => ({ ...req })
|
||||
app.post('/graphql', graphqlHTTP(req => {
|
||||
return {
|
||||
schema,
|
||||
graphiql: false,
|
||||
context: {
|
||||
user: req.user,
|
||||
userId: req.headers.userid
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
app.post('/graphql', checkJwt, (err, req, res, next) => {
|
||||
|
||||
@@ -204,6 +204,56 @@
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
},
|
||||
"color": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
|
||||
"integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
|
||||
"requires": {
|
||||
"color-convert": "1.9.3",
|
||||
"color-string": "1.5.3"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"color-string": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
|
||||
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3",
|
||||
"simple-swizzle": "0.2.2"
|
||||
}
|
||||
},
|
||||
"colornames": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz",
|
||||
"integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y="
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz",
|
||||
"integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ=="
|
||||
},
|
||||
"colorspace": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz",
|
||||
"integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==",
|
||||
"requires": {
|
||||
"color": "3.0.0",
|
||||
"text-hex": "1.0.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
@@ -277,6 +327,16 @@
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"diagnostics": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz",
|
||||
"integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==",
|
||||
"requires": {
|
||||
"colorspace": "1.1.1",
|
||||
"enabled": "1.0.2",
|
||||
"kuler": "1.0.1"
|
||||
}
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
@@ -300,11 +360,24 @@
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"enabled": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
|
||||
"integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
|
||||
"requires": {
|
||||
"env-variable": "0.0.5"
|
||||
}
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"env-variable": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz",
|
||||
"integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA=="
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -406,6 +479,16 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"fast-safe-stringify": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz",
|
||||
"integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg=="
|
||||
},
|
||||
"fecha": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
|
||||
"integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
|
||||
@@ -511,11 +594,26 @@
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
|
||||
"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
@@ -618,6 +716,14 @@
|
||||
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.2.1.tgz",
|
||||
"integrity": "sha512-xpDFy8OxkFM+vK6pXy6JmH92ibeEFUuDWzas5M9L7MzVmHW3jzwAHxodCPV/BYkf4A31bVDLyonrMfp9RXb/oA=="
|
||||
},
|
||||
"kuler": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz",
|
||||
"integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==",
|
||||
"requires": {
|
||||
"colornames": "1.1.1"
|
||||
}
|
||||
},
|
||||
"limiter": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.3.tgz",
|
||||
@@ -678,6 +784,25 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
|
||||
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
|
||||
},
|
||||
"logform": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz",
|
||||
"integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==",
|
||||
"requires": {
|
||||
"colors": "1.3.2",
|
||||
"fast-safe-stringify": "2.0.6",
|
||||
"fecha": "2.3.3",
|
||||
"ms": "2.1.1",
|
||||
"triple-beam": "1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz",
|
||||
@@ -3558,6 +3683,11 @@
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"one-time": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
|
||||
"integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
|
||||
@@ -3573,6 +3703,11 @@
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
|
||||
@@ -3641,6 +3776,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "1.0.0",
|
||||
"process-nextick-args": "2.0.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"string_decoder": "1.1.1",
|
||||
"util-deprecate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"regexp-clone": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz",
|
||||
@@ -3756,6 +3905,14 @@
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
||||
},
|
||||
"simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
|
||||
"requires": {
|
||||
"is-arrayish": "0.3.2"
|
||||
}
|
||||
},
|
||||
"sliced": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
|
||||
@@ -3777,11 +3934,29 @@
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"text-hex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
@@ -3791,6 +3966,11 @@
|
||||
"punycode": "1.4.1"
|
||||
}
|
||||
},
|
||||
"triple-beam": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
@@ -3819,6 +3999,11 @@
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
@@ -3849,6 +4034,31 @@
|
||||
"resolved": "https://registry.npmjs.org/very-fast-args/-/very-fast-args-1.1.0.tgz",
|
||||
"integrity": "sha1-4W0dH6+KbllqJGQh/ZCneWPQs5Y="
|
||||
},
|
||||
"winston": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz",
|
||||
"integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==",
|
||||
"requires": {
|
||||
"async": "2.6.1",
|
||||
"diagnostics": "1.1.1",
|
||||
"is-stream": "1.1.0",
|
||||
"logform": "1.10.0",
|
||||
"one-time": "0.0.4",
|
||||
"readable-stream": "2.3.6",
|
||||
"stack-trace": "0.0.10",
|
||||
"triple-beam": "1.3.0",
|
||||
"winston-transport": "4.2.0"
|
||||
}
|
||||
},
|
||||
"winston-transport": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.2.0.tgz",
|
||||
"integrity": "sha512-0R1bvFqxSlK/ZKTH86nymOuKv/cT1PQBMuDdA7k7f0S9fM44dNH6bXnuxwXPrN8lefJgtZq08BKdyZ0DZIy/rg==",
|
||||
"requires": {
|
||||
"readable-stream": "2.3.6",
|
||||
"triple-beam": "1.3.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"jwks-rsa": "^1.3.0",
|
||||
"lodash": "^4.17.10",
|
||||
"mongoose": "^5.2.12",
|
||||
"npm": "^6.4.1"
|
||||
"npm": "^6.4.1",
|
||||
"winston": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ const MODULE_NAME = 'schema'
|
||||
const graphql = require('graphql')
|
||||
const _ = require('lodash')
|
||||
const User = require('../models/user')
|
||||
|
||||
const logger = require('../utils/logger')
|
||||
const tokenDecoder = require('../auth/token-decoder')
|
||||
|
||||
const {
|
||||
@@ -104,22 +104,22 @@ const RootQuery = new GraphQLObjectType({
|
||||
resolve (parent, args) {
|
||||
// Code to get data from data source.
|
||||
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Entering function.') }
|
||||
|
||||
/* In order to be able to wait for asyc calls to the database, we need to return a promise to GraphQL. */
|
||||
|
||||
const promiseToGraphQL = new Promise((resolve, reject) => {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> Entering function.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> args.authId = ' + args.authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> args.authId = ' + args.authId) }
|
||||
|
||||
findUserByAuthId(args.authId, onUserFound)
|
||||
|
||||
function onUserFound (err, responseToGraphQL) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserFound -> Entering function.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserFound -> responseToGraphQL = ' + JSON.stringify(responseToGraphQL)) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserFound -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserFound -> responseToGraphQL = ' + JSON.stringify(responseToGraphQL)) }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserFound -> err.message = ' + err.message) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> RootQuery -> userByAuthId -> resolve -> Promise -> onUserFound -> err.message = ' + err.message) }
|
||||
reject(responseToGraphQL)
|
||||
} else {
|
||||
resolve(responseToGraphQL)
|
||||
@@ -154,7 +154,7 @@ const RootQuery = new GraphQLObjectType({
|
||||
type: new GraphQLList(UserType),
|
||||
args: {alias: {type: GraphQLString}, firstName: {type: GraphQLString}, middleName: {type: GraphQLString}, lastName: {type: GraphQLString}},
|
||||
resolve (parent, args) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> usersSearch -> resolve -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> usersSearch -> resolve -> Entering function.') }
|
||||
|
||||
let mongoQuery = { $or: [] }
|
||||
|
||||
@@ -172,7 +172,7 @@ const RootQuery = new GraphQLObjectType({
|
||||
type: new GraphQLList(DescendentType),
|
||||
args: {id: {type: GraphQLString}},
|
||||
resolve (parent, args) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> RootQuery -> descendents -> resolve -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> RootQuery -> descendents -> resolve -> Entering function.') }
|
||||
|
||||
return User.find({referrerId: args.id})
|
||||
}
|
||||
@@ -191,20 +191,20 @@ const Mutation = new GraphQLObjectType({
|
||||
idToken: {type: new GraphQLNonNull(GraphQLString)}
|
||||
},
|
||||
resolve (parent, args) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Entering function.') }
|
||||
|
||||
/* In order to be able to wait for asyc calls to the database, and authorization authority, we need to return a promise to GraphQL. */
|
||||
|
||||
const promiseToGraphQL = new Promise((resolve, reject) => {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> Entering function.') }
|
||||
authenticate(args.idToken, onAuthenticated)
|
||||
|
||||
function onAuthenticated (err, responseToGraphQL) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> Entering function.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> responseToGraphQL = ' + JSON.stringify(responseToGraphQL)) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> responseToGraphQL = ' + JSON.stringify(responseToGraphQL)) }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> err.message = ' + err.message) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> Mutation -> authenticate -> resolve -> Promise -> onAuthenticated -> err.message = ' + err.message) }
|
||||
reject(responseToGraphQL)
|
||||
} else {
|
||||
resolve(responseToGraphQL)
|
||||
@@ -289,12 +289,12 @@ const Mutation = new GraphQLObjectType({
|
||||
|
||||
function findUserByAuthId (authId, callBackFunction) {
|
||||
try {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> Entering function.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> authId = ' + authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> authId = ' + authId) }
|
||||
|
||||
if (authId === null || authId === undefined) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> User requested not specified.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> args.authId = ' + authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> User requested not specified.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> args.authId = ' + authId) }
|
||||
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: 'Bad Request' })
|
||||
return
|
||||
@@ -304,13 +304,13 @@ function findUserByAuthId (authId, callBackFunction) {
|
||||
|
||||
function onUserReceived (err, user) {
|
||||
if (err) {
|
||||
if (ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> Database Error.') }
|
||||
if (ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> err = ' + err) }
|
||||
if (ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> Database Error.') }
|
||||
if (ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> err = ' + err) }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
} else {
|
||||
if (user === null) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> User not found at Database.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> args.authId = ' + authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> User not found at Database.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> args.authId = ' + authId) }
|
||||
|
||||
let customResponse = {
|
||||
result: global.CUSTOM_OK_RESPONSE.result,
|
||||
@@ -322,15 +322,15 @@ function findUserByAuthId (authId, callBackFunction) {
|
||||
}
|
||||
|
||||
if (user.authId === authId && user.authId !== undefined) {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> User found at Database.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> args.authId = ' + authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> User found at Database.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> args.authId = ' + authId) }
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, user)
|
||||
return
|
||||
} else {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> User found at Database is not the user requested.') }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> args.authId = ' + authId) }
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> user.authId = ' + user.authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> User found at Database is not the user requested.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> args.authId = ' + authId) }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> findUserByAuthId -> onUserReceived -> user.authId = ' + user.authId) }
|
||||
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
return
|
||||
@@ -338,14 +338,14 @@ function findUserByAuthId (authId, callBackFunction) {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> findUserByAuthId -> err.message = ' + err.message) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> findUserByAuthId -> err.message = ' + err.message) }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
}
|
||||
}
|
||||
|
||||
function authenticate (encodedToken, callBackFunction) {
|
||||
try {
|
||||
if (INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> Entering function.') }
|
||||
|
||||
let authId = ''
|
||||
let alias = ''
|
||||
@@ -355,10 +355,10 @@ function authenticate (encodedToken, callBackFunction) {
|
||||
tokenDecoder(encodedToken, onValidated)
|
||||
|
||||
function onValidated (err, decodedToken) {
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> Entering function.') }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> Entering function.') }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> err.message = ' + err.message) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> err.message = ' + err.message) }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
return
|
||||
}
|
||||
@@ -378,18 +378,18 @@ function authenticate (encodedToken, callBackFunction) {
|
||||
findUserByAuthId(authId, onUserFound)
|
||||
|
||||
function onUserFound (err, user) {
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> Entering function.') }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> Entering function.') }
|
||||
|
||||
if (err.result === global.DEFAULT_FAIL_RESPONSE.result) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> err.message = ' + err.message) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> err.message = ' + err.message) }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> User already exists at database') }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> User already exists at database') }
|
||||
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> Existing User: ' + JSON.stringify(user)) }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> Existing User: ' + JSON.stringify(user)) }
|
||||
|
||||
/*
|
||||
|
||||
@@ -408,7 +408,7 @@ function authenticate (encodedToken, callBackFunction) {
|
||||
err.result === global.CUSTOM_OK_RESPONSE.result &&
|
||||
err.message === 'User Not Found'
|
||||
) {
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> User does not exist at database') }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> User does not exist at database') }
|
||||
|
||||
/*
|
||||
|
||||
@@ -427,8 +427,8 @@ function authenticate (encodedToken, callBackFunction) {
|
||||
socialAccountProvider !== 'github' &&
|
||||
socialAccountProvider !== 'auth0'
|
||||
) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> Social Account Provider not Supoorted. ') }
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> socialAccountProvider = ' + socialAccountProvider) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> Social Account Provider not Supoorted. ') }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> socialAccountProvider = ' + socialAccountProvider) }
|
||||
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
return
|
||||
@@ -446,20 +446,20 @@ function authenticate (encodedToken, callBackFunction) {
|
||||
roleId: '1'
|
||||
})
|
||||
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> ' + alias + ' being added to the database') }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> ' + alias + ' being added to the database') }
|
||||
|
||||
newUser.save(onSaved)
|
||||
|
||||
function onSaved (err, savedUser) {
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> onSaved -> Entering function.') }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> onSaved -> Entering function.') }
|
||||
|
||||
if (err) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> onSaved -> err = ' + err) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> onSaved -> err = ' + err) }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
return
|
||||
}
|
||||
|
||||
if (global.INFO_LOG === true) { console.log('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> onSaved -> Saved User: ' + JSON.stringify(savedUser)) }
|
||||
if (global.INFO_LOG === true) { logger.info('[INFO] ' + MODULE_NAME + ' -> authenticate -> onValidated -> onUserFound -> onSaved -> Saved User: ' + JSON.stringify(savedUser)) }
|
||||
|
||||
/*
|
||||
|
||||
@@ -476,7 +476,7 @@ function authenticate (encodedToken, callBackFunction) {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (global.ERROR_LOG === true) { console.log('[ERROR] ' + MODULE_NAME + ' -> authenticate -> err.message = ' + err.message) }
|
||||
if (global.ERROR_LOG === true) { logger.error('[ERROR] ' + MODULE_NAME + ' -> authenticate -> err.message = ' + err.message) }
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE, { error: err })
|
||||
}
|
||||
}
|
||||
|
||||