From 80bd1f102eb39c7ec026af4fa14992b0986fa443 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Tue, 2 May 2017 14:23:09 +0200 Subject: [PATCH 01/11] list users --- src/components/menu-sidebar.js | 1 + src/containers/users.js | 136 ++++++++++++++++++++++++ src/data-managers/users-data-manager.js | 14 +++ src/router.js | 3 + src/stores/user-store.js | 14 +++ 5 files changed, 168 insertions(+) create mode 100644 src/containers/users.js diff --git a/src/components/menu-sidebar.js b/src/components/menu-sidebar.js index 120065d..1782304 100644 --- a/src/components/menu-sidebar.js +++ b/src/components/menu-sidebar.js @@ -33,6 +33,7 @@ class SidebarMenu extends Component {
  • Projects
  • Simulations
  • Simulators
  • +
  • User Management
  • Logout
  • diff --git a/src/containers/users.js b/src/containers/users.js new file mode 100644 index 0000000..531f112 --- /dev/null +++ b/src/containers/users.js @@ -0,0 +1,136 @@ +/** + * File: users.js + * Author: Ricardo Hernandez-Montoya + * Date: 02.05.2017 + * + * This file is part of VILLASweb. + * + * VILLASweb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VILLASweb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VILLASweb. If not, see . + ******************************************************************************/ + +import React, { Component } from 'react'; +import { Container } from 'flux/utils'; +import { Button, Modal, Glyphicon } from 'react-bootstrap'; + +import AppDispatcher from '../app-dispatcher'; +import UserStore from '../stores/user-store'; + +import Table from '../components/table'; +import TableColumn from '../components/table-column'; +import NewProjectDialog from '../components/dialog/new-project'; +import EditProjectDialog from '../components/dialog/edit-project'; + +class Projects extends Component { + static getStores() { + return [ UserStore ]; + } + + static calculateState() { + return { + users: UserStore.getState().users, + + newModal: false, + editModal: false, + deleteModal: false, + modalData: {} + }; + } + + componentWillMount() { + AppDispatcher.dispatch({ + type: 'users/start-load' + }); + } + + // closeNewModal(data) { + // this.setState({ newModal: false }); + + // if (data) { + // AppDispatcher.dispatch({ + // type: 'projects/start-add', + // data: data + // }); + // } + // } + + // confirmDeleteModal() { + // this.setState({ deleteModal: false }); + + // AppDispatcher.dispatch({ + // type: 'projects/start-remove', + // data: this.state.modalData + // }); + // } + + // closeEditModal(data) { + // this.setState({ editModal: false }); + + // if (data) { + // AppDispatcher.dispatch({ + // type: 'projects/start-edit', + // data: data + // }); + // } + // } + + // getSimulationName(id) { + // for (var i = 0; i < this.state.simulations.length; i++) { + // if (this.state.simulations[i]._id === id) { + // return this.state.simulations[i].name; + // } + // } + + // return id; + // } + + render() { + + this.state.users.map( (user) => console.log('User: %o', user)); + + return ( +
    +

    Users

    + + + + + this.setState({ editModal: true, modalData: this.state.users[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.users[index] })} /> +
    + + {/* + + this.closeNewModal(data)} simulations={this.state.simulations} /> + + this.closeEditModal(data)} project={this.state.modalData} simulations={this.state.simulations} /> + + + + Delete Project + + + + Are you sure you want to delete the project '{this.state.modalData.name}'? + + + + + + + */} +
    + ); + } +} + +export default Container.create(Projects); diff --git a/src/data-managers/users-data-manager.js b/src/data-managers/users-data-manager.js index 711c68d..08c3138 100644 --- a/src/data-managers/users-data-manager.js +++ b/src/data-managers/users-data-manager.js @@ -55,6 +55,20 @@ class UsersDataManager extends RestDataManager { }); }); } + + getUsers(token) { + RestAPI.get(this.makeURL('/users'), token).then(response => { + AppDispatcher.dispatch({ + type: 'users/users-loaded', + users: response.users + }); + }).catch(error => { + AppDispatcher.dispatch({ + type: 'users/users-load-error', + error: error + }); + }); + } } export default new UsersDataManager(); diff --git a/src/router.js b/src/router.js index a74a7eb..85bbe78 100644 --- a/src/router.js +++ b/src/router.js @@ -30,6 +30,7 @@ import Simulators from './containers/simulators'; import Visualization from './containers/visualization'; import Simulations from './containers/simulations'; import Simulation from './containers/simulation'; +import Users from './containers/users'; import Login from './containers/login'; import Logout from './containers/logout'; @@ -50,6 +51,8 @@ class Root extends Component { + + diff --git a/src/stores/user-store.js b/src/stores/user-store.js index aeed56f..9acf4d2 100644 --- a/src/stores/user-store.js +++ b/src/stores/user-store.js @@ -80,6 +80,20 @@ class UserStore extends ReduceStore { } return state; + + case 'users/start-load': + console.log('Sending request'); + UsersDataManager.getUsers(state.token); + + return state; + + case 'users/users-loaded': + + return Object.assign({}, state, { users: action.users }); + + case 'users/users-load-error': + // Users couldn't be loaded. Keep same state + return state; default: return state; From 6a4c31baef0570900242468dc42c9d6df45608dc Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Tue, 2 May 2017 16:29:11 +0200 Subject: [PATCH 02/11] List users reusing array-store --- src/containers/users.js | 43 ++++++++++++----------- src/data-managers/users-data-manager.js | 6 ++-- src/stores/user-store.js | 16 +-------- src/stores/users-store.js | 45 +++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 37 deletions(-) create mode 100644 src/stores/users-store.js diff --git a/src/containers/users.js b/src/containers/users.js index 531f112..b8773be 100644 --- a/src/containers/users.js +++ b/src/containers/users.js @@ -25,20 +25,33 @@ import { Button, Modal, Glyphicon } from 'react-bootstrap'; import AppDispatcher from '../app-dispatcher'; import UserStore from '../stores/user-store'; +import UsersStore from '../stores/users-store'; import Table from '../components/table'; import TableColumn from '../components/table-column'; -import NewProjectDialog from '../components/dialog/new-project'; -import EditProjectDialog from '../components/dialog/edit-project'; +// import NewUserDialog from '../components/dialog/new-user'; +// import EditUserDialog from '../components/dialog/edit-user'; -class Projects extends Component { +class Users extends Component { static getStores() { - return [ UserStore ]; + return [ UserStore, UsersStore ]; } - static calculateState() { + static calculateState(prevState, props) { + + let tokenState = UserStore.getState().token; + + // If there is a token available and this method was called as a result of loading users + if (!prevState && tokenState) { + AppDispatcher.dispatch({ + type: 'users/start-load', + token: tokenState + }); + } + return { - users: UserStore.getState().users, + token: tokenState, + users: UsersStore.getState(), newModal: false, editModal: false, @@ -47,18 +60,12 @@ class Projects extends Component { }; } - componentWillMount() { - AppDispatcher.dispatch({ - type: 'users/start-load' - }); - } - // closeNewModal(data) { // this.setState({ newModal: false }); // if (data) { // AppDispatcher.dispatch({ - // type: 'projects/start-add', + // type: 'users/start-add', // data: data // }); // } @@ -95,8 +102,6 @@ class Projects extends Component { // } render() { - - this.state.users.map( (user) => console.log('User: %o', user)); return (
    @@ -108,11 +113,11 @@ class Projects extends Component { this.setState({ editModal: true, modalData: this.state.users[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.users[index] })} /> - {/* + - this.closeNewModal(data)} simulations={this.state.simulations} /> + {/* this.closeNewModal(data)} />*/} - this.closeEditModal(data)} project={this.state.modalData} simulations={this.state.simulations} /> + {/* this.closeEditModal(data)} project={this.state.modalData} simulations={this.state.simulations} /> @@ -133,4 +138,4 @@ class Projects extends Component { } } -export default Container.create(Projects); +export default Container.create(Users); diff --git a/src/data-managers/users-data-manager.js b/src/data-managers/users-data-manager.js index 08c3138..b20c3c2 100644 --- a/src/data-managers/users-data-manager.js +++ b/src/data-managers/users-data-manager.js @@ -59,12 +59,12 @@ class UsersDataManager extends RestDataManager { getUsers(token) { RestAPI.get(this.makeURL('/users'), token).then(response => { AppDispatcher.dispatch({ - type: 'users/users-loaded', - users: response.users + type: 'users/loaded', + data: response.users }); }).catch(error => { AppDispatcher.dispatch({ - type: 'users/users-load-error', + type: 'users/load-error', error: error }); }); diff --git a/src/stores/user-store.js b/src/stores/user-store.js index 9acf4d2..0c3a70a 100644 --- a/src/stores/user-store.js +++ b/src/stores/user-store.js @@ -79,21 +79,7 @@ class UserStore extends ReduceStore { } - return state; - - case 'users/start-load': - console.log('Sending request'); - UsersDataManager.getUsers(state.token); - - return state; - - case 'users/users-loaded': - - return Object.assign({}, state, { users: action.users }); - - case 'users/users-load-error': - // Users couldn't be loaded. Keep same state - return state; + return state; default: return state; diff --git a/src/stores/users-store.js b/src/stores/users-store.js new file mode 100644 index 0000000..3eb1595 --- /dev/null +++ b/src/stores/users-store.js @@ -0,0 +1,45 @@ +/** + * File: users-store.js + * Author: Markus Grigull + * Date: 15.03.2017 + * + * This file is part of VILLASweb. + * + * VILLASweb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VILLASweb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VILLASweb. If not, see . + ******************************************************************************/ + +import ArrayStore from './array-store'; +import UsersDataManager from '../data-managers/users-data-manager'; + +class UsersStore extends ArrayStore { + constructor() { + super('users', UsersDataManager); + } + + reduce(state, action) { + switch (action.type) { + + // Override ArrayStore's start-load to pass token + case 'users/start-load': + UsersDataManager.getUsers(action.token); + return state; + + default: + return super.reduce(state, action); + } + } + +} + +export default new UsersStore(); From 1a54ae09a21183a2fea3ee11ee9f11c9eeabad3e Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Tue, 2 May 2017 17:26:47 +0200 Subject: [PATCH 03/11] Allow optional token inclusion in REST API calls --- src/data-managers/rest-data-manager.js | 18 +++++++++--------- src/data-managers/users-data-manager.js | 15 +-------------- src/stores/array-store.js | 11 ++++++----- src/stores/users-store.js | 5 ----- 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/data-managers/rest-data-manager.js b/src/data-managers/rest-data-manager.js index f4fd82f..99dbd04 100644 --- a/src/data-managers/rest-data-manager.js +++ b/src/data-managers/rest-data-manager.js @@ -51,10 +51,10 @@ class RestDataManager { return object; } - load(id) { + load(id, token = null) { if (id != null) { // load single object - RestAPI.get(this.makeURL(this.url + '/' + id)).then(response => { + RestAPI.get(this.makeURL(this.url + '/' + id), token).then(response => { const data = this.filterKeys(response[this.type]); AppDispatcher.dispatch({ @@ -69,7 +69,7 @@ class RestDataManager { }); } else { // load all objects - RestAPI.get(this.makeURL(this.url)).then(response => { + RestAPI.get(this.makeURL(this.url), token).then(response => { const data = response[this.type + 's'].map(element => { return this.filterKeys(element); }); @@ -87,11 +87,11 @@ class RestDataManager { } } - add(object) { + add(object, token = null) { var obj = {}; obj[this.type] = this.filterKeys(object); - RestAPI.post(this.makeURL(this.url), obj).then(response => { + RestAPI.post(this.makeURL(this.url), obj, token).then(response => { AppDispatcher.dispatch({ type: this.type + 's/added', data: response[this.type] @@ -104,8 +104,8 @@ class RestDataManager { }); } - remove(object) { - RestAPI.delete(this.makeURL(this.url + '/' + object._id)).then(response => { + remove(object, token = null) { + RestAPI.delete(this.makeURL(this.url + '/' + object._id), token).then(response => { AppDispatcher.dispatch({ type: this.type + 's/removed', data: response[this.type], @@ -119,11 +119,11 @@ class RestDataManager { }); } - update(object) { + update(object, token = null) { var obj = {}; obj[this.type] = this.filterKeys(object); - RestAPI.put(this.makeURL(this.url + '/' + object._id), obj).then(response => { + RestAPI.put(this.makeURL(this.url + '/' + object._id, token), obj).then(response => { AppDispatcher.dispatch({ type: this.type + 's/edited', data: response[this.type] diff --git a/src/data-managers/users-data-manager.js b/src/data-managers/users-data-manager.js index b20c3c2..bd60534 100644 --- a/src/data-managers/users-data-manager.js +++ b/src/data-managers/users-data-manager.js @@ -55,20 +55,7 @@ class UsersDataManager extends RestDataManager { }); }); } - - getUsers(token) { - RestAPI.get(this.makeURL('/users'), token).then(response => { - AppDispatcher.dispatch({ - type: 'users/loaded', - data: response.users - }); - }).catch(error => { - AppDispatcher.dispatch({ - type: 'users/load-error', - error: error - }); - }); - } + } export default new UsersDataManager(); diff --git a/src/stores/array-store.js b/src/stores/array-store.js index 9ff162e..b7cfbee 100644 --- a/src/stores/array-store.js +++ b/src/stores/array-store.js @@ -69,10 +69,10 @@ class ArrayStore extends ReduceStore { case this.type + '/start-load': if (Array.isArray(action.data)) { action.data.forEach((id) => { - this.dataManager.load(id); + this.dataManager.load(id, action.token); }); } else { - this.dataManager.load(action.data); + this.dataManager.load(action.data, action.token); } return state; @@ -88,18 +88,19 @@ class ArrayStore extends ReduceStore { return state; case this.type + '/start-add': - this.dataManager.add(action.data); + this.dataManager.add(action.data, action.token); return state; case this.type + '/added': return this.updateElements(state, [action.data]); case this.type + '/add-error': + console.log('something happened'); // TODO: Add error message return state; case this.type + '/start-remove': - this.dataManager.remove(action.data); + this.dataManager.remove(action.data, action.token); return state; case this.type + '/removed': @@ -112,7 +113,7 @@ class ArrayStore extends ReduceStore { return state; case this.type + '/start-edit': - this.dataManager.update(action.data); + this.dataManager.update(action.data, action.token); return state; case this.type + '/edited': diff --git a/src/stores/users-store.js b/src/stores/users-store.js index 3eb1595..0b38e69 100644 --- a/src/stores/users-store.js +++ b/src/stores/users-store.js @@ -30,11 +30,6 @@ class UsersStore extends ArrayStore { reduce(state, action) { switch (action.type) { - // Override ArrayStore's start-load to pass token - case 'users/start-load': - UsersDataManager.getUsers(action.token); - return state; - default: return super.reduce(state, action); } From a4ea7af42933f62faca799e25ad68fecad379516 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Tue, 2 May 2017 17:27:04 +0200 Subject: [PATCH 04/11] add users with fixed password --- src/components/dialog/new-user.js | 101 ++++++++++++++++++++++++++++++ src/containers/users.js | 35 ++++++----- 2 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 src/components/dialog/new-user.js diff --git a/src/components/dialog/new-user.js b/src/components/dialog/new-user.js new file mode 100644 index 0000000..60f845d --- /dev/null +++ b/src/components/dialog/new-user.js @@ -0,0 +1,101 @@ +/** + * File: new-user.js + * Author: Ricardo Hernandez-Montoya + * Date: 02.05.2017 + * + * This file is part of VILLASweb. + * + * VILLASweb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VILLASweb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VILLASweb. If not, see . + ******************************************************************************/ + +import React, { Component, PropTypes } from 'react'; +import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; + +import Dialog from './dialog'; + +class NewUserDialog extends Component { + static propTypes = { + show: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired + }; + + valid: false; + + constructor(props) { + super(props); + + this.state = { + username: '', + role: 'admin', + password: '1234' + }; + } + + onClose(canceled) { + if (canceled === false) { + this.props.onClose(this.state); + } else { + this.props.onClose(); + } + } + + handleChange(e) { + this.setState({ [e.target.id]: e.target.value }); + } + + resetState() { + this.setState({ + username: '', + role: 'admin', + password: '1234' + }); + } + + validateForm(target) { + // check all controls + var username = true; + + if (this.state.username === '') { + username = false; + } + + this.valid = username; + + // return state to control + if (target === 'username') return username ? "success" : "error"; + } + + render() { + return ( + this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> +
    + + Username + this.handleChange(e)} /> + + + + Simulation + this.handleChange(e)}> + + + + +
    +
    + ); + } +} + +export default NewUserDialog; diff --git a/src/containers/users.js b/src/containers/users.js index b8773be..4ab17eb 100644 --- a/src/containers/users.js +++ b/src/containers/users.js @@ -21,7 +21,8 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import { Button, Modal, Glyphicon } from 'react-bootstrap'; +// import { Button, Modal, Glyphicon } from 'react-bootstrap'; +import { Button, Glyphicon } from 'react-bootstrap'; import AppDispatcher from '../app-dispatcher'; import UserStore from '../stores/user-store'; @@ -29,7 +30,7 @@ import UsersStore from '../stores/users-store'; import Table from '../components/table'; import TableColumn from '../components/table-column'; -// import NewUserDialog from '../components/dialog/new-user'; +import NewUserDialog from '../components/dialog/new-user'; // import EditUserDialog from '../components/dialog/edit-user'; class Users extends Component { @@ -60,16 +61,17 @@ class Users extends Component { }; } - // closeNewModal(data) { - // this.setState({ newModal: false }); + closeNewModal(data) { + this.setState({ newModal: false }); - // if (data) { - // AppDispatcher.dispatch({ - // type: 'users/start-add', - // data: data - // }); - // } - // } + if (data) { + AppDispatcher.dispatch({ + type: 'users/start-add', + data: data, + token: this.state.token + }); + } + } // confirmDeleteModal() { // this.setState({ deleteModal: false }); @@ -85,8 +87,9 @@ class Users extends Component { // if (data) { // AppDispatcher.dispatch({ - // type: 'projects/start-edit', - // data: data + // type: 'users/start-edit', + // data: data, + // token: this.state.token // }); // } // } @@ -115,11 +118,11 @@ class Users extends Component { - {/* this.closeNewModal(data)} />*/} + this.closeNewModal(data)} /> - {/* this.closeEditModal(data)} project={this.state.modalData} simulations={this.state.simulations} /> + {/* this.closeEditModal(data)} project={this.state.modalData} />*/} - + {/* Delete Project From 8f6e1fc4399e09581781e08d55d6f24a4b478e89 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 3 May 2017 11:05:22 +0200 Subject: [PATCH 05/11] User edit and remove --- src/components/dialog/edit-user.js | 104 +++++++++++++++++++++++++ src/containers/users.js | 60 ++++++-------- src/data-managers/rest-data-manager.js | 2 +- 3 files changed, 130 insertions(+), 36 deletions(-) create mode 100644 src/components/dialog/edit-user.js diff --git a/src/components/dialog/edit-user.js b/src/components/dialog/edit-user.js new file mode 100644 index 0000000..9485c29 --- /dev/null +++ b/src/components/dialog/edit-user.js @@ -0,0 +1,104 @@ +/** + * File: edit-user.js + * Author: Ricardo Hernandez-Montoya + * Date: 02.05.2017 + * + * This file is part of VILLASweb. + * + * VILLASweb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VILLASweb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VILLASweb. If not, see . + ******************************************************************************/ + +import React, { Component, PropTypes } from 'react'; +import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap'; + +import Dialog from './dialog'; + +class EditUserDialog extends Component { + static propTypes = { + show: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, + user: PropTypes.object.isRequired + }; + + valid: true; + + constructor(props) { + super(props); + + this.state = { + username: '', + role: '', + _id: '' + } + } + + onClose(canceled) { + if (canceled === false) { + this.props.onClose(this.state); + } else { + this.props.onClose(); + } + } + + handleChange(e) { + this.setState({ [e.target.id]: e.target.value }); + } + + resetState() { + this.setState({ + username: this.props.user.username, + role: this.props.user.role, + _id: this.props.user._id + }); + } + + validateForm(target) { + // check all controls + var username = true; + + if (this.state.username === '') { + username = false; + } + + this.valid = username; + + // return state to control + if (target === 'username') return username ? "success" : "error"; + + return "success"; + } + + render() { + return ( + this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> +
    + + Username + this.handleChange(e)} /> + + + + Simulation + this.handleChange(e)}> + + + + +
    +
    + ); + } +} + +export default EditUserDialog; diff --git a/src/containers/users.js b/src/containers/users.js index 4ab17eb..b1f573f 100644 --- a/src/containers/users.js +++ b/src/containers/users.js @@ -21,8 +21,7 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -// import { Button, Modal, Glyphicon } from 'react-bootstrap'; -import { Button, Glyphicon } from 'react-bootstrap'; +import { Button, Modal, Glyphicon } from 'react-bootstrap'; import AppDispatcher from '../app-dispatcher'; import UserStore from '../stores/user-store'; @@ -31,7 +30,7 @@ import UsersStore from '../stores/users-store'; import Table from '../components/table'; import TableColumn from '../components/table-column'; import NewUserDialog from '../components/dialog/new-user'; -// import EditUserDialog from '../components/dialog/edit-user'; +import EditUserDialog from '../components/dialog/edit-user'; class Users extends Component { static getStores() { @@ -73,36 +72,27 @@ class Users extends Component { } } - // confirmDeleteModal() { - // this.setState({ deleteModal: false }); + confirmDeleteModal() { + this.setState({ deleteModal: false }); - // AppDispatcher.dispatch({ - // type: 'projects/start-remove', - // data: this.state.modalData - // }); - // } + AppDispatcher.dispatch({ + type: 'users/start-remove', + data: this.state.modalData, + token: this.state.token + }); + } - // closeEditModal(data) { - // this.setState({ editModal: false }); + closeEditModal(data) { + this.setState({ editModal: false }); - // if (data) { - // AppDispatcher.dispatch({ - // type: 'users/start-edit', - // data: data, - // token: this.state.token - // }); - // } - // } - - // getSimulationName(id) { - // for (var i = 0; i < this.state.simulations.length; i++) { - // if (this.state.simulations[i]._id === id) { - // return this.state.simulations[i].name; - // } - // } - - // return id; - // } + if (data) { + AppDispatcher.dispatch({ + type: 'users/start-edit', + data: data, + token: this.state.token + }); + } + } render() { @@ -120,22 +110,22 @@ class Users extends Component { this.closeNewModal(data)} /> - {/* this.closeEditModal(data)} project={this.state.modalData} />*/} + this.closeEditModal(data)} user={this.state.modalData} /> - {/* + - Delete Project + Delete user - Are you sure you want to delete the project '{this.state.modalData.name}'? + Are you sure you want to delete the user '{this.state.modalData.username}'? - */} +
    ); } diff --git a/src/data-managers/rest-data-manager.js b/src/data-managers/rest-data-manager.js index 99dbd04..2ae0a46 100644 --- a/src/data-managers/rest-data-manager.js +++ b/src/data-managers/rest-data-manager.js @@ -123,7 +123,7 @@ class RestDataManager { var obj = {}; obj[this.type] = this.filterKeys(object); - RestAPI.put(this.makeURL(this.url + '/' + object._id, token), obj).then(response => { + RestAPI.put(this.makeURL(this.url + '/' + object._id), obj, token).then(response => { AppDispatcher.dispatch({ type: this.type + 's/edited', data: response[this.type] From 703fa92d2fb9142599f5952db999e90cdd339949 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 3 May 2017 11:26:11 +0200 Subject: [PATCH 06/11] include user e-mail --- src/components/dialog/edit-user.js | 9 ++++++++- src/components/dialog/new-user.js | 9 ++++++++- src/containers/users.js | 3 ++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/components/dialog/edit-user.js b/src/components/dialog/edit-user.js index 9485c29..a779725 100644 --- a/src/components/dialog/edit-user.js +++ b/src/components/dialog/edit-user.js @@ -38,6 +38,7 @@ class EditUserDialog extends Component { this.state = { username: '', + mail: '', role: '', _id: '' } @@ -58,6 +59,7 @@ class EditUserDialog extends Component { resetState() { this.setState({ username: this.props.user.username, + mail: this.props.user.mail, role: this.props.user.role, _id: this.props.user._id }); @@ -88,8 +90,13 @@ class EditUserDialog extends Component { this.handleChange(e)} /> + + E-mail + this.handleChange(e)} /> + + - Simulation + Role this.handleChange(e)}> diff --git a/src/components/dialog/new-user.js b/src/components/dialog/new-user.js index 60f845d..690f17d 100644 --- a/src/components/dialog/new-user.js +++ b/src/components/dialog/new-user.js @@ -37,6 +37,7 @@ class NewUserDialog extends Component { this.state = { username: '', + mail: '', role: 'admin', password: '1234' }; @@ -57,6 +58,7 @@ class NewUserDialog extends Component { resetState() { this.setState({ username: '', + mail: '', role: 'admin', password: '1234' }); @@ -85,8 +87,13 @@ class NewUserDialog extends Component { this.handleChange(e)} /> + + E-mail + this.handleChange(e)} /> + + - Simulation + Role this.handleChange(e)}> diff --git a/src/containers/users.js b/src/containers/users.js index b1f573f..91f720c 100644 --- a/src/containers/users.js +++ b/src/containers/users.js @@ -101,7 +101,8 @@ class Users extends Component {

    Users

    - + + this.setState({ editModal: true, modalData: this.state.users[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.users[index] })} />
    From 8fb0166059b61eeb1fe52d8b16352224409f8876 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 3 May 2017 11:44:08 +0200 Subject: [PATCH 07/11] human names and consisting roles with back-end --- src/components/dialog/edit-user.js | 5 +++-- src/components/dialog/new-user.js | 5 +++-- src/containers/users.js | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/components/dialog/edit-user.js b/src/components/dialog/edit-user.js index a779725..c8bb203 100644 --- a/src/components/dialog/edit-user.js +++ b/src/components/dialog/edit-user.js @@ -98,8 +98,9 @@ class EditUserDialog extends Component { Role this.handleChange(e)}> - - + + + diff --git a/src/components/dialog/new-user.js b/src/components/dialog/new-user.js index 690f17d..f666e31 100644 --- a/src/components/dialog/new-user.js +++ b/src/components/dialog/new-user.js @@ -95,8 +95,9 @@ class NewUserDialog extends Component { Role this.handleChange(e)}> - - + + + diff --git a/src/containers/users.js b/src/containers/users.js index 91f720c..288c4f4 100644 --- a/src/containers/users.js +++ b/src/containers/users.js @@ -94,6 +94,12 @@ class Users extends Component { } } + getHumanRoleName(role_key) { + const HUMAN_ROLE_NAMES = {admin: 'Administrator', user: 'User', guest: 'Guest'}; + + return HUMAN_ROLE_NAMES.hasOwnProperty(role_key)? HUMAN_ROLE_NAMES[role_key] : ''; + } + render() { return ( @@ -103,7 +109,7 @@ class Users extends Component { - + this.getHumanRoleName(role)} /> this.setState({ editModal: true, modalData: this.state.users[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.users[index] })} />
    From d218c1854d466bcd8db80de9c0ee42f4dd5daba8 Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 3 May 2017 12:46:53 +0200 Subject: [PATCH 08/11] hide user management section for non-admins --- src/components/menu-sidebar.js | 4 +++- src/containers/app.js | 6 ++++-- src/data-managers/users-data-manager.js | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/menu-sidebar.js b/src/components/menu-sidebar.js index 1782304..882ab56 100644 --- a/src/components/menu-sidebar.js +++ b/src/components/menu-sidebar.js @@ -33,7 +33,9 @@ class SidebarMenu extends Component {
  • Projects
  • Simulations
  • Simulators
  • -
  • User Management
  • + { this.props.currentRole === 'admin' ? +
  • User Management
  • : '' + }
  • Logout
  • diff --git a/src/containers/app.js b/src/containers/app.js index 4e90442..9e6eaf0 100644 --- a/src/containers/app.js +++ b/src/containers/app.js @@ -76,9 +76,11 @@ class App extends Component { } } + let currentUser = UserStore.getState().currentUser; + return { simulations: SimulationStore.getState(), - currentUser: UserStore.getState().currentUser, + currentRole: currentUser? currentUser.role : '', token: UserStore.getState().token, runningSimulators: simulators @@ -183,7 +185,7 @@ class App extends Component {
    - +
    {children} diff --git a/src/data-managers/users-data-manager.js b/src/data-managers/users-data-manager.js index bd60534..f5db8f8 100644 --- a/src/data-managers/users-data-manager.js +++ b/src/data-managers/users-data-manager.js @@ -46,7 +46,7 @@ class UsersDataManager extends RestDataManager { RestAPI.get(this.makeURL('/users/me'), token).then(response => { AppDispatcher.dispatch({ type: 'users/current-user', - user: response + user: response.user }); }).catch(error => { AppDispatcher.dispatch({ From 39c8a2518a14f659fabafaa6e3563ceefa45880e Mon Sep 17 00:00:00 2001 From: Ricardo Hernandez-Montoya Date: Wed, 3 May 2017 15:58:58 +0200 Subject: [PATCH 09/11] sidebar menu items no wrap and grow --- src/components/menu-sidebar.js | 12 ++++----- src/containers/app.js | 10 ++++--- src/styles/app.css | 49 +++++++++++++++++++++++++--------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/components/menu-sidebar.js b/src/components/menu-sidebar.js index 882ab56..152644a 100644 --- a/src/components/menu-sidebar.js +++ b/src/components/menu-sidebar.js @@ -29,14 +29,14 @@ class SidebarMenu extends Component {

    Menu

      -
    • Home
    • -
    • Projects
    • -
    • Simulations
    • -
    • Simulators
    • +
    • Home
    • +
    • Projects
    • +
    • Simulations
    • +
    • Simulators
    • { this.props.currentRole === 'admin' ? -
    • User Management
    • : '' +
    • User Management
    • : '' } -
    • Logout
    • +
    • Logout
    ); diff --git a/src/containers/app.js b/src/containers/app.js index 9e6eaf0..2af248e 100644 --- a/src/containers/app.js +++ b/src/containers/app.js @@ -77,7 +77,7 @@ class App extends Component { } let currentUser = UserStore.getState().currentUser; - + return { simulations: SimulationStore.getState(), currentRole: currentUser? currentUser.role : '', @@ -185,10 +185,12 @@ class App extends Component {
    - -
    - {children} +
    + +
    + {children} +