Client: Manage Team Dialogs

This commit is contained in:
Barry Low committed 2018-09-17 12:38:42 -07:00
1 parent 5b521b3620
commit 4e75489949
11 files changed
+593 -144

No files matched your search

+9 -7
View File
@@ -71,8 +71,8 @@ const isLoggedIn = async ctx => {
const isRequestingMemberAlsoOwner = ({ ctx, memberId, type, typeId }) =>
ctx.db.exists[type]({ id: typeId, owner: { auth0id: memberId } })
const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ auth0id: memberId })
ctx.db.exists[type]({ slug: typeId, owner: memberId })
const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ authId: memberId })
const directiveResolvers = {
isAuthenticated: async (next, source, args, ctx) => {
@@ -89,12 +89,14 @@ const directiveResolvers = {
throw new Error(`Unauthorized, incorrect role`)
},
isOwner: async (next, source, { type }, ctx) => {
const { id: typeId } =
console.log('directive isOwner: ', source, type, ctx)
const { slug: typeId } =
source && source.id
? source
: ctx.request.body.variables ? ctx.request.body.variables : { id: null }
const { auth0id: memberId } = await isLoggedIn(ctx)
console.log('directive isOwner 0: ', type, typeId, memberId)
const user = await isLoggedIn(ctx)
console.log('directive isOwner 0: ', typeId, user.sub)
const memberId = user.sub
const isOwner =
type === `Member`
? memberId === typeId
@@ -106,14 +108,14 @@ const directiveResolvers = {
throw new Error(`Unauthorized, must be owner`)
},
isOwnerOrHasRole: async (next, source, { roles, type }, ctx, ...p) => {
const { auth0id: memberId } = await isLoggedIn(ctx)
const { authId: memberId } = await isLoggedIn(ctx)
console.log('directive isOwnerOrHasRole 1: ', memberId, roles, type)
if(memberId === undefined && role=== undefined) throw new Error(`Not logged in`)
if (roles.includes(role)) {
return next()
}
const { auth0id: typeId } = ctx.request.body.variables
const { authId: typeId } = ctx.request.body.variables
const isOwner = await isRequestingMemberAlsoOwner({
ctx,
memberId,
@@ -2,8 +2,8 @@
import gql from 'graphql-tag'
export const DELETE_TEAM = gql`
mutation deleteTeam($id: ID!) {
deleteTeam(id: $id) {
mutation deleteTeam($slug: String!) {
deleteTeam(slug: $slug) {
id
}
}
+43
View File
@@ -0,0 +1,43 @@
import React from 'react'
import PropTypes from 'prop-types'
import Typography from '@material-ui/core/Typography'
import { withStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardContent from '@material-ui/core/CardContent'
const styles = theme => ({
card: {
display: 'flex',
width: '100%',
margin: '1.5em',
padding: '3em'
},
cardDetails: {
display: 'flex',
flex: 1
},
cardContent: {
flex: 1
}
})
export const MessageCard = ({ classes, message, children }) => (
<Card className={classes.card}>
<div className={classes.cardDetails}>
<CardContent className={classes.cardContent}>
<Typography variant='headline' align='center' gutterBottom>{message}</Typography>
{children}
</CardContent>
</div>
</Card>
)
MessageCard.propTypes = {
children: PropTypes.node,
classes: PropTypes.object.isRequired,
message: PropTypes.string.isRequired
}
export default withStyles(styles)(MessageCard)
+3
View File
@@ -0,0 +1,3 @@
import MessageCard from './MessageCard'
export { MessageCard }
+7
View File
@@ -34,6 +34,13 @@ const styles = theme => ({
aawebMedia: {
width: '100%',
height: 320
},
dashLink: {
float: 'right',
color: '#111',
fontSize: 16,
textDecoration: 'none',
paddingRight: '1em'
}
})
@@ -0,0 +1,196 @@
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 AddIcon from '@material-ui/icons/Add'
import TextField from '@material-ui/core/TextField'
import FormControl from '@material-ui/core/FormControl'
import FormHelperText from '@material-ui/core/FormHelperText'
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 Typography from '@material-ui/core/Typography'
import { getItem } from '../../../utils/local-storage'
import { isEmpty } from '../../../utils/js-helpers'
import CREATE_TEAM from '../../../graphql/teams/CreateTeamMutation'
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
// import { checkGraphQLError } from '../../../utils/graphql-errors'
const styles = theme => ({
dialogStyle: {
padding: '3em'
},
buttonRight: {
// position: 'absolute',
// right: '3em'
marginTop: '1em',
marginRight: 'auto',
marginLeft: 'auto',
display: 'block',
lineHeight: '1em'
}
})
export class CreateTeamDialog 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: '',
errors: {
name: ''
}
}
}
render () {
const { classes, authId } = this.props
return (
<Mutation
mutation={CREATE_TEAM}
refetchQueries={[
{
query: GET_TEAMS_BY_OWNER,
variables: { authId }
}
]}
>
{(createTeam, { loading, error, data }) => {
let errors
let loader = null
if (loading) {
loader = <Typography variant='subheading'>Submitting team...</Typography>
}
if (error) {
errors = error.graphQLErrors.map(({ message }, i) => {
// const displayMessage = checkGraphQLError(message)
return (
<Typography key={i} variant='caption'>
{message}
</Typography>
)
})
}
return (
<div>
<Button variant='fab' color='primary' aria-label='Add' className={classes.buttonRight} onClick={this.handleClickOpen}>
<AddIcon />
</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby='form-dialog-title'
>
<DialogTitle id='form-dialog-title'>Create a Team</DialogTitle>
<DialogContent>
<DialogContentText>Team Name:</DialogContentText>
<FormControl required error={e => (this.state.errors.name !== '' || error)}>
<TextField
autoFocus
margin='dense'
id='teamname'
label='Team Name'
type='text'
fullWidth
value={this.state.name}
onChange={this.handleChange}
error={e => this.state.errors.name !== '' || error}
/>
{this.state.errors.name !== '' && (<FormHelperText>{this.state.errors.name}</FormHelperText>)}
{error && (<FormHelperText>{errors}</FormHelperText>)}
{loader}
</FormControl>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color='primary'>
Cancel
</Button>
<Button onClick={e => {
this.handleSubmit(e, createTeam, this.state.name)
}} color='primary'>
Create Team
</Button>
</DialogActions>
</Dialog>
</div>
)
}}
</Mutation>
)
}
handleClickOpen () {
this.setState({ open: true })
}
handleClose () {
this.setState({ open: false })
}
handleChange (e) {
const errors = this.validate(e.target.value)
if (isEmpty(errors)) {
this.setState({ errors: { name: '' } })
this.setState({ name: e.target.value })
} else {
this.setState({ errors: errors })
this.setState({ name: e.target.value })
}
}
async handleSubmit (e, createTeam, name) {
e.preventDefault()
const currentUser = await getItem('user')
let authId = JSON.parse(currentUser)
authId = authId.authId
console.log('createTeam submit: ', authId, name)
const slug = this.slugify(name)
await createTeam({ variables: { name, slug, owner: authId } })
this.setState({ name: '' })
}
validate (data) {
const errors = {}
if (data === '') errors.name = 'Please enter a team name'
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
}
}
CreateTeamDialog.propTypes = {
classes: PropTypes.object.isRequired,
authId: PropTypes.string
}
export default withStyles(styles)(CreateTeamDialog)
@@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import { Query } from 'react-apollo'
import { withStateHandlers, lifecycle, compose } from 'recompose'
import { Link } from 'react-router-dom'
import Typography from '@material-ui/core/Typography'
import Grid from '@material-ui/core/Grid'
@@ -9,7 +10,8 @@ import Grid from '@material-ui/core/Grid'
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
import DashTeamItem from './DashTeamItem'
import CreateTeamWrapper from './CreateTeamWrapper'
import CreateTeamDialog from './CreateTeamDialog'
import { MessageCard } from '../../common/'
import { isDefined, isString } from '../../../utils/js-helpers'
import { getItem } from '../../../utils/local-storage'
@@ -38,11 +40,10 @@ export const DashTeam = ({ classes, user = null }) => {
)
}
return (
<Grid item md={6}>
<Grid item md={6} style={{ position: 'relative' }}>
<Typography variant='display1' gutterBottom>
Teams
Teams <Link to='/manage-teams' className={classes.dashLink}>Manage Teams</Link>
</Typography>
<CreateTeamWrapper authId={authId} />
<Query query={GET_TEAMS_BY_OWNER} variables={{ authId }}>
{({ loading, error, data }) => {
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
@@ -70,6 +71,16 @@ export const DashTeam = ({ classes, user = null }) => {
{loader}
</Grid>
)
} else {
return (
<Grid container spacing={40}>
<Grid xs={10}>
<MessageCard message='No teams yet...'>
<CreateTeamDialog authId={authId} />
</MessageCard>
</Grid>
</Grid>
)
}
} else {
return (
@@ -0,0 +1,130 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router-dom'
import { Mutation } from 'react-apollo'
import Button from '@material-ui/core/Button'
import DeleteIcon from '@material-ui/icons/Delete'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import DialogTitle from '@material-ui/core/DialogTitle'
import Typography from '@material-ui/core/Typography'
import DELETE_TEAM from '../../../graphql/teams/DeleteTeamMutation'
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
import { checkGraphQLError } from '../../../utils/graphql-errors'
export class ManageTeamDelete 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.state = {
open: false,
motto: '',
description: ''
}
}
handleClickOpen () {
this.setState({ open: true })
}
handleClose () {
this.setState({ open: false })
}
handleChange (e) {
this.setState({ name: e.target.value })
}
render () {
console.log(this.props, this.props.slug)
const authId = this.props.authId
return (
<Mutation
mutation={DELETE_TEAM}
refetchQueries={[
{
query: GET_TEAMS_BY_OWNER,
variables: { authId }
}
]}
update={(cache, { data: { deleteTeam } }) => {
const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER })
console.log('Mutation cache update: ', deleteTeam, data)
data.getTeamsByOwner.push(deleteTeam)
cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data })
}}
>
{(deleteTeam, { loading, error, data }) => {
let errors
let loader
if (loading) {
loader = <Typography variant='caption'>Submitting team...</Typography>
}
if (error) {
errors = error.graphQLErrors.map(({ message }, i) => {
const displayMessage = checkGraphQLError(message)
console.log('createTeam error:', displayMessage)
return (
<Typography key={i} variant='caption'>
{message}
</Typography>
)
})
}
return (
<div>
<Button size='small' color='primary' className={this.props.classes.buttonRight} onClick={this.handleClickOpen}>
<DeleteIcon /> Delete
</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby='form-dialog-title'
>
<DialogTitle id='form-dialog-title'>Delete Team Team</DialogTitle>
<DialogContent>
<Typography variant='subheading' color='primary'>DANGER - Deleting your team cannot be undone</Typography>
<Typography variant='subheading'>Are you sure you want to delete this team?</Typography>
{loader}
{errors}
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color='primary'>
Cancel
</Button>
<Button onClick={e => {
this.handleSubmit(e, deleteTeam, this.props.slug, authId)
}} color='primary'>
Delete Team
</Button>
</DialogActions>
</Dialog>
</div>
)
}}
</Mutation>
)
}
async handleSubmit (e, deleteTeam, slug, authId) {
e.preventDefault()
await deleteTeam({ variables: { slug, owner: authId } })
}
}
ManageTeamDelete.propTypes = {
classes: PropTypes.object.isRequired,
slug: PropTypes.string.isRequired,
authId: PropTypes.string.isRequired
}
export default withRouter(ManageTeamDelete)
@@ -1,8 +1,10 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router-dom'
import { Mutation } from 'react-apollo'
import Button from '@material-ui/core/Button'
import AddIcon from '@material-ui/icons/Add'
import EditIcon from '@material-ui/icons/Edit'
import TextField from '@material-ui/core/TextField'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
@@ -13,15 +15,19 @@ import Typography from '@material-ui/core/Typography'
import { getItem } from '../../../utils/local-storage'
import UPDATE_TEAM_PROFILE from '../../../graphql/teams/UpdateTeamProfileMutation'
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
import { checkGraphQLError } from '../../../utils/graphql-errors'
export class ManageTeamEdit extends Component {
constructor (props) {
super(props)
this.handleClickOpen = this.handleClickOpen.bind(this)
this.handleClose = this.handleClose.bind(this)
this.handlePost = this.handlePost.bind(this)
this.slugify = this.slugify.bind(this)
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.state = {
open: false,
@@ -30,6 +36,101 @@ export class ManageTeamEdit extends Component {
}
}
render () {
console.log(this.props, this.props.slug)
return (
<Mutation
mutation={UPDATE_TEAM_PROFILE}
update={(cache, { data: { deleteTeam } }) => {
const data = cache.readQuery({ query: GET_TEAMS_BY_OWNER })
console.log('Mutation cache update: ', deleteTeam, data)
data.getTeamsByOwner.push(deleteTeam)
cache.writeQuery({ query: GET_TEAMS_BY_OWNER, data })
}}
>
{(updateTeamProfile, { loading, error, data }) => {
let errors
let loader
let description
let motto
if (loading) {
loader = <Typography variant='caption'>Submitting team...</Typography>
}
if (error) {
errors = error.graphQLErrors.map(({ message }, i) => {
const displayMessage = checkGraphQLError(message)
console.log('updateTeamProfile error:', displayMessage)
return (
<Typography key={i} variant='caption'>
{message}
</Typography>
)
})
}
return (
<div>
<Button size='small' color='primary' className={this.props.classes.buttonRight} onClick={this.handleClickOpen}>
<EditIcon /> Edit
</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby='form-dialog-title'
>
<DialogTitle id='form-dialog-title'>Edit Team Details</DialogTitle>
<DialogContent>
<Typography variant='subheading'>Team Creation</Typography>
<DialogContentText>Team Motto:</DialogContentText>
<TextField
autoFocus
margin='dense'
id='teammotto'
label='Team Motto'
type='text'
fullWidth
value={this.state.motto}
onChange={this.handleChange}
inputRef={node => {
motto = node
}}
/>
<DialogContentText>Team description:</DialogContentText>
<TextField
autoFocus
margin='dense'
id='teamDescription'
label='Team Description'
type='text'
rows={4}
multiline
fullWidth
value={this.state.description}
onChange={this.handleChange}
inputRef={node => {
description = node
}}
/>
{loader}
{errors}
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color='primary'>
Cancel
</Button>
<Button onClick={e => {
this.handleSubmit(e, updateTeamProfile, this.props.slug, description, motto)
}} color='primary'>
Update Team
</Button>
</DialogActions>
</Dialog>
</div>
)
}}
</Mutation>
)
}
handleClickOpen () {
this.setState({ open: true })
}
@@ -39,95 +140,29 @@ export class ManageTeamEdit extends Component {
}
handleChange (e) {
this.setState({ name: e.target.value })
switch (e.target.id) {
case 'motto':
this.setState({ motto: e.target.value })
break
case 'description':
this.setState({ description: e.target.value })
break
default:
}
}
render () {
console.log(this.props, this.props.team)
return (
<div>
<Button
variant='extendedFab'
aria-label='AddTeam'
className={this.props.classes.button}
onClick={this.handleClickOpen}
>
<AddIcon className={this.props.classes.extendedIcon} />
<Typography variant='subheading'>Create A Team</Typography>
</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby='form-dialog-title'
>
<DialogTitle id='form-dialog-title'>Edit Team Details</DialogTitle>
<DialogContent>
<Typography variant='subheading'>Team Creation</Typography>
<DialogContentText>Team Motto:</DialogContentText>
<TextField
autoFocus
margin='dense'
id='teammotto'
label='Team Motto'
type='text'
fullWidth
value={this.state.mottoe}
onChange={this.handleChange}
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color='primary'>
Cancel
</Button>
<Button onClick={this.handlePost} color='primary'>
Create Team
</Button>
</DialogActions>
</Dialog>
</div>
)
}
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
}
async handlePost (e) {
async handleSubmit (e, updateTeamProfile, slug, description, motto) {
e.preventDefault()
const { name } = this.state
const slug = this.slugify(name)
const currentUser = await getItem('user')
let authId = JSON.parse(currentUser)
authId = authId.sub
console.log('createPage cu:', JSON.parse(currentUser))
await this.props.createTeamMutation({
variables: {
name,
slug,
owner: authId
}
})
this.setState({ open: false })
authId = authId.authId
await updateTeamProfile({ variables: { slug, owner: authId, description: description, motto: motto } })
}
}
ManageTeamEdit.propTypes = {
classes: PropTypes.object.isRequired,
team: PropTypes.object.isRequired,
createTeamMutation: PropTypes.function
slug: PropTypes.string.isRequired
}
export default withRouter(ManageTeamEdit)
@@ -10,8 +10,9 @@ import Button from '@material-ui/core/Button'
import Typography from '@material-ui/core/Typography'
import ManageTeamDelete from './ManageTeamDelete'
import ManageTeamEdit from './ManageTeamEdit'
export const ManageTeamsItem = ({ classes, team }) => (
export const ManageTeamsItem = ({ classes, team, authId }) => (
<Grid item xs={12}>
<Card className={classes.card}>
<div className={classes.cardDetails}>
@@ -32,10 +33,8 @@ export const ManageTeamsItem = ({ classes, team }) => (
<Button size='small' color='primary' className={classes.buttonRight}>
Details
</Button>
<ManageTeamDelete classes={classes} slug={team.slug} />
<Button size='small' color='primary' className={classes.buttonRight}>
Delete
</Button>
<ManageTeamEdit classes={classes} slug={team.slug} authId={authId} />
<ManageTeamDelete classes={classes} slug={team.slug} authId={authId} />
</CardActions>
</div>
</Card>
@@ -44,7 +43,8 @@ export const ManageTeamsItem = ({ classes, team }) => (
ManageTeamsItem.propTypes = {
classes: PropTypes.object.isRequired,
team: PropTypes.object.isRequired
team: PropTypes.object.isRequired,
authId: PropTypes.string.isRequired
}
export default ManageTeamsItem
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
import { Query } from 'react-apollo'
import { withStateHandlers, lifecycle, compose } from 'recompose'
import Typography from '@material-ui/core/Typography'
import Grid from '@material-ui/core/Grid'
import { withStyles } from '@material-ui/core/styles'
@@ -13,6 +12,8 @@ import { getItem } from '../../../utils/local-storage'
import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
import ManageTeamsItem from './ManageTeamsItem'
import CreateTeamDialog from './CreateTeamDialog'
import { MessageCard } from '../../common/'
const styles = theme => ({
heroContent: {
@@ -55,53 +56,74 @@ export const ManageTeamsList = ({ classes, user = null }) => {
if (isDefined(owner.authId)) authId = owner.authId
}
console.log('ManageTeamsList 2: ', owner, authId)
if (authId === undefined || authId === null) {
return (
<Grid container spacing={40}>
<Grid>
<MessageCard message='Loading...' />
</Grid>
</Grid>
)
} else {
return (
<Query query={GET_TEAMS_BY_OWNER} fetchPolicy='network-only' variables={{ authId }}>
{({ loading, error, data }) => {
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
return (
<Query query={GET_TEAMS_BY_OWNER} fetchPolicy='network-only' variables={{ authId }}>
{({ loading, error, data }) => {
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
let errors
if (error) {
errors = error.graphQLErrors.map(({ message }, i) => {
return (
<Typography key={i} variant='caption'>
{message}
</Typography>
)
})
}
if (!loading && !error) {
if (data.teamsByOwner.length > 0) {
return (
<React.Fragment>
let errors = null
if (error) {
errors = error.graphQLErrors.map(({ message }, i) => {
return (
<MessageCard message={message} />
)
})
}
if (!loading && !error) {
if (data.teamsByOwner.length > 0) {
return (
<React.Fragment>
<Grid container spacing={40}>
{!loading &&
data.teamsByOwner.map(team => (
<ManageTeamsItem
key={team.id}
team={team}
classes={classes}
authId={authId}
/>
))}
<MessageCard message='Create another team'>
<CreateTeamDialog authId={authId} />
</MessageCard>
{errors}
</Grid>
</React.Fragment>
)
} else {
return (
<Grid container spacing={40}>
{!loading &&
data.teamsByOwner.map(team => (
<ManageTeamsItem
key={team.id}
team={team}
classes={classes}
/>
))}
{errors}
<Grid xs={10}>
<MessageCard message='You don&rsquo;t have any teams. Create one!'>
<CreateTeamDialog authId={authId} />
</MessageCard>
</Grid>
</Grid>
</React.Fragment>
)
}
} else {
return (
<Grid container spacing={40}>
<Grid xs={12}>
<MessageCard message='Loading...' />
if (errors !== null) (<MessageCard message={errors} />)
</Grid>
</Grid>
)
}
} else {
return (
<Grid container spacing={40}>
<Typography variant='subheading' gutterBottom>
Loading...
</Typography>
{errors}
</Grid>
)
}
}}
</Query>
)
}}
</Query>
)
}
}
ManageTeamsList.propTypes = {