@@ -106,20 +125,19 @@ export class CreateTeamDialog extends Component {
async handlePost (e) {
e.preventDefault()
- const { name } = this.state
+ const { name, botName } = 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))
+ const botSlug = this.slugify(botName)
+
await this.props.createTeamMutation({
variables: {
name,
slug,
- owner: authId
+ botName,
+ botSlug
}
})
- this.setState({ open: false })
+ this.setState({ open: false, name: '', botName: '' })
}
}
diff --git a/client/src/views/dashboard/components/DashTeam.js b/client/src/views/dashboard/components/DashTeam.js
index cc2f3b1b4..32fa0c54a 100644
--- a/client/src/views/dashboard/components/DashTeam.js
+++ b/client/src/views/dashboard/components/DashTeam.js
@@ -18,14 +18,11 @@ import { getItem } from '../../../utils/local-storage'
export const DashTeam = ({ classes, user = null }) => {
let owner
- let loader
let authId = null
console.log('DashTeam: ', user)
if (user !== null && isString(user)) {
owner = JSON.parse(user)
if (isDefined(owner.authId)) authId = owner.authId
- } else {
- loader = Loading...
}
console.log('DashTeam 2: ', owner, authId)
@@ -71,7 +68,6 @@ export const DashTeam = ({ classes, user = null }) => {
))}
{queryLoader}
{errors}
- {loader}
)
} else {
@@ -79,7 +75,7 @@ export const DashTeam = ({ classes, user = null }) => {
-
+
diff --git a/client/src/views/dashboard/components/InviteMemberDialog.js b/client/src/views/dashboard/components/InviteMemberDialog.js
new file mode 100644
index 000000000..f34b8c9ee
--- /dev/null
+++ b/client/src/views/dashboard/components/InviteMemberDialog.js
@@ -0,0 +1,207 @@
+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 DialogTitle from '@material-ui/core/DialogTitle'
+import Typography from '@material-ui/core/Typography'
+import { isEmpty } from '../../../utils/js-helpers'
+
+import SEND_MEMBER_INVITE from '../../../graphql/teams/SendMemberInvite'
+
+// 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 InviteMemberDialog 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.state = {
+ open: false,
+ email: '',
+ errors: {
+ email: ''
+ }
+ }
+ }
+
+ render () {
+ const { classes, teamId } = this.props
+
+ if (this.state.open) {
+ return (
+
+ {(sendMemberInvite, { loading, error, data }) => {
+ console.log('sendMemberInvite: ', data)
+ let errors
+ let loader = null
+ if (loading) {
+ loader = (
+ Submitting invitation...
+ )
+ }
+ if (error) {
+ errors = error.graphQLErrors.map(({ message }, i) => {
+ // const displayMessage = checkGraphQLError(message)
+ return (
+
+ {message}
+
+ )
+ })
+ }
+ return (
+
+
+
+
+
+ Invite a New Team Member
+
+ {(data === undefined || data.sendMemberInviteSG !== 'Success') && (
+
+ this.handleChange(e)}
+ error={this.state.errors.email !== ''}
+ />
+ {this.state.errors.email !== '' && (
+ {this.state.errors.email}
+ )}
+ {error && {errors} }
+ {loader}
+
+ )}
+ {data !== undefined && data.sendMemberInviteSG === 'Success' && (
+ Invitation successfully sent!
+ )}
+
+
+ {(data === undefined || data.sendMemberInviteSG !== 'Success') && (
+
+
+ Cancel
+
+ {
+ this.handleSubmit(e, sendMemberInvite, this.state.email, teamId)
+ }}
+ color='primary'
+ >
+ Send Invitation
+
+
+ )}
+ {data !== undefined && data.sendMemberInviteSG === 'Success' && (
+
+ Close
+
+ )}
+
+
+
+ )
+ }}
+
+ )
+ } else {
+ return (
+
+
+
+ )
+ }
+ }
+
+ 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: { email: '' } })
+ this.setState({ email: e.target.value })
+ } else {
+ this.setState({ errors: errors })
+ this.setState({ email: e.target.value })
+ }
+ }
+
+ async handleSubmit (e, sendMemberInvite, email, teamId) {
+ e.preventDefault()
+ console.log('sendMemberInvite submit: ', email, teamId)
+ await sendMemberInvite({ variables: { email, teamId } })
+ this.setState({ email: '' })
+ }
+
+ validate (data) {
+ const errors = {}
+ if (data === '') errors.email = 'Please enter an email address'
+ return errors
+ }
+}
+
+InviteMemberDialog.propTypes = {
+ classes: PropTypes.object.isRequired,
+ teamId: PropTypes.string
+}
+
+export default withStyles(styles)(InviteMemberDialog)
diff --git a/client/src/views/dashboard/components/ManageFBEdit.js b/client/src/views/dashboard/components/ManageFBEdit.js
new file mode 100644
index 000000000..ba150bc83
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageFBEdit.js
@@ -0,0 +1,223 @@
+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 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'
+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 { MessageCard, ImageUpload } from '@advancedalgos/web-components'
+
+import UPDATE_FB from '../../../graphql/teams/UpdateFBMutation'
+import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
+
+import { checkGraphQLError } from '../../../utils/graphql-errors'
+
+import GET_AZURE_SAS from '../../../graphql/teams/GetAzureSASMutation'
+
+const styles = theme => ({
+ dialogContainer: {
+ display: 'block',
+ margin: '3em',
+ minWidth: 400
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ }
+})
+
+export class ManageFBEdit extends Component {
+ constructor (props) {
+ super(props)
+
+ this.handleClickOpen = this.handleClickOpen.bind(this)
+ this.handleClose = this.handleClose.bind(this)
+ this.handleSubmit = this.handleSubmit.bind(this)
+ this.handleAvatar = this.handleAvatar.bind(this)
+
+ const avatar = props.fb.avatar || ''
+ this.authId = props.authId
+
+ this.state = {
+ open: false,
+ avatar: avatar
+ }
+ }
+
+ render () {
+ console.log('ManageFBEdit ', this.props, this.props.slug, this.props.fb)
+ const { classes, fb, slug } = this.props
+ return (
+
+ {(updateFB, { loading, error, data }) => {
+ let errors
+ let loader
+ if (loading) {
+ loader = (
+ Submitting team...
+ )
+ }
+ if (error) {
+ errors = error.graphQLErrors.map(({ message }, i) => {
+ const displayMessage = checkGraphQLError(message)
+ console.log('updateTeamProfile error:', displayMessage)
+ return (
+
+ {message}
+
+ )
+ })
+ }
+ return (
+
+
+ Edit
+
+
+
+
+ Edit Financial Being
+
+
+
+ {(getAzureSAS, { loading, error, data }) => {
+ console.log('getAzureSAS: ', loading, error, data, fb)
+ const AzureStorageUrl = process.env.AZURE_STORAGE_URL
+ const containerName = slug
+ let AzureSASURL
+ if (!loading && data !== undefined) {
+ AzureSASURL = data.getAzureSAS
+ } else {
+ getAzureSAS({ variables: { teamSlug: containerName } })
+ }
+
+ let avatar = null
+ if (fb.avatar !== undefined && fb.avatar !== null) avatar = fb.avatar
+ if (this.state.avatar !== null) avatar = this.state.avatar
+ if (this.state.avatar === null && fb.avatar === undefined) avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
+
+ if (loading || data === undefined) {
+ return ( )
+ } else {
+ return (
+
+ Update Financial Beings's Avatar
+
+
+ )
+ }
+ }}
+
+
+ {loader}
+ {errors}
+
+
+
+ Cancel
+
+ {
+ this.handleSubmit(e, updateFB, fb.id, slug)
+ }}
+ color='primary'
+ >
+ Update Financial Being
+
+
+
+
+
+ )
+ }}
+
+ )
+ }
+
+ handleClickOpen () {
+ this.setState({ open: true })
+ }
+
+ handleClose () {
+ this.setState({ open: false })
+ }
+
+ handleAvatar (avatarUrl) {
+ console.log('handleAvatar: ', avatarUrl)
+ this.setState({ avatar: `${avatarUrl}?${Math.random()}` })
+ }
+
+ async handleSubmit (e, updateFB, fbId, slug) {
+ console.log('handleSubmit: ', this.state)
+ e.preventDefault()
+
+ await updateFB({
+ variables: {
+ fbId,
+ avatar: this.state.avatar
+ }
+ })
+ this.setState({ open: false })
+ }
+}
+
+ManageFBEdit.propTypes = {
+ classes: PropTypes.object.isRequired,
+ slug: PropTypes.string.isRequired,
+ fb: PropTypes.object,
+ authId: PropTypes.string.isRequired
+}
+
+export default withStyles(styles)(ManageFBEdit)
diff --git a/client/src/views/dashboard/components/ManageFBItem.js b/client/src/views/dashboard/components/ManageFBItem.js
new file mode 100644
index 000000000..466f43f95
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageFBItem.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import Grid from '@material-ui/core/Grid'
+import Card from '@material-ui/core/Card'
+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 ManageFBEdit from './ManageFBEdit'
+
+export const ManageFBItem = ({ classes, team, authId }) => {
+ console.log('ManageFBItem', team, team.fb[0], team.profile.avatar)
+ let avatar
+ if (team.fb[0].avatar !== undefined && team.fb[0].avatar !== 'a') {
+ avatar = team.fb[0].avatar
+ } else {
+ avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
+ }
+ return (
+
+
+
+
+
+
+ {team.fb[0].name}
+
+
+ {team.fb[0].kind}
+
+
+
+
+
+
+
+
+ )
+}
+
+ManageFBItem.propTypes = {
+ classes: PropTypes.object.isRequired,
+ team: PropTypes.object.isRequired,
+ authId: PropTypes.string.isRequired
+}
+
+export default ManageFBItem
diff --git a/client/src/views/dashboard/components/ManageFBList.js b/client/src/views/dashboard/components/ManageFBList.js
new file mode 100644
index 000000000..a865be3b9
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageFBList.js
@@ -0,0 +1,150 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Query } from 'react-apollo'
+import { withStateHandlers, lifecycle, compose } from 'recompose'
+
+import Grid from '@material-ui/core/Grid'
+import { MessageCard } from '@advancedalgos/web-components'
+import { withStyles } from '@material-ui/core/styles'
+
+import { isDefined, isString } from '../../../utils/js-helpers'
+import { getItem } from '../../../utils/local-storage'
+
+import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
+
+import ManageFBItem from './ManageFBItem'
+import CreateTeamDialog from './CreateTeamDialog'
+
+const styles = theme => ({
+ heroContent: {
+ maxWidth: 600,
+ margin: '0 auto',
+ padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
+ },
+ cardGrid: {
+ padding: `${theme.spacing.unit * 8}px 0`
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ },
+ card: {
+ display: 'flex',
+ width: '100%'
+ },
+ cardDetails: {
+ display: 'flex',
+ flex: 1
+ },
+ cardContent: {
+ flex: 1
+ },
+ cardMedia: {
+ flex: 1,
+ width: 100,
+ height: 100,
+ maxWidth: 100,
+ justifyContent: 'flex-start'
+ }
+})
+
+export const ManageFBList = ({ classes, user = null }) => {
+ let owner
+ let authId = null
+ console.log('ManageTeamsList: ', user)
+ if (user !== null && isString(user)) {
+ owner = JSON.parse(user)
+ if (isDefined(owner.authId)) authId = owner.authId
+ }
+ console.log('ManageTeamsList 2: ', owner, authId)
+ if (authId === undefined || authId === null) {
+ return (
+
+
+
+
+
+ )
+ } else {
+ return (
+
+ {({ loading, error, data }) => {
+ console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
+
+ let errors = null
+ if (error) {
+ errors = error.graphQLErrors.map(({ message }, i) => {
+ return
+ })
+ }
+ if (!loading && !error) {
+ if (data.teamsByOwner.length > 0) {
+ return (
+
+
+ {!loading &&
+ data.teamsByOwner.map(team => (
+
+ ))}
+ {errors}
+
+
+ )
+ } else {
+ return (
+
+
+
+
+
+
+
+ )
+ }
+ } else {
+ return (
+
+
+
+ {errors !== null && }
+
+
+ )
+ }
+ }}
+
+ )
+ }
+}
+
+ManageFBList.propTypes = {
+ user: PropTypes.any,
+ classes: PropTypes.object.isRequired
+}
+
+const getUserOnMount = lifecycle({
+ componentDidMount () {
+ getItem('user').then(user => {
+ this.setState({ user })
+ }) // Set user to state
+ }
+})
+
+const mapStateToProps = withStateHandlers(() => ({ user: null }), {
+ user: ({ user }) => () => ({ user })
+})
+
+const ManageFBListAuthId = compose(
+ mapStateToProps,
+ getUserOnMount
+)(ManageFBList)
+
+export default withStyles(styles)(ManageFBListAuthId)
diff --git a/client/src/views/dashboard/components/ManageMemberDelete.js b/client/src/views/dashboard/components/ManageMemberDelete.js
new file mode 100644
index 000000000..b3ee25d1b
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageMemberDelete.js
@@ -0,0 +1,152 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { withStyles } from '@material-ui/core/styles'
+import { Mutation } from 'react-apollo'
+
+import Button from '@material-ui/core/Button'
+import PersonAddDisabledIcon from '@material-ui/icons/PersonAddDisabled'
+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 REMOVE_TEAM_MEMBER from '../../../graphql/teams/RemoveTeamMemberMutation'
+import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
+
+import { checkGraphQLError } from '../../../utils/graphql-errors'
+
+const styles = theme => ({
+ dialogContainer: {
+ display: 'block',
+ margin: '3em',
+ minWidth: 400
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ }
+})
+
+export class ManageMemberDelete 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
+ }
+ }
+
+ 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.teamId)
+ const { classes, teamId, authId } = this.props
+ return (
+
+ {(deleteTeam, { loading, error, data }) => {
+ let errors
+ let loader
+ if (loading) {
+ loader = (
+ Submitting team...
+ )
+ }
+ if (error) {
+ errors = error.graphQLErrors.map(({ message }, i) => {
+ const displayMessage = checkGraphQLError(message)
+ console.log('createTeam error:', displayMessage)
+ return (
+
+ {message}
+
+ )
+ })
+ }
+ return (
+
+
+ Remove
+
+
+
+
+ Remove Team Member
+
+
+
+ DANGER - Removing your team cannot be undone
+
+
+ Are you sure you want to remove this team member?
+
+ {loader}
+ {errors}
+
+
+
+ Cancel
+
+ {
+ this.handleSubmit(
+ e,
+ deleteTeam,
+ teamId,
+ authId
+ )
+ }}
+ color='primary'
+ >
+ Remove Member
+
+
+
+
+
+ )
+ }}
+
+ )
+ }
+
+ async handleSubmit (e, deleteTeam, teamId, memberId) {
+ e.preventDefault()
+ await deleteTeam({ variables: { teamId, memberId } })
+ this.setState({ open: false })
+ }
+}
+
+ManageMemberDelete.propTypes = {
+ classes: PropTypes.object.isRequired,
+ teamId: PropTypes.string.isRequired,
+ authId: PropTypes.string
+}
+
+export default withStyles(styles)(ManageMemberDelete)
diff --git a/client/src/views/dashboard/components/ManageMemberRole.js b/client/src/views/dashboard/components/ManageMemberRole.js
new file mode 100644
index 000000000..6edf5ddf1
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageMemberRole.js
@@ -0,0 +1,169 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { withStyles } from '@material-ui/core/styles'
+import { Mutation } from 'react-apollo'
+
+import Button from '@material-ui/core/Button'
+import AssignmentIndIcon from '@material-ui/icons/AssignmentInd'
+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 TextField from '@material-ui/core/TextField'
+import MenuItem from '@material-ui/core/MenuItem'
+
+import SET_TEAM_MEMBER_ROLE from '../../../graphql/teams/SetTeamMemberRoleMutation'
+import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
+
+import { checkGraphQLError } from '../../../utils/graphql-errors'
+
+const styles = theme => ({
+ dialogContainer: {
+ display: 'block',
+ margin: '3em',
+ minWidth: 400
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ }
+})
+
+const roles = [
+ { role: 'Admin' },
+ { role: 'Member' }
+]
+
+export class ManageMemberRole 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,
+ role: ''
+ }
+ }
+
+ 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.teamId)
+ const { classes, teamId, authId } = this.props
+ return (
+
+ {(setTeamMemberRole, { loading, error, data }) => {
+ let errors
+ let loader
+ if (loading) {
+ loader = (
+ Submitting team...
+ )
+ }
+ if (error) {
+ errors = error.graphQLErrors.map(({ message }, i) => {
+ const displayMessage = checkGraphQLError(message)
+ console.log('createTeam error:', displayMessage)
+ return (
+
+ {message}
+
+ )
+ })
+ }
+ return (
+
+
+ Set Role
+
+
+
+
+ Set Team Member Role
+
+
+
+ Admin members can approve new team members, send team invitations, and remove team members.
+
+ this.setState({ role: e.target.value })}
+ fullWidth
+ >
+ {roles.map(role => (
+ {role.role}
+ ))}
+
+ {loader}
+ {errors}
+
+
+
+ Cancel
+
+ {
+ this.handleSubmit(
+ e,
+ setTeamMemberRole,
+ teamId,
+ authId
+ )
+ }}
+ color='primary'
+ >
+ Set Member Role
+
+
+
+
+
+ )
+ }}
+
+ )
+ }
+
+ async handleSubmit (e, setTeamMemberRole, teamId, authId) {
+ e.preventDefault()
+ const role = this.state.role
+ await setTeamMemberRole({ variables: { teamId, memberId: authId, role: role } })
+ this.setState({ open: false })
+ }
+}
+
+ManageMemberRole.propTypes = {
+ classes: PropTypes.object.isRequired,
+ teamId: PropTypes.string.isRequired,
+ authId: PropTypes.string.isRequired
+}
+
+export default withStyles(styles)(ManageMemberRole)
diff --git a/client/src/views/dashboard/components/ManageMemberStatus.js b/client/src/views/dashboard/components/ManageMemberStatus.js
new file mode 100644
index 000000000..a6f1f6e8f
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageMemberStatus.js
@@ -0,0 +1,99 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { withStyles } from '@material-ui/core/styles'
+
+import Button from '@material-ui/core/Button'
+import HistoryIcon from '@material-ui/icons/History'
+import Dialog from '@material-ui/core/Dialog'
+import Typography from '@material-ui/core/Typography'
+import Card from '@material-ui/core/Card'
+import CardContent from '@material-ui/core/CardContent'
+import CardActions from '@material-ui/core/CardActions'
+
+const styles = theme => ({
+ dialogContainer: {
+ display: 'block',
+ margin: '3em',
+ minWidth: 400
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ }
+})
+
+export class ManageMemberStatus extends Component {
+ constructor (props) {
+ super(props)
+
+ this.handleClickOpen = this.handleClickOpen.bind(this)
+ this.handleClose = this.handleClose.bind(this)
+
+ this.state = {
+ open: false,
+ role: ''
+ }
+ }
+
+ 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.status)
+ const { classes, status } = this.props
+ return (
+
+
+ Status Details
+
+
+
+
+
+
+ Member Status Details
+
+ {status !== null && status.map(stat => {
+ return (
+
+ {stat.status} | {stat.reason} | {stat.createdAt}
+
+ )
+ })}
+
+
+ Close
+
+
+
+
+
+
+
+ )
+ }
+}
+
+ManageMemberStatus.propTypes = {
+ classes: PropTypes.object.isRequired,
+ status: PropTypes.array
+}
+
+export default withStyles(styles)(ManageMemberStatus)
diff --git a/client/src/views/dashboard/components/ManageMembersItem.js b/client/src/views/dashboard/components/ManageMembersItem.js
new file mode 100644
index 000000000..cb9b8bdbd
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageMembersItem.js
@@ -0,0 +1,64 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import Grid from '@material-ui/core/Grid'
+import Typography from '@material-ui/core/Typography'
+
+import ManageMemberDelete from './ManageMemberDelete'
+import ManageMemberRole from './ManageMemberRole'
+import ManageMemberStatus from './ManageMemberStatus'
+import { MessageCard } from '@advancedalgos/web-components'
+
+export const ManageMembersItem = ({ classes, member, teamId, authId }) => {
+ console.log('ManageMembersItem', member)
+ let profile = null
+ let email = null
+ let memberStatus = null
+ if (member.member !== null) {
+ profile = member.member
+ }
+ if (member.member === null && member.email !== null) {
+ email = member.email
+ }
+ if (member.status.length > 0) memberStatus = member.status
+ if (profile !== null || email !== null) {
+ return (
+
+
+
+ {profile !== null ? profile.alias : email}
+
+
+
+
+ {email !== null ? `${memberStatus[memberStatus.length - 1].status} | Sent: ${memberStatus[memberStatus.length - 1].createdAt}` : `${member.role} | Member since: `}
+
+
+
+ { profile !== null && member.role !== 'OWNER' && (
+
+ )}
+ {(email !== null || member.role !== 'OWNER') && (
+
+ )}
+ {(email !== null || member.role !== 'OWNER') && (
+
+ )}
+
+
+ )
+ } else {
+ return (
+
+ )
+ }
+}
+
+ManageMembersItem.propTypes = {
+ classes: PropTypes.object.isRequired,
+ member: PropTypes.object.isRequired,
+ teamId: PropTypes.string.isRequired,
+ authId: PropTypes.string.isRequired
+}
+
+export default ManageMembersItem
diff --git a/client/src/views/dashboard/components/ManageMembersTeamItem.js b/client/src/views/dashboard/components/ManageMembersTeamItem.js
new file mode 100644
index 000000000..068d06904
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageMembersTeamItem.js
@@ -0,0 +1,116 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { withStyles } from '@material-ui/core/styles'
+
+import Grid from '@material-ui/core/Grid'
+import Card from '@material-ui/core/Card'
+import CardContent from '@material-ui/core/CardContent'
+import CardMedia from '@material-ui/core/CardMedia'
+import Typography from '@material-ui/core/Typography'
+
+import InviteMemberDialog from './InviteMemberDialog'
+import ManageMembersItem from './ManageMembersItem'
+import { MessageCard } from '@advancedalgos/web-components'
+
+const styles = theme => ({
+ heroContent: {
+ maxWidth: 600,
+ margin: '0 auto',
+ padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
+ },
+ cardGrid: {
+ padding: `${theme.spacing.unit * 8}px 0`
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ },
+ card: {
+ display: 'flex',
+ width: '100%'
+ },
+ cardDetails: {
+ display: 'flex',
+ flex: 1
+ },
+ cardContent: {
+ flex: 1
+ },
+ cardMedia: {
+ flex: 1,
+ width: 100,
+ height: 100,
+ maxWidth: 100,
+ justifyContent: 'flex-start'
+ },
+ cardMemberMedia: {
+ flex: 1,
+ width: 36,
+ height: 36,
+ maxWidth: 36,
+ justifyContent: 'flex-start'
+ },
+ memberContainer: {
+ margin: 10,
+ padding: 6
+ }
+})
+
+export const ManageMembersTeamItem = ({ classes, team, authId }) => {
+ console.log('ManageMembersItem', team, team.profile, team.profile.avatar)
+ let avatar
+ if (team.profile.avatar !== undefined && team.profile.avatar !== 'a') {
+ avatar = team.profile.avatar
+ } else {
+ avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
+ }
+ if (team.members.length > 0) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {team.name}
+
+
+
+
+
+
+ {team.members.length > 0 && team.members.map((member, index) => (
+
+ ))}
+
+
+
+
+
+ )
+ } else {
+ return
+ }
+}
+
+ManageMembersTeamItem.propTypes = {
+ classes: PropTypes.object.isRequired,
+ team: PropTypes.object.isRequired,
+ authId: PropTypes.string.isRequired
+}
+
+export default withStyles(styles)(ManageMembersTeamItem)
diff --git a/client/src/views/dashboard/components/ManageTeamDelete.js b/client/src/views/dashboard/components/ManageTeamDelete.js
index 9f88ba9a3..95a80a883 100644
--- a/client/src/views/dashboard/components/ManageTeamDelete.js
+++ b/client/src/views/dashboard/components/ManageTeamDelete.js
@@ -123,8 +123,7 @@ export class ManageTeamDelete extends Component {
this.handleSubmit(
e,
deleteTeam,
- this.props.slug,
- authId
+ this.props.slug
)
}}
color='primary'
@@ -141,9 +140,9 @@ export class ManageTeamDelete extends Component {
)
}
- async handleSubmit (e, deleteTeam, slug, authId) {
+ async handleSubmit (e, deleteTeam, slug) {
e.preventDefault()
- await deleteTeam({ variables: { slug, owner: authId } })
+ await deleteTeam({ variables: { slug } })
this.setState({ open: false })
}
}
diff --git a/client/src/views/dashboard/components/ManageTeamDetails.js b/client/src/views/dashboard/components/ManageTeamDetails.js
index 33eac05ed..dd1eb10f5 100644
--- a/client/src/views/dashboard/components/ManageTeamDetails.js
+++ b/client/src/views/dashboard/components/ManageTeamDetails.js
@@ -67,15 +67,15 @@ export class ManageTeamDetails extends Component {
const { name, members, profile, createdAt } = this.props.team
let avatar
let banner
- if (profile.avatar !== undefined && profile.avatar !== 'a') {
+ if (profile.avatar !== undefined && profile.avatar !== null) {
avatar = 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%3EAvatar%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
+ avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
}
- if (profile.banner !== undefined && profile.banner !== 'a') {
+ if (profile.banner !== undefined && profile.banner !== null) {
banner = profile.banner
} else {
- banner = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22200%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Asvg%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23banner_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%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%3E%3Ctitle%3EBanner%20Placeholder%3C%2Ftitle%3E%3Crect%20stroke%3D%22null%22%20id%3D%22svg_1%22%20fill%3D%22%2355595c%22%20height%3D%22200%22%20width%3D%22800%22%2F%3E%3Cg%20stroke%3D%22null%22%20id%3D%22banner_164edaf95ee%22%3E%3Ctext%20stroke%3D%22null%22%20id%3D%22svg_3%22%20y%3D%22106.5%22%20x%3D%22367.73438%22%3EBanner%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E'
+ banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
}
return (
diff --git a/client/src/views/dashboard/components/ManageTeamEdit.js b/client/src/views/dashboard/components/ManageTeamEdit.js
index 900dfa62f..d37a27804 100644
--- a/client/src/views/dashboard/components/ManageTeamEdit.js
+++ b/client/src/views/dashboard/components/ManageTeamEdit.js
@@ -127,10 +127,11 @@ export class ManageTeamEdit extends Component {
let avatar = null
if (this.state.avatar !== null) avatar = this.state.avatar
if (team.profile !== null && team.profile.avatar !== undefined && team.profile.avatar !== null) avatar = team.profile.avatar
-
+ if (this.state.avatar === null && team.profile !== null && team.profile.avatar === undefined) avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
let banner = null
if (this.state.banner !== null) banner = this.state.banner
if (team.profile !== null && team.profile.banner !== undefined && team.profile.banner !== null) banner = team.profile.banner
+ if (this.state.banner === null && team.profile !== null && team.profile.banner === undefined) banner = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-banner-default.png'
console.log('team images: ', avatar, banner)
if (loading || data === undefined) {
diff --git a/client/src/views/dashboard/components/ManageTeamMembersList.js b/client/src/views/dashboard/components/ManageTeamMembersList.js
new file mode 100644
index 000000000..f8d6a2eb1
--- /dev/null
+++ b/client/src/views/dashboard/components/ManageTeamMembersList.js
@@ -0,0 +1,142 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Query } from 'react-apollo'
+import { withStateHandlers, lifecycle, compose } from 'recompose'
+
+import Grid from '@material-ui/core/Grid'
+import { withStyles } from '@material-ui/core/styles'
+
+import { isDefined, isString } from '../../../utils/js-helpers'
+import { getItem } from '../../../utils/local-storage'
+
+import GET_TEAMS_BY_OWNER from '../../../graphql/teams/GetTeamsByOwnerQuery'
+
+import ManageMembersTeamItem from './ManageMembersTeamItem'
+import { MessageCard } from '@advancedalgos/web-components'
+
+const styles = theme => ({
+ heroContent: {
+ maxWidth: 600,
+ margin: '0 auto',
+ padding: `${theme.spacing.unit * 8}px 0 ${theme.spacing.unit * 6}px`
+ },
+ cardGrid: {
+ padding: `${theme.spacing.unit * 8}px 0`
+ },
+ buttonRight: {
+ justifyContent: 'flex-end'
+ },
+ card: {
+ display: 'flex',
+ width: '100%'
+ },
+ cardDetails: {
+ display: 'flex',
+ flex: 1
+ },
+ cardContent: {
+ flex: 1
+ },
+ cardMedia: {
+ flex: 1,
+ width: 100,
+ height: 100,
+ maxWidth: 100,
+ justifyContent: 'flex-start'
+ }
+})
+
+export const ManageTeamMembersList = ({ classes, user = null }) => {
+ let owner
+ let authId = null
+ console.log('ManageTeamsList: ', user)
+ if (user !== null && isString(user)) {
+ owner = JSON.parse(user)
+ if (isDefined(owner.authId)) authId = owner.authId
+ }
+ console.log('ManageTeamsList 2: ', owner, authId)
+ if (authId === undefined || authId === null) {
+ return (
+
+
+
+
+
+ )
+ } else {
+ return (
+
+ {({ loading, error, data }) => {
+ console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
+ let errors = null
+ if (error) {
+ errors = error.graphQLErrors.map(({ message }, i) => {
+ return
+ })
+ }
+ if (!loading && !error) {
+ if (data.teamsByOwner.length > 0) {
+ return (
+
+
+ {!loading &&
+ data.teamsByOwner.map(team => (
+
+ ))
+ }
+ {errors}
+
+
+ )
+ } else {
+ return (
+
+
+
+
+
+ )
+ }
+ } else {
+ return (
+
+
+
+ {errors !== null && }
+
+
+ )
+ }
+ }}
+
+ )
+ }
+}
+
+ManageTeamMembersList.propTypes = {
+ user: PropTypes.any,
+ classes: PropTypes.object.isRequired
+}
+
+const getUserOnMount = lifecycle({
+ componentDidMount () {
+ getItem('user').then(user => {
+ this.setState({ user })
+ }) // Set user to state
+ }
+})
+
+const mapStateToProps = withStateHandlers(() => ({ user: null }), {
+ user: ({ user }) => () => ({ user })
+})
+
+const ManageTeamMembersListAuthId = compose(
+ mapStateToProps,
+ getUserOnMount
+)(ManageTeamMembersList)
+
+export default withStyles(styles)(ManageTeamMembersListAuthId)
diff --git a/client/src/views/dashboard/components/ManageTeamsItem.js b/client/src/views/dashboard/components/ManageTeamsItem.js
index 270d3a57a..47aca6eff 100644
--- a/client/src/views/dashboard/components/ManageTeamsItem.js
+++ b/client/src/views/dashboard/components/ManageTeamsItem.js
@@ -18,7 +18,7 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
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://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
}
return (
@@ -39,7 +39,7 @@ export const ManageTeamsItem = ({ classes, team, authId }) => {
-
+
diff --git a/client/src/views/dashboard/components/ManageTeamsList.js b/client/src/views/dashboard/components/ManageTeamsList.js
index 816a4db88..db69248b4 100644
--- a/client/src/views/dashboard/components/ManageTeamsList.js
+++ b/client/src/views/dashboard/components/ManageTeamsList.js
@@ -68,8 +68,8 @@ export const ManageTeamsList = ({ classes, user = null }) => {
return (
{({ loading, error, data }) => {
console.log('GET_TEAMS_BY_OWNER: ', loading, error, data)
@@ -94,9 +94,6 @@ export const ManageTeamsList = ({ classes, user = null }) => {
authId={authId}
/>
))}
-
-
-
{errors}
diff --git a/client/src/views/index.js b/client/src/views/index.js
index 195ec74ff..30ab09b90 100644
--- a/client/src/views/index.js
+++ b/client/src/views/index.js
@@ -5,6 +5,7 @@ import Home from './home'
import About from './about'
import Dashboard from './dashboard'
import Teams from './teams'
+import AcceptTeamInvite from './teams/AcceptTeamInvite'
import { theme, globalStyles } from './theme'
@@ -12,6 +13,7 @@ export {
NavBar,
Footer,
Callback,
+ AcceptTeamInvite,
Home,
About,
Dashboard,
diff --git a/client/src/views/teams/AcceptTeamInvite.js b/client/src/views/teams/AcceptTeamInvite.js
new file mode 100644
index 000000000..b2ac3ece5
--- /dev/null
+++ b/client/src/views/teams/AcceptTeamInvite.js
@@ -0,0 +1,31 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+import queryString from 'query-string'
+
+import { MessageCard } from '@advancedalgos/web-components'
+
+class AcceptTeamInvite extends Component {
+ render () {
+ const { location, auth } = this.props
+ const param = queryString.parse(location.search)
+ console.log(param, auth)
+
+ if (auth === undefined) {
+ return
+ }
+
+ auth.loginInvite(param.token)
+
+ return (
+
+ )
+ }
+}
+
+AcceptTeamInvite.propTypes = {
+ location: PropTypes.object.isRequired,
+ auth: PropTypes.object
+}
+
+export default AcceptTeamInvite
diff --git a/client/tools/webpack/webpack.prod.config.js b/client/tools/webpack/webpack.prod.config.js
index 14724d7ad..b5810a748 100644
--- a/client/tools/webpack/webpack.prod.config.js
+++ b/client/tools/webpack/webpack.prod.config.js
@@ -12,6 +12,7 @@ const Dotenv = require('dotenv-webpack')
module.exports = merge(commonConfig, {
mode: 'production',
+ devtool: 'inline-sourcemap',
output: {
path: path.resolve(__dirname, '../../build'),
filename: 'script.js'