diff --git a/design/Deighton AR Design.sketch b/design/Deighton AR Design.sketch index b669cee..685e011 100644 Binary files a/design/Deighton AR Design.sketch and b/design/Deighton AR Design.sketch differ diff --git a/mobile/src/ui/Icon.js b/mobile/src/ui/Icon.js index 4771f84..64f2adc 100644 --- a/mobile/src/ui/Icon.js +++ b/mobile/src/ui/Icon.js @@ -16,6 +16,9 @@ const images = { done: require("./images/done.png"), target: require("./images/target.png"), pin: require("./images/pin.png"), + hardhat: require("./images/hardhat.png"), + clipboard: require("./images/clipboard.png"), + question: require("./images/question.png"), } export class Icon extends Component { diff --git a/mobile/src/ui/images/clipboard.png b/mobile/src/ui/images/clipboard.png new file mode 100644 index 0000000..ae94ee7 Binary files /dev/null and b/mobile/src/ui/images/clipboard.png differ diff --git a/mobile/src/ui/images/hardhat.png b/mobile/src/ui/images/hardhat.png new file mode 100644 index 0000000..b9f20b9 Binary files /dev/null and b/mobile/src/ui/images/hardhat.png differ diff --git a/mobile/src/ui/images/question.png b/mobile/src/ui/images/question.png new file mode 100644 index 0000000..b7f20dc Binary files /dev/null and b/mobile/src/ui/images/question.png differ diff --git a/website/src/Teams/Teams.js b/website/src/Teams/Teams.js index 17c36c8..13be65b 100644 --- a/website/src/Teams/Teams.js +++ b/website/src/Teams/Teams.js @@ -1,13 +1,18 @@ -import React, { Component, Fragment } from 'react' -import PropTypes from 'prop-types' -import autobind from 'autobind-decorator' -import { TeamList } from './TeamList' -import { TeamForm } from './TeamForm' -import { TeamFormPlaceholder } from './TeamFormPlaceholder' -import { api } from 'src/API' -import { Row, Column, Box } from 'ui' -import { YesNoMessageModal, MessageModal, ChangeEmailModal, WaitModal } from '../Modal' -import { sizeInfo, colorInfo } from 'ui/style' +import React, { Component, Fragment } from "react" +import PropTypes from "prop-types" +import autobind from "autobind-decorator" +import { TeamList } from "./TeamList" +import { TeamForm } from "./TeamForm" +import { TeamFormPlaceholder } from "./TeamFormPlaceholder" +import { api } from "src/API" +import { Row, Column, Box } from "ui" +import { + YesNoMessageModal, + MessageModal, + ChangeEmailModal, + WaitModal, +} from "../Modal" +import { sizeInfo, colorInfo } from "ui/style" export class Teams extends Component { static propTypes = { @@ -28,24 +33,27 @@ export class Teams extends Component { } componentDidMount() { - this.props.changeTitle('Teams') + this.props.changeTitle("Teams") - api.listTeams().then((list) => { - list.items.sort((teamA, teamB) => (teamA.name.localeCompare(teamB.name))) - this.setState({ teams: list.items }) - }).catch((error) => { - this.setState({ - messageModal: { - icon: 'hand', - message: 'Unable to get the list of teams.', - detail: error.message, - } + api + .listTeams() + .then((list) => { + list.items.sort((teamA, teamB) => teamA.name.localeCompare(teamB.name)) + this.setState({ teams: list.items }) + }) + .catch((error) => { + this.setState({ + messageModal: { + icon: "hand", + message: "Unable to get the list of teams.", + detail: error.message, + }, + }) }) - }) } componentWillUnmount() { - this.props.changeTitle('') + this.props.changeTitle("") } removeUnfinishedNewTeam() { @@ -64,9 +72,10 @@ export class Teams extends Component { this.nextSelectedTeam = team this.setState({ yesNoModal: { - question: 'This team has been modified. Are you sure you would like to navigate away?', - onDismiss: this.handleModifiedModalDismiss - } + question: + "This team has been modified. Are you sure you would like to navigate away?", + onDismiss: this.handleModifiedModalDismiss, + }, }) } else { this.setState({ selectedTeam: team }) @@ -77,77 +86,92 @@ export class Teams extends Component { @autobind handleSave(team) { if (team._id) { - this.setState({ waitModal: { message: 'Updating Team' } }) - api.updateTeam(team).then((updatedTeam) => { - this.setState({ - waitModal: null, - teams: this.state.teams.map((team) => (team._id === updatedTeam._id ? updatedTeam : team)), - modified: false, - selectedTeam: updatedTeam + this.setState({ waitModal: { message: "Updating Team" } }) + api + .updateTeam(team) + .then((updatedTeam) => { + this.setState({ + waitModal: null, + teams: this.state.teams.map( + (team) => (team._id === updatedTeam._id ? updatedTeam : team) + ), + modified: false, + selectedTeam: updatedTeam, + }) }) - }).catch((error) => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to save the team changes', - detail: error.message, - } + .catch((error) => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to save the team changes", + detail: error.message, + }, + }) }) - }) } else { - this.setState({ waitModal: { message: 'Creating Team' } }) - api.createTeam(team).then((createdTeam) => { - this.setState({ - waitModal: false, - teams: this.state.teams.map((team) => (!team._id ? createdTeam : team)).sort((a, b) => ( - a.name < b.name ? -1 : a.name > b.name ? 1 : 0 - )), - modified: false, - selectedTeam: createdTeam + this.setState({ waitModal: { message: "Creating Team" } }) + api + .createTeam(team) + .then((createdTeam) => { + this.setState({ + waitModal: false, + teams: this.state.teams + .map((team) => (!team._id ? createdTeam : team)) + .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)), + modified: false, + selectedTeam: createdTeam, + }) }) - }).catch((error) => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to create the team.', - detail: error.message, - } + .catch((error) => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to create the team.", + detail: error.message, + }, + }) }) - }) } } @autobind handleChangeEmail() { - this.setState({ changeEmailModal: { oldEmail: this.state.selectedTeam.email } }) + this.setState({ + changeEmailModal: { oldEmail: this.state.selectedTeam.email }, + }) } @autobind handleResendEmail() { this.setState({ - waitModal: { message: 'Resending Email...' } + waitModal: { message: "Resending Email..." }, }) - api.sendConfirmEmail({ existingEmail: this.state.selectedTeam.email }).then(() => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'thumb', - message: `An email has been sent to '${this.state.selectedTeam.email}' with further instructions.` - } + api + .sendConfirmEmail({ existingEmail: this.state.selectedTeam.email }) + .then(() => { + this.setState({ + waitModal: null, + messageModal: { + icon: "thumb", + message: `An email has been sent to '${ + this.state.selectedTeam.email + }' with further instructions.`, + }, + }) }) - }).catch((error) => { - this.setState({ - error: true, - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to request email change.', - detail: error.message, - } + .catch((error) => { + this.setState({ + error: true, + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to request email change.", + detail: error.message, + }, + }) }) - }) } @autobind @@ -157,28 +181,34 @@ export class Teams extends Component { return } this.setState({ - waitModal: { message: 'Requesting Email Change...' } + waitModal: { message: "Requesting Email Change..." }, }) if (this.state.selectedTeam) { - api.sendConfirmEmail({ existingEmail: this.state.selectedTeam.email, newEmail }).then(() => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: `An email has been sent to '${newEmail}' to confirm this email.` - } + api + .sendConfirmEmail({ + existingEmail: this.state.selectedTeam.email, + newEmail, }) - }).catch((error) => { - this.setState({ - error: true, - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to request email change.', - detail: error.message, - } + .then(() => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: `An email has been sent to '${newEmail}' to confirm this email.`, + }, + }) + }) + .catch((error) => { + this.setState({ + error: true, + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to request email change.", + detail: error.message, + }, + }) }) - }) } } @@ -186,9 +216,10 @@ export class Teams extends Component { handleRemove() { this.setState({ yesNoModal: { - question: 'Are you sure you want to remove this team? This will also remove them from any teams they belong to.', - onDismiss: this.handleRemoveModalDismiss - } + question: + "Are you sure you want to remove this team? This will also remove them from any teams they belong to.", + onDismiss: this.handleRemoveModalDismiss, + }, }) } @@ -196,31 +227,39 @@ export class Teams extends Component { handleRemoveModalDismiss(yes) { if (yes) { const selectedTeamId = this.state.selectedTeam._id - const selectedIndex = this.state.teams.findIndex((team) => (team._id === selectedTeamId)) + const selectedIndex = this.state.teams.findIndex( + (team) => team._id === selectedTeamId + ) if (selectedIndex >= 0) { - this.setState({ waitModal: { message: 'Removing Team' } }) - api.deleteTeam(selectedTeamId).then(() => { - this.setState({ - waitModal: null, - teams: [...this.state.teams.slice(0, selectedIndex), ...this.state.teams.slice(selectedIndex + 1)], - selectedTeam: null + this.setState({ waitModal: { message: "Removing Team" } }) + api + .deleteTeam(selectedTeamId) + .then(() => { + this.setState({ + waitModal: null, + teams: [ + ...this.state.teams.slice(0, selectedIndex), + ...this.state.teams.slice(selectedIndex + 1), + ], + selectedTeam: null, + }) }) - }).catch((error) => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to remove the team.', - detail: error.message, - } + .catch((error) => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to remove the team.", + detail: error.message, + }, + }) }) - }) } } this.setState({ - yesNoModal: null + yesNoModal: null, }) } @@ -229,14 +268,14 @@ export class Teams extends Component { if (yes) { this.setState({ selectedTeam: this.nextSelectedTeam, - modified: false + modified: false, }) this.removeUnfinishedNewTeam() delete this.nextSelectedTeam } this.setState({ - yesNoModal: null + yesNoModal: null, }) } @@ -252,9 +291,13 @@ export class Teams extends Component { @autobind handleAddNewTeam() { - let newTeam = {} - let newTeams = [newTeam].concat(this.state.teams) - this.setState({ teams: newTeams, selectedTeam: newTeam }) + let teams = this.state.teams + + if (teams.length > 0 && !!teams[0]._id) { + let newTeam = {} + let newTeams = [newTeam].concat(this.state.teams) + this.setState({ teams: newTeams, selectedTeam: newTeam }) + } } render() { @@ -266,43 +309,65 @@ export class Teams extends Component { - - + + - - { - this.state.selectedTeam - ? - : - } + + {this.state.selectedTeam ? ( + + ) : ( + + )} - + onDismiss={this.handleChangeEmailDismiss} + /> - + + onDismiss={this.handleMessageModalDismiss} + /> - + ) diff --git a/website/src/Users/Users.js b/website/src/Users/Users.js index 04e8022..2181b70 100644 --- a/website/src/Users/Users.js +++ b/website/src/Users/Users.js @@ -1,13 +1,18 @@ -import React, { Component, Fragment } from 'react' -import PropTypes from 'prop-types' -import autobind from 'autobind-decorator' -import { UserList } from './UserList' -import { UserForm } from './UserForm' -import { UserFormPlaceholder } from './UserFormPlaceholder' -import { api } from 'src/API' -import { Row, Column, Box } from 'ui' -import { YesNoMessageModal, MessageModal, ChangeEmailModal, WaitModal } from '../Modal' -import { sizeInfo, colorInfo } from 'ui/style' +import React, { Component, Fragment } from "react" +import PropTypes from "prop-types" +import autobind from "autobind-decorator" +import { UserList } from "./UserList" +import { UserForm } from "./UserForm" +import { UserFormPlaceholder } from "./UserFormPlaceholder" +import { api } from "src/API" +import { Row, Column, Box } from "ui" +import { + YesNoMessageModal, + MessageModal, + ChangeEmailModal, + WaitModal, +} from "../Modal" +import { sizeInfo, colorInfo } from "ui/style" export class Users extends Component { static propTypes = { @@ -28,24 +33,29 @@ export class Users extends Component { } componentDidMount() { - this.props.changeTitle('Users') + this.props.changeTitle("Users") - api.listUsers().then((list) => { - list.items.sort((userA, userB) => (userA.lastName.localeCompare(userB.lastName))) - this.setState({ users: list.items }) - }).catch((error) => { - this.setState({ - messageModal: { - icon: 'hand', - message: 'Unable to get the list of users.', - detail: error.message, - } + api + .listUsers() + .then((list) => { + list.items.sort((userA, userB) => + userA.lastName.localeCompare(userB.lastName) + ) + this.setState({ users: list.items }) + }) + .catch((error) => { + this.setState({ + messageModal: { + icon: "hand", + message: "Unable to get the list of users.", + detail: error.message, + }, + }) }) - }) } componentWillUnmount() { - this.props.changeTitle('') + this.props.changeTitle("") } removeUnfinishedNewUser() { @@ -64,9 +74,10 @@ export class Users extends Component { this.nextSelectedUser = user this.setState({ yesNoModal: { - question: 'This user has been modified. Are you sure you would like to navigate away?', - onDismiss: this.handleModifiedModalDismiss - } + question: + "This user has been modified. Are you sure you would like to navigate away?", + onDismiss: this.handleModifiedModalDismiss, + }, }) } else { this.setState({ selectedUser: user }) @@ -77,77 +88,95 @@ export class Users extends Component { @autobind handleSave(user) { if (user._id) { - this.setState({ waitModal: { message: 'Updating User' } }) - api.updateUser(user).then((updatedUser) => { - this.setState({ - waitModal: null, - users: this.state.users.map((user) => (user._id === updatedUser._id ? updatedUser : user)), - modified: false, - selectedUser: updatedUser + this.setState({ waitModal: { message: "Updating User" } }) + api + .updateUser(user) + .then((updatedUser) => { + this.setState({ + waitModal: null, + users: this.state.users.map( + (user) => (user._id === updatedUser._id ? updatedUser : user) + ), + modified: false, + selectedUser: updatedUser, + }) }) - }).catch((error) => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to save the user changes', - detail: error.message, - } + .catch((error) => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to save the user changes", + detail: error.message, + }, + }) }) - }) } else { - this.setState({ waitModal: { message: 'Creating User' } }) - api.createUser(user).then((createdUser) => { - this.setState({ - waitModal: false, - users: this.state.users.map((user) => (!user._id ? createdUser : user)).sort((a, b) => ( - a.lastName < b.lastName ? -1 : a.lastName > b.lastName : 0 - )), - modified: false, - selectedUser: createdUser + this.setState({ waitModal: { message: "Creating User" } }) + api + .createUser(user) + .then((createdUser) => { + this.setState({ + waitModal: false, + users: this.state.users + .map((user) => (!user._id ? createdUser : user)) + .sort( + (a, b) => + ((a.lastName < b.lastName ? -1 : a.lastName > b.lastName): 0) + ), + modified: false, + selectedUser: createdUser, + }) }) - }).catch((error) => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to create the user.', - detail: error.message, - } + .catch((error) => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to create the user.", + detail: error.message, + }, + }) }) - }) } } @autobind handleChangeEmail() { - this.setState({ changeEmailModal: { oldEmail: this.state.selectedUser.email } }) + this.setState({ + changeEmailModal: { oldEmail: this.state.selectedUser.email }, + }) } @autobind handleResendEmail() { this.setState({ - waitModal: { message: 'Resending Email...' } + waitModal: { message: "Resending Email..." }, }) - api.sendConfirmEmail({ existingEmail: this.state.selectedUser.email }).then(() => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'thumb', - message: `An email has been sent to '${this.state.selectedUser.email}' with further instructions.` - } + api + .sendConfirmEmail({ existingEmail: this.state.selectedUser.email }) + .then(() => { + this.setState({ + waitModal: null, + messageModal: { + icon: "thumb", + message: `An email has been sent to '${ + this.state.selectedUser.email + }' with further instructions.`, + }, + }) }) - }).catch((error) => { - this.setState({ - error: true, - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to request email change.', - detail: error.message, - } + .catch((error) => { + this.setState({ + error: true, + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to request email change.", + detail: error.message, + }, + }) }) - }) } @autobind @@ -157,28 +186,34 @@ export class Users extends Component { return } this.setState({ - waitModal: { message: 'Requesting Email Change...' } + waitModal: { message: "Requesting Email Change..." }, }) if (this.state.selectedUser) { - api.sendConfirmEmail({ existingEmail: this.state.selectedUser.email, newEmail }).then(() => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: `An email has been sent to '${newEmail}' to confirm this email.` - } + api + .sendConfirmEmail({ + existingEmail: this.state.selectedUser.email, + newEmail, }) - }).catch((error) => { - this.setState({ - error: true, - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to request email change.', - detail: error.message, - } + .then(() => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: `An email has been sent to '${newEmail}' to confirm this email.`, + }, + }) + }) + .catch((error) => { + this.setState({ + error: true, + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to request email change.", + detail: error.message, + }, + }) }) - }) } } @@ -186,9 +221,10 @@ export class Users extends Component { handleRemove() { this.setState({ yesNoModal: { - question: 'Are you sure you want to remove this user? This will also remove them from any teams they belong to.', - onDismiss: this.handleRemoveModalDismiss - } + question: + "Are you sure you want to remove this user? This will also remove them from any teams they belong to.", + onDismiss: this.handleRemoveModalDismiss, + }, }) } @@ -196,31 +232,39 @@ export class Users extends Component { handleRemoveModalDismiss(yes) { if (yes) { const selectedUserId = this.state.selectedUser._id - const selectedIndex = this.state.users.findIndex((user) => (user._id === selectedUserId)) + const selectedIndex = this.state.users.findIndex( + (user) => user._id === selectedUserId + ) if (selectedIndex >= 0) { - this.setState({ waitModal: { message: 'Removing User' } }) - api.deleteUser(selectedUserId).then(() => { - this.setState({ - waitModal: null, - users: [...this.state.users.slice(0, selectedIndex), ...this.state.users.slice(selectedIndex + 1)], - selectedUser: null + this.setState({ waitModal: { message: "Removing User" } }) + api + .deleteUser(selectedUserId) + .then(() => { + this.setState({ + waitModal: null, + users: [ + ...this.state.users.slice(0, selectedIndex), + ...this.state.users.slice(selectedIndex + 1), + ], + selectedUser: null, + }) }) - }).catch((error) => { - this.setState({ - waitModal: null, - messageModal: { - icon: 'hand', - message: 'Unable to remove the user.', - detail: error.message, - } + .catch((error) => { + this.setState({ + waitModal: null, + messageModal: { + icon: "hand", + message: "Unable to remove the user.", + detail: error.message, + }, + }) }) - }) } } this.setState({ - yesNoModal: null + yesNoModal: null, }) } @@ -229,14 +273,14 @@ export class Users extends Component { if (yes) { this.setState({ selectedUser: this.nextSelectedUser, - modified: false + modified: false, }) this.removeUnfinishedNewUser() delete this.nextSelectedUser } this.setState({ - yesNoModal: null + yesNoModal: null, }) } @@ -252,9 +296,13 @@ export class Users extends Component { @autobind handleAddNewUser() { - let newUser = {} - let newUsers = [newUser].concat(this.state.users) - this.setState({ users: newUsers, selectedUser: newUser }) + let users = this.state.users + + if (users.length > 0 && !!users[0]._id) { + let newUser = {} + let newUsers = [newUser].concat(users) + this.setState({ users: newUsers, selectedUser: newUser }) + } } render() { @@ -266,43 +314,65 @@ export class Users extends Component { - - + + - - { - this.state.selectedUser - ? - : - } + + {this.state.selectedUser ? ( + + ) : ( + + )} - + onDismiss={this.handleChangeEmailDismiss} + /> - + + onDismiss={this.handleMessageModalDismiss} + /> - + )