diff --git a/client/package-lock.json b/client/package-lock.json index 0ffb90ac3..142f5ecb1 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,6 +1,6 @@ { "name": "@advancedalgos/teams-client", - "version": "0.0.22", + "version": "0.0.24", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -12040,14 +12040,14 @@ } }, "react": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/react/-/react-16.5.2.tgz", - "integrity": "sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw==", + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.6.1.tgz", + "integrity": "sha512-OtawJThYlvRgm9BXK+xTL7BIlDx8vv21j+fbQDjRRUyok6y7NyjlweGorielTahLZHYIdKUoK2Dp9ByVWuMqxw==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "schedule": "^0.5.0" + "scheduler": "^0.11.0" } }, "react-apollo": { @@ -12089,14 +12089,14 @@ } }, "react-dom": { - "version": "16.5.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.5.2.tgz", - "integrity": "sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA==", + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.6.1.tgz", + "integrity": "sha512-zm+wBuEMGm009Wt1uE4Zw5KcXOW7qC4E/xW/fpJsCsbOco4U/R84u+DzzO/S4SYSdNBcqcaulcp4w3FXl8pImw==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "schedule": "^0.5.0" + "scheduler": "^0.11.0" } }, "react-dropzone": { @@ -13088,11 +13088,12 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, - "schedule": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/schedule/-/schedule-0.5.0.tgz", - "integrity": "sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw==", + "scheduler": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.11.0.tgz", + "integrity": "sha512-MAYbBfmiEHxF0W+c4CxMpEqMYK+rYF584VP/qMKSiHM6lTkBKKYOJaDiSILpJHla6hBOsVd6GucPL46o2Uq3sg==", "requires": { + "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, diff --git a/client/package.json b/client/package.json index 258ac437d..1f63bd8be 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "@advancedalgos/teams-client", - "version": "0.0.24", + "version": "0.0.25", "description": "Advanced Algos Team client-side web app", "main": "src/index.js", "scripts": { @@ -90,15 +90,15 @@ "minilog": "^3.1.0", "prop-types": "^15.6.2", "query-string": "^6.2.0", - "react": "^16.5.2", + "react": "^16.6.1", "react-apollo": "^2.2.4", - "react-dom": "^16.5.2", + "react-dom": "^16.6.1", "react-router-dom": "^4.3.1", "recompose": "^0.30.0", "subscriptions-transport-ws": "^0.9.15" }, "peerDependencies": { - "@material-ui/core": "^3.2.0", + "@material-ui/core": "^3.2.2", "@material-ui/icons": "^3.0.1" }, "standard": { diff --git a/client/src/index.js b/client/src/index.js index 9ff881c15..c5381d25c 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -11,7 +11,6 @@ import { FinancialBeings, Settings, Teams, - TeamBar, globalStyles } from './views' @@ -35,16 +34,8 @@ class App extends Component { } render () { - const { match } = this.props - let loggedIn - if (this.state.user !== null) { - loggedIn = () - } else { - loggedIn = '' - } return (
- {loggedIn} +
+ {title} + {text} +
+
+ ) + } + if (size === 'medium') { + return ( +
+
+ {title} + {text} +
+
+ ) + } + return ( +
+ ) + } +} + +TopBar.propTypes = { + classes: PropTypes.object.isRequired, + size: PropTypes.string, + title: PropTypes.string, + text: PropTypes.string +} + +export default withStyles(styles)(TopBar) diff --git a/client/src/views/common/components/TopBarStyles.js b/client/src/views/common/components/TopBarStyles.js new file mode 100644 index 000000000..816d907e1 --- /dev/null +++ b/client/src/views/common/components/TopBarStyles.js @@ -0,0 +1,39 @@ +const styles = () => ({ + rootBig: { + backgroundImage: 'url(https://aacorporatesitedevelop.azurewebsites.net/img/photos/connect.jpg)', + width: '100%', + height: '100vh' + }, + rootMedium: { + backgroundImage: 'url(https://aacorporatesitedevelop.azurewebsites.net/img/photos/connect.jpg)', + width: '100%', + height: '50vh' + }, + rootSmall: { + backgroundImage: 'url(https://aacorporatesitedevelop.azurewebsites.net/img/photos/connect.jpg)', + width: '100%', + height: '220px' + }, + captions: { + position: 'relative', + top: '50%', + transform: 'translateY(-50%)' + }, + title: { + fontFamily: 'Saira', + color: 'white', + fontSize: '64px', + lineHeight: '78px', + fontWeight: 100 + }, + text: { + fontFamily: 'Saira', + color: 'white', + fontSize: '20px', + lineHeight: '30px', + fontWeight: 600, + padding: '20px 0 0.5em 0' + } +}) + +export default styles diff --git a/client/src/views/common/index.js b/client/src/views/common/index.js index 5c526115f..113554cae 100644 --- a/client/src/views/common/index.js +++ b/client/src/views/common/index.js @@ -1,3 +1,4 @@ import TeamBar from './components/TeamBar' +import TopBar from './components/TopBar' -export { TeamBar } +export { TeamBar, TopBar } diff --git a/client/src/views/financial-beings/index.js b/client/src/views/financial-beings/index.js index fba9ce00d..e23c46ce4 100644 --- a/client/src/views/financial-beings/index.js +++ b/client/src/views/financial-beings/index.js @@ -1,9 +1,9 @@ import React from 'react' import PropTypes from 'prop-types' -import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' +import { TopBar } from '../common' import ManageFBList from './components/ManageFBList' const styles = theme => ({ @@ -14,9 +14,7 @@ const styles = theme => ({ const FinancialBeings = ({ classes }) => (
- - Financial Beings - +
) diff --git a/client/src/views/manage-teams/components/CreateTeamForm.js b/client/src/views/manage-teams/components/CreateTeamForm.js new file mode 100644 index 000000000..29cdd04e0 --- /dev/null +++ b/client/src/views/manage-teams/components/CreateTeamForm.js @@ -0,0 +1,217 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { Mutation } from 'react-apollo' +import { withStyles } from '@material-ui/core/styles' + +import Button from '@material-ui/core/Button' +import TextField from '@material-ui/core/TextField' +import FormControl from '@material-ui/core/FormControl' +import FormHelperText from '@material-ui/core/FormHelperText' +import Typography from '@material-ui/core/Typography' +import { isEmpty } from '../../../utils/js-helpers' + +import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation' +import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' + +import log from '../../../utils/log' + +const styles = theme => ({ + formContainer: { + width: '100%', + margin: '3em 0 1em' + }, + dialogStyle: { + padding: '3em' + }, + textField: { + marginBottom: 10 + }, + submitButton: { + margin: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 6}px` + } +}) + +export class CreateTeamForm extends Component { + constructor (props) { + super(props) + + this.handleClickOpen = this.handleClickOpen.bind(this) + this.handleClose = this.handleClose.bind(this) + this.handleChange = this.handleChange.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + this.validate = this.validate.bind(this) + this.slugify = this.slugify.bind(this) + + this.state = { + open: false, + name: '', + botName: '', + nameError: '', + botNameError: '' + } + } + + render () { + const { classes } = this.props + return ( + + {(createTeam, { loading, error, data }) => { + let errors + let loader = null + if (loading) { + loader = ( + Submitting team... + ) + } + if (error) { + errors = error.graphQLErrors.map(({ message }, i) => { + // const displayMessage = checkGraphQLError(message) + return ( + + {message} + + ) + }) + } + return ( + + Create a name for your team + + {this.state.nameError !== '' && ( + {this.state.nameError} + )} +
+ Create a name for your teams bot. +
+ + {this.state.botNameError !== '' && ( + {this.state.botNameError} + )} + {error && {errors}} + {loader} + +
+ ) + }} +
+ ) + } + + handleClickOpen () { + this.setState({ open: true }) + } + + handleClose () { + this.setState({ open: false }) + } + + handleChange (e) { + let id = e.target.id + let value = e.target.value + let error = this.validate({ id, value }) + switch (id) { + case 'name': + if (!isEmpty(error)) this.setState({ nameError: error }) + this.setState({ name: value }) + break + case 'botName': + if (!isEmpty(error)) this.setState({ botNameError: error }) + this.setState({ botName: value }) + break + default: + } + } + + async handleSubmit (e, createTeam, name, botName) { + e.preventDefault() + log.debug('createTeam submit: ', name, botName) + const slug = this.slugify(name) + const botSlug = this.slugify(botName) + await createTeam({ variables: { name, slug, botName, botSlug } }) + window.canvasApp.eventHandler.raiseEvent('User Profile Changed') + this.setState({ name: '', open: false }) + } + + validate (data) { + const errors = {} + switch (data.id) { + case 'name': + if (data.value === '') { + this.setState({ nameError: 'Please enter a team name' }) + } else { + this.setState({ nameError: '' }) + } + break + case 'botName': + if (data.value === '') { + this.setState({ botNameError: 'Please enter a bot name' }) + } else { + this.setState({ botNameError: '' }) + } + break + default: + } + return errors + } + + slugify (string) { + const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;' + const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------' + const p = new RegExp(a.split('').join('|'), 'g') + + return string + .toString() + .toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters + .replace(/&/g, '-and-') // Replace & with 'and' + .replace(/[^\w-]+/g, '') // Remove all non-word characters + .replace(/--+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, '') // Trim - from end of text + } +} + +CreateTeamForm.propTypes = { + classes: PropTypes.object.isRequired +} + +export default withStyles(styles)(CreateTeamForm) diff --git a/client/src/views/manage-teams/components/ManageTeamsList.js b/client/src/views/manage-teams/components/ManageTeamsList.js index 59577baa6..74bc3fb3e 100644 --- a/client/src/views/manage-teams/components/ManageTeamsList.js +++ b/client/src/views/manage-teams/components/ManageTeamsList.js @@ -3,17 +3,23 @@ import PropTypes from 'prop-types' import { Query } from 'react-apollo' import Grid from '@material-ui/core/Grid' +import Paper from '@material-ui/core/Paper' +import Typography from '@material-ui/core/Typography' import { MessageCard } from '@advancedalgos/web-components' import { withStyles } from '@material-ui/core/styles' import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery' import ManageTeamsItem from './ManageTeamsItem' -import CreateTeamDialog from './CreateTeamDialog' +import CreateTeamForm from './CreateTeamForm' import log from '../../../utils/log' const styles = theme => ({ + container: { + padding: `${theme.spacing.unit * 8}px ${theme.spacing.unit * 6}px`, + margin: `${theme.spacing.unit * 1}px 0` + }, heroContent: { maxWidth: 600, margin: '0 auto', @@ -63,7 +69,7 @@ export const ManageTeamsList = ({ classes, user = null, ...props }) => ( if (data.teams_TeamsByOwner.length > 0) { return ( - + {!loading && data.teams_TeamsByOwner.map(team => ( ( ) } else { return ( - - - - - + + + + + You don’t have any teams. Create one! + + + To begin developing on the Advanced Algos platform, as well as participate in Algobot competitions, + you'll need to create a team. A default trading algobot will be cloned and added to your team so + that you can begin experimenting right away.. + + + - + ) } } else { return ( - + - - {errors !== null && } + {errors === null && + + Loading... + + } + {errors !== null && + + {errors} + + } ) diff --git a/client/src/views/manage-teams/index.js b/client/src/views/manage-teams/index.js index 763154429..b70be5273 100644 --- a/client/src/views/manage-teams/index.js +++ b/client/src/views/manage-teams/index.js @@ -1,23 +1,42 @@ import React from 'react' import PropTypes from 'prop-types' -import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' +import Grid from '@material-ui/core/Grid' +import { TopBar } from '../common' import ManageTeamsList from './components/ManageTeamsList' const styles = theme => ({ - tableContainer: { - height: 320 + container: { + width: 'auto', + marginTop: theme.spacing.unit * 3, + marginLeft: theme.spacing.unit * 3, + marginRight: theme.spacing.unit * 3, + marginBottom: theme.spacing.unit * 6, + [theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: { + width: 800, + marginLeft: 'auto', + marginRight: 'auto' + } } }) const ManageTeams = ({ classes, ...props }) => (
- - Manage Your Teams - - + + + + + +
) diff --git a/client/src/views/team-members/index.js b/client/src/views/team-members/index.js index 7c450150f..a5c4c79c7 100644 --- a/client/src/views/team-members/index.js +++ b/client/src/views/team-members/index.js @@ -1,11 +1,10 @@ import React from 'react' import PropTypes from 'prop-types' -import Typography from '@material-ui/core/Typography' import { withStyles } from '@material-ui/core/styles' // import ManageTeamMembersList from './components/ManageTeamMembersList' -import { MessageCard } from '@advancedalgos/web-components' +import { TopBar } from '../common' const styles = theme => ({ tableContainer: { @@ -15,11 +14,7 @@ const styles = theme => ({ const TeamMembers = ({ classes }) => (
- - Team Members - - - +
) diff --git a/client/src/views/teams/components/TeamsDetails.js b/client/src/views/teams/components/TeamsDetails.js index d7cd1e0cf..d7d751d14 100644 --- a/client/src/views/teams/components/TeamsDetails.js +++ b/client/src/views/teams/components/TeamsDetails.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types' import CssBaseline from '@material-ui/core/CssBaseline' import Typography from '@material-ui/core/Typography' import Paper from '@material-ui/core/Paper' +import Grid from '@material-ui/core/Grid' import { withStyles } from '@material-ui/core/styles' import { Link } from 'react-router-dom' @@ -22,37 +23,38 @@ const styles = theme => ({ marginLeft: theme.spacing.unit * 3, marginRight: theme.spacing.unit * 3, marginBottom: theme.spacing.unit * 6, - [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { - width: 900, + [theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: { + width: 800, marginLeft: 'auto', marginRight: 'auto' } }, paper: { - marginTop: theme.spacing.unit * 3, + marginTop: 0, marginBottom: theme.spacing.unit * 3, - padding: theme.spacing.unit * 2, - [theme.breakpoints.up(600 + theme.spacing.unit * 3 * 2)]: { + padding: 0, + [theme.breakpoints.up(800 + theme.spacing.unit * 3 * 2)]: { marginTop: theme.spacing.unit * 6, marginBottom: theme.spacing.unit * 6, - padding: theme.spacing.unit * 3 + padding: `0 0 ${theme.spacing.unit * 6}px` } }, heroContent: { - maxWidth: 600, + maxWidth: 800, margin: '0 auto', - padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px` + padding: `0 0 ${theme.spacing.unit * 6}px` + }, + teamContent: { + margin: `${theme.spacing.unit * 1}px ${theme.spacing.unit * 3}px 0 0` }, banner: { maxWidth: '100%', - height: 'auto', - margin: '0 auto' + height: 'auto' }, avatar: { maxWidth: 100, height: 100, - margin: '0 1em 1em 0', - float: 'left' + margin: `${theme.spacing.unit * 1}px 0 0 ${theme.spacing.unit * 3}px ` } }) @@ -73,31 +75,38 @@ const TeamsDetails = ({ classes, team }) => {
+ ← Back to all teams - ← Back to all teams
{team.name} - {team.name} - - {team.name} - - - {team.createdAt} - - - Motto: {team.profile.motto} - - - Description: {team.profile.description} - - - Members: {team.members.length} - + + + {team.name} + + + + + {team.name} + + + {team.createdAt} + + + Motto: {team.profile.motto} + + + Description: {team.profile.description} + + + Members: {team.members.length} + + + +
diff --git a/client/src/views/teams/components/TeamsItem.js b/client/src/views/teams/components/TeamsItem.js index 34ba34df2..28ae53a9c 100644 --- a/client/src/views/teams/components/TeamsItem.js +++ b/client/src/views/teams/components/TeamsItem.js @@ -13,12 +13,12 @@ import Typography from '@material-ui/core/Typography' import { Link } from 'react-router-dom' // const TeamDetailsLink = ({ teamSlug, ...props }) => export const TeamsItem = ({ classes, team }) => { - /* let avatar + let avatar if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') { avatar = team.profile.avatar } else { - avatar = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22288%22%20height%3D%22225%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20288%20225%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_164edaf95ee%20text%20%7B%20fill%3A%23eceeef%3Bfont-weight%3Abold%3Bfont-family%3AArial%2C%20Helvetica%2C%20Open%20Sans%2C%20sans-serif%2C%20monospace%3Bfont-size%3A14pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_164edaf95ee%22%3E%3Crect%20width%3D%22288%22%20height%3D%22225%22%20fill%3D%22%2355595c%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2296.32500076293945%22%20y%3D%22118.8%22%3EThumbnail%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E' - } */ + avatar = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-avatar-default.png' + } let banner if (team.profile.banner !== undefined && team.profile.banner !== null) { banner = team.profile.banner @@ -26,7 +26,7 @@ export const TeamsItem = ({ classes, team }) => { banner = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-banner-default.png' } return ( - + { title={team.name} /> - - {team.name} - - - Members: 1 - - - Now recruiting! - + + + {team.name} + + + + {team.name} + + + Members: 1 + + + Now recruiting! + + + diff --git a/client/src/views/teams/components/TeamsList.js b/client/src/views/teams/components/TeamsList.js index ac416122f..0dc6877c9 100644 --- a/client/src/views/teams/components/TeamsList.js +++ b/client/src/views/teams/components/TeamsList.js @@ -30,11 +30,16 @@ const styles = theme => ({ flexDirection: 'column' }, cardMedia: { - paddingTop: '56.25%' // 16:9 + paddingTop: '25%' // 16:9 }, cardContent: { flexGrow: 1 }, + avatar: { + maxWidth: 50, + height: 50, + margin: '0 1em 1em 0' + }, buttonRight: { justifyContent: 'flex-end' } @@ -78,16 +83,6 @@ export const TeamsList = ({ classes, match }) => ( } else { return ( -
- - Teams - -
{!loading && data.teams_Teams.edges.map(team => ( diff --git a/client/src/views/teams/index.js b/client/src/views/teams/index.js index 3c2087d83..07034a796 100644 --- a/client/src/views/teams/index.js +++ b/client/src/views/teams/index.js @@ -1,9 +1,9 @@ import React from 'react' import PropTypes from 'prop-types' -import CssBaseline from '@material-ui/core/CssBaseline' import { withStyles } from '@material-ui/core/styles' +import { TopBar } from '../common' import TeamsList from './components/TeamsList' const styles = theme => ({ @@ -17,11 +17,12 @@ const styles = theme => ({ }, layout: { width: 'auto', + marginTop: theme.spacing.unit * 3, marginLeft: theme.spacing.unit * 3, marginRight: theme.spacing.unit * 3, marginBottom: theme.spacing.unit * 6, - [theme.breakpoints.up(900 + theme.spacing.unit * 3 * 2)]: { - width: 900, + [theme.breakpoints.up(1200 + theme.spacing.unit * 3 * 2)]: { + width: 1200, marginLeft: 'auto', marginRight: 'auto' } @@ -30,7 +31,7 @@ const styles = theme => ({ const Teams = ({ classes, match }) => ( - +