Commit 0895ad3c authored by Sonja Happ's avatar Sonja Happ

Major modifications in login data management:

- only token and currentUser are stored (and error msg if any)
- token and current User are stored in local storage and used by app.js
- placeholders in user edit dialogs are replaced by actual values (except for pw)
- UserStore is renamed to LoginStore to resolve naming confusion
- Error notifications are moved to react components instead of data managers/ dispatchers
- updateCurrentUser method was added in UserDataManager for updating own user #197
- cleanup of edit-own-user dialog #197
parent 0646d85a
......@@ -31,7 +31,7 @@ import { Hidden } from 'react-grid-system'
import AppDispatcher from './common/app-dispatcher';
import ScenarioStore from './scenario/scenario-store';
import SimulatorStore from './simulator/simulator-store';
import UserStore from './user/user-store';
import LoginStore from './user/login-store';
import NotificationsDataManager from './common/data-managers/notifications-data-manager';
import Home from './common/home';
......@@ -40,12 +40,8 @@ import Footer from './common/footer';
import SidebarMenu from './common/menu-sidebar';
import HeaderMenu from './common/header-menu';
//import Projects from './project/projects';
//import Project from './project/project';
import Simulators from './simulator/simulators';
import Dashboard from './dashboard/dashboard';
//import Simulations from './simulation/simulations';
//import Simulation from './simulation/simulation';
import Scenarios from './scenario/scenarios';
import Scenario from './scenario/scenario';
import SimulationModel from './simulationmodel/simulation-model';
......@@ -57,19 +53,16 @@ import './styles/app.css';
class App extends React.Component {
static getStores() {
return [ SimulatorStore, UserStore, ScenarioStore];
return [ SimulatorStore, LoginStore, ScenarioStore];
}
static calculateState(prevState) {
let currentUser = UserStore.getState().currentUser;
return {
simulators: SimulatorStore.getState(),
scenarios: ScenarioStore.getState(),
currentRole: currentUser ? currentUser.role : '',
currentUsername: currentUser ? currentUser.username: '',
currentUserID: UserStore.getState().userid,
token: UserStore.getState().token,
currentUser: LoginStore.getState().currentUser,
token: LoginStore.getState().token,
showSidebarMenu: false,
};
......@@ -77,17 +70,13 @@ class App extends React.Component {
componentWillMount() {
// if token stored locally, request user
const token = localStorage.getItem('token');
const userid = localStorage.getItem('userid');
let token = localStorage.getItem("token");
let currentUser = JSON.parse(localStorage.getItem("currentUser"));
if (token != null && token !== '') {
// save token so we dont logout
this.setState({ token });
AppDispatcher.dispatch({
type: 'users/logged-in',
token: token,
userid: userid
currentUser: currentUser
});
}
}
......@@ -128,7 +117,7 @@ class App extends React.Component {
*/}
<Hidden sm md lg xl>
<Col style={{ width: this.state.showSidebarMenu ? '280px' : '0px' }} className="sidenav">
<HeaderMenu onClose={this.hideSidebarMenu} currentRole={this.state.currentRole} />
<HeaderMenu onClose={this.hideSidebarMenu} currentRole={this.state.currentUser.role} />
</Col>
</Hidden>
......@@ -139,7 +128,7 @@ class App extends React.Component {
<div className={`app-body app-body-spacing`} >
<Col xs={false}>
<SidebarMenu currentRole={this.state.currentRole} />
<SidebarMenu currentRole={this.state.currentUser.role} />
</Col>
<div className={`app-content app-content-margin-left`}>
......
......@@ -79,14 +79,8 @@ class ArrayStore extends ReduceStore {
case this.type + '/loaded':
if (Array.isArray(action.data)) {
console.log("####### loaded array of type " + this.type);
//console.log(action.data);
//console.log(state);
return this.updateElements(state, action.data);
} else {
console.log("####### loaded single object of type " + this.type);
//console.log([action.data]);
//console.log(state);
return this.updateElements(state, [action.data]);
}
......@@ -141,22 +135,9 @@ class ArrayStore extends ReduceStore {
this.dataManager.update(action.data, action.token,action.param);
return state;
case this.type + '/start-own-edit':
this.dataManager.update(action.data, action.token,action.param);
return state;
case this.type + '/edited':
return this.updateElements(state, [action.data]);
case this.type + '/confirm-pw-doesnt-match':
const USER_PW_ERROR_NOTIFICATION = {
title: 'The new password does not match',
message: 'Try again',
level: 'error'
};
NotificationsDataManager.addNotification(USER_PW_ERROR_NOTIFICATION);
return state;
case this.type + '/edit-error':
return state;
......
......@@ -26,18 +26,15 @@ import React from 'react';
//import RestAPI from '../api/rest-api';
import config from '../config';
import UserStore from "../user/user-store";
import LoginStore from "../user/login-store";
class Home extends React.Component {
constructor(props) {
super(props);
let currentUser = UserStore.getState().currentUser;
this.state = {
currentRole: currentUser ? currentUser.role : '',
currentUsername: currentUser ? currentUser.username: '',
currentUserID: currentUser ? currentUser.id: 0,
token: UserStore.getState().token
currentUser: LoginStore.getState().currentUser,
token: LoginStore.getState().token
};
}
......@@ -64,7 +61,7 @@ class Home extends React.Component {
VILLASweb is a frontend for distributed real-time simulation hosted by <a href={"mailto:" + config.admin.mail}>{config.admin.name}</a>.
</p>
<p>
You are logged in as user <b>{this.state.currentUsername}</b> with <b>ID {this.state.currentUserID}</b> and role <b>{this.state.currentRole}</b>.
You are logged in as user <b>{this.state.currentUser.username}</b> with <b>ID {this.state.currentUser.id}</b> and role <b>{this.state.currentUser.role}</b>.
</p>
{/*
<p>
......
......@@ -34,7 +34,7 @@ import WidgetToolbox from './widget-toolbox';
import WidgetArea from './widget-area';
import DashboardButtonGroup from './dashboard-button-group';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import DashboardStore from './dashboard-store';
import ProjectStore from '../project/project-store';
import SimulationStore from '../simulation/simulation-store';
......@@ -49,14 +49,14 @@ class Dashboard extends React.Component {
static lastWidgetKey = 0;
static getStores() {
return [ DashboardStore, ProjectStore, SimulationStore, SimulationModelStore, FileStore, UserStore, WidgetStore ];
return [ DashboardStore, ProjectStore, SimulationStore, SimulationModelStore, FileStore, LoginStore, WidgetStore ];
}
static calculateState(prevState, props) {
if (prevState == null) {
prevState = {};
}
const sessionToken = UserStore.getState().token;
const sessionToken = LoginStore.getState().token;
let dashboard = Map();
console.log("dashboard calculate state was called: " + props.match.params.dashboard);
let dashboards = DashboardStore.getState()
......
......@@ -24,19 +24,19 @@ import { Container } from 'flux/utils';
import { FormGroup, FormControl, FormLabel, Button, ProgressBar, Col } from 'react-bootstrap';
import FileStore from './file-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import AppDispatcher from '../common/app-dispatcher';
class SelectFile extends React.Component {
static getStores() {
return [ FileStore, UserStore ];
return [ FileStore, LoginStore ];
}
static calculateState() {
return {
files: FileStore.getState(),
sessionToken: UserStore.getState().token,
sessionToken: LoginStore.getState().token,
selectedFile: '',
uploadFile: null,
uploadProgress: 0
......
......@@ -26,7 +26,7 @@ import FileSaver from 'file-saver';
import AppDispatcher from '../common/app-dispatcher';
import ProjectStore from './project-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import DashboardStore from '../dashboard/dashboard-store';
import SimulationStore from '../simulation/simulation-store';
......@@ -41,14 +41,14 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Dashboards extends Component {
static getStores() {
return [ ProjectStore, DashboardStore, UserStore, SimulationStore ];
return [ ProjectStore, DashboardStore, LoginStore, SimulationStore ];
}
static calculateState(prevState, props) {
prevState = prevState || {};
// load project
const sessionToken = UserStore.getState().token;
const sessionToken = LoginStore.getState().token;
let project = ProjectStore.getState().find(project => project._id === props.match.params.project);
if (project == null) {
......
......@@ -25,7 +25,7 @@ import { Button } from 'react-bootstrap';
import AppDispatcher from '../common/app-dispatcher';
import ProjectStore from './project-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import SimulationStore from '../simulation/simulation-store';
import Icon from '../common/icon';
......@@ -38,14 +38,14 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Projects extends React.Component {
static getStores() {
return [ ProjectStore, SimulationStore, UserStore ];
return [ ProjectStore, SimulationStore, LoginStore ];
}
static calculateState() {
return {
projects: ProjectStore.getState(),
simulations: SimulationStore.getState(),
sessionToken: UserStore.getState().token,
sessionToken: LoginStore.getState().token,
newModal: false,
editModal: false,
......
......@@ -22,42 +22,5 @@
import ScenariosDataManager from './scenarios-data-manager';
import ArrayStore from '../common/array-store';
//import UsersDataManager from "../user/users-data-manager";
//import SimulatorDataDataManager from "../simulator/simulator-data-data-manager";
//import AppDispatcher from "../common/app-dispatcher";
export default new ArrayStore('scenarios', ScenariosDataManager);
// class ScenariosStore extends ReduceStore {
// constructor() {
// super('scenarios', ScenariosDataManager);
// }
//
// getInitialState() {
// return {
// scenarios: [],
//
// };
// }
//
// reduce(state, action) {
// switch (action.type) {
// case 'scenarios/load-models':
// // request simulation model data of scenario
// ScenariosDataManager.getSimulationModels(action.token, action.scenarioID);
//
// return Object.assign({}, state, { token: action.token, simulationmodels: action.simulationmodels});
//
// case 'scenarios/load-dashboards':
// // request dashboard data of scenario
// ScenariosDataManager.getDashboards(action.token, action.scenarioID);
//
// return Object.assign({}, state, { token: action.token, dashboards: action.dashboards});
// default:
// return state;
// }
// }
// }
//
// export default new ScenariosStore();
......@@ -29,7 +29,7 @@ import ScenarioStore from './scenario-store';
import SimulatorStore from '../simulator/simulator-store';
import DashboardStore from '../dashboard/dashboard-store';
import SimulationModelStore from '../simulationmodel/simulation-model-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import AppDispatcher from '../common/app-dispatcher';
import Icon from '../common/icon';
......@@ -44,12 +44,12 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Scenario extends React.Component {
static getStores() {
return [ ScenarioStore, SimulationModelStore, DashboardStore, SimulatorStore];
return [ ScenarioStore, SimulationModelStore, DashboardStore, SimulatorStore, LoginStore];
}
static calculateState(prevState, props) {
// get selected scenario
const sessionToken = UserStore.getState().token;
const sessionToken = LoginStore.getState().token;
const scenario = ScenarioStore.getState().find(s => s.id === parseInt(props.match.params.scenario, 10));
if (scenario == null) {
......@@ -187,7 +187,6 @@ class Scenario extends React.Component {
type: 'dashboards/start-add',
data,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......@@ -203,7 +202,6 @@ class Scenario extends React.Component {
type: 'dashboards/start-remove',
data: this.state.modalDashboardData,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
......@@ -215,7 +213,6 @@ class Scenario extends React.Component {
type: 'dashboards/start-add',
data,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......
......@@ -26,7 +26,7 @@ import FileSaver from 'file-saver';
import AppDispatcher from '../common/app-dispatcher';
import ScenarioStore from './scenario-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import Icon from '../common/icon';
import Table from '../common/table';
......@@ -39,12 +39,12 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Scenarios extends Component {
static getStores() {
return [ ScenarioStore, UserStore ];
return [ ScenarioStore, LoginStore ];
}
static calculateState() {
const scenarios = ScenarioStore.getState();
const sessionToken = UserStore.getState().token;
const sessionToken = LoginStore.getState().token;
console.log(scenarios);
return {
......
......@@ -28,7 +28,7 @@ import _ from 'lodash';
import SimulationStore from './simulation-store';
import SimulatorStore from '../simulator/simulator-store';
import SimulationModelStore from '../simulationmodel/simulation-model-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import AppDispatcher from '../common/app-dispatcher';
import Icon from '../common/icon';
......@@ -41,12 +41,12 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Simulation extends React.Component {
static getStores() {
return [ SimulationStore, SimulatorStore, SimulationModelStore, UserStore ];
return [ SimulationStore, SimulatorStore, SimulationModelStore, LoginStore ];
}
static calculateState(prevState, props) {
// get selected simulation
const sessionToken = UserStore.getState().token;
const sessionToken = LoginStore.getState().token;
let simulation = SimulationStore.getState().find(s => s._id === props.match.params.simulation);
if (simulation == null) {
......
......@@ -26,7 +26,7 @@ import FileSaver from 'file-saver';
import AppDispatcher from '../common/app-dispatcher';
import SimulationStore from './simulation-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import SimulatorStore from '../simulator/simulator-store';
import SimulationModelStore from '../simulationmodel/simulation-model-store';
......@@ -42,7 +42,7 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Simulations extends Component {
static getStores() {
return [ SimulationStore, UserStore, SimulatorStore, SimulationModelStore ];
return [ SimulationStore, LoginStore, SimulatorStore, SimulationModelStore ];
}
static calculateState() {
......@@ -50,7 +50,7 @@ class Simulations extends Component {
const simulationModels = SimulationModelStore.getState();
const simulators = SimulatorStore.getState();
const sessionToken = UserStore.getState().token;
const sessionToken = LoginStore.getState().token;
return {
simulations,
......
......@@ -24,7 +24,7 @@ import { Container } from 'flux/utils';
import { Button, Col, Form, FormLabel } from 'react-bootstrap';
import SimulationModelStore from './simulation-model-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import AppDispatcher from '../common/app-dispatcher';
import SelectSimulator from '../simulator/select-simulator';
......@@ -35,7 +35,7 @@ import ParametersEditor from '../common/parameters-editor';
class SimulationModel extends React.Component {
static getStores() {
return [ SimulationModelStore, UserStore ];
return [ SimulationModelStore, LoginStore ];
}
static calculateState(prevState, props) {
......@@ -43,7 +43,7 @@ class SimulationModel extends React.Component {
return {
simulationModel: simulationModel || {},
sessionToken: UserStore.getState().token
sessionToken: LoginStore.getState().token
};
}
......
......@@ -27,7 +27,7 @@ import _ from 'lodash';
import AppDispatcher from '../common/app-dispatcher';
import SimulatorStore from './simulator-store';
import UserStore from '../user/user-store';
import LoginStore from '../user/login-store';
import Icon from '../common/icon';
import Table from '../common/table';
......@@ -41,7 +41,7 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Simulators extends Component {
static getStores() {
return [ UserStore, SimulatorStore ];
return [ LoginStore, SimulatorStore ];
}
static statePrio(state) {
......@@ -78,8 +78,7 @@ class Simulators extends Component {
});
return {
sessionToken: UserStore.getState().token,
sessionUserID: UserStore.getState().userid,
sessionToken: LoginStore.getState().token,
simulators,
modalSimulator: {},
deleteModal: false,
......@@ -92,7 +91,6 @@ class Simulators extends Component {
AppDispatcher.dispatch({
type: 'simulators/start-load',
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
// Start timer for periodic refresh
......@@ -112,7 +110,6 @@ class Simulators extends Component {
AppDispatcher.dispatch({
type: 'simulators/start-load',
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......@@ -126,7 +123,6 @@ class Simulators extends Component {
type: 'simulators/start-add',
data,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......@@ -146,7 +142,6 @@ class Simulators extends Component {
type: 'simulators/start-edit',
data: simulator,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......@@ -162,7 +157,6 @@ class Simulators extends Component {
type: 'simulators/start-remove',
data: this.state.modalSimulator,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
......@@ -184,7 +178,6 @@ class Simulators extends Component {
type: 'simulators/start-add',
data,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......@@ -221,7 +214,6 @@ class Simulators extends Component {
simulator: this.state.simulators[index],
data: action.data,
token: this.state.sessionToken,
userid: this.state.sessionUserID
});
}
}
......
......@@ -23,7 +23,7 @@ import React from 'react';
import {FormGroup, FormControl, FormLabel, Col} from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
import UserStore from './user-store';
//import LoginStore from './login-store';
class EditOwnUserDialog extends React.Component {
......@@ -34,17 +34,15 @@ class EditOwnUserDialog extends React.Component {
this.state = {
username: '',
mail: '',
role: '',
id: '',
mail: '',
password: '',
oldPassword: '',
active: '',
confirmpassword: ''
}
}
onClose(canceled) {
if (canceled === false) {
......@@ -56,18 +54,15 @@ class EditOwnUserDialog extends React.Component {
}
}
handleChange(e) {
let user = UserStore.getState().currentUser;
this.setState({ [e.target.id]: e.target.value });
// check all controls
var username = true;
var role = true;
var mail = true;
var pw = true;
var active = true;
var oldPassword = true;
var confirmpassword = true;
......@@ -75,7 +70,6 @@ class EditOwnUserDialog extends React.Component {
username = false;
}
if(this.state.mail === ''){
mail = false;
}
......@@ -84,10 +78,6 @@ class EditOwnUserDialog extends React.Component {
pw = false;
}
if(this.state.active === ''){
active = false;
}
if(this.state.oldPassword === ''){
oldPassword = false;
}
......@@ -96,23 +86,26 @@ class EditOwnUserDialog extends React.Component {
confirmpassword = false;
}
this.setState({
/*this.setState({
role: user.role,
id: user.id
});
id: user.id,
active: user.active
});*/
// form is valid if any of the fields contain somethig
this.valid = username || role || active || oldPassword || mail || pw || confirmpassword;
// form is valid if the following condition is met
this.valid = username || mail || (oldPassword && pw && confirmpassword);
}
resetState() {
this.setState({
//username: this.props.user.username,
//mail: this.props.user.mail,
role: this.props.user.role,
id: this.props.user.id
username: '',
mail: '',
oldPassword: '',
confirmpassword: '',
password: '',
id: this.props.user.id,
});
}
......@@ -122,12 +115,12 @@ class EditOwnUserDialog extends React.Component {
<form>
<FormGroup as={Col} controlId="username">
<FormLabel>Username</FormLabel>
<FormControl type="text" placeholder="Enter username" value={this.state.username} onChange={(e) => this.handleChange(e)} />
<FormControl type="text" placeholder={this.props.user.username} value={this.state.username} onChange={(e) => this.handleChange(e)} />
<FormControl.Feedback />
</FormGroup>
<FormGroup as={Col} controlId="mail">
<FormLabel>E-mail</FormLabel>
<FormControl type="text" placeholder="Enter e-mail" <