diff --git a/src/app.js b/src/app.js index aa9ce6a..cddc5de 100644 --- a/src/app.js +++ b/src/app.js @@ -87,8 +87,13 @@ class App extends React.Component { }; render() { - if (this.state.token == null) { - return (); + + let token = localStorage.getItem("token"); + let currentUser = JSON.parse(localStorage.getItem("currentUser")); + + if (token == null || currentUser == null) { + console.log("APP redirecting to logout/ login") + return (); } return ( @@ -99,7 +104,7 @@ class App extends React.Component { */} - + @@ -110,17 +115,17 @@ class App extends React.Component {
- +
- + - +
diff --git a/src/common/header-menu.js b/src/common/header-menu.js index 6105f76..9c6f7eb 100644 --- a/src/common/header-menu.js +++ b/src/common/header-menu.js @@ -27,11 +27,12 @@ export default class HeaderMenu extends React.Component { ; diff --git a/src/common/home.js b/src/common/home.js index 0aee6b9..4bf124f 100644 --- a/src/common/home.js +++ b/src/common/home.js @@ -19,6 +19,7 @@ import React from 'react'; import config from '../config'; import LoginStore from "../user/login-store"; +import {Redirect} from "react-router-dom"; class Home extends React.Component { constructor(props) { @@ -38,6 +39,13 @@ class Home extends React.Component { } render() { + + let currentUser = JSON.parse(localStorage.getItem("currentUser")); + if (currentUser == null){ + console.log("HOME redirecting to logout/ login") + return (); + } + return (
Logo VILLASweb @@ -47,7 +55,7 @@ class Home extends React.Component { VILLASweb is a frontend for distributed real-time simulation hosted by {config.admin.name}.

- You are logged in as user {this.state.currentUser.username} with ID {this.state.currentUser.id} and role {this.state.currentUser.role}. + You are logged in as user {currentUser.username} with ID {currentUser.id} and role {currentUser.role}.

Data Model

diff --git a/src/common/menu-sidebar.js b/src/common/menu-sidebar.js index 59874ed..06d1342 100644 --- a/src/common/menu-sidebar.js +++ b/src/common/menu-sidebar.js @@ -31,7 +31,7 @@ class SidebarMenu extends React.Component { { this.props.currentRole === 'Admin' ?
  • User Management
  • : '' } -
  • Account
  • +
  • Account
  • Logout
  • diff --git a/src/dashboard/dashboard.js b/src/dashboard/dashboard.js index 584a4f2..ee3c247 100644 --- a/src/dashboard/dashboard.js +++ b/src/dashboard/dashboard.js @@ -28,7 +28,6 @@ import WidgetToolbox from '../widget/widget-toolbox'; import WidgetArea from '../widget/widget-area'; import DashboardButtonGroup from './dashboard-button-group'; -import LoginStore from '../user/login-store'; import DashboardStore from './dashboard-store'; import SignalStore from '../signal/signal-store' import FileStore from '../file/file-store'; @@ -42,8 +41,9 @@ import 'react-contexify/dist/ReactContexify.min.css'; class Dashboard extends Component { static lastWidgetKey = 0; + static webSocketsOpened = false; static getStores() { - return [ DashboardStore, LoginStore,FileStore, WidgetStore, SignalStore, ConfigStore, ICStore]; + return [ DashboardStore, FileStore, WidgetStore, SignalStore, ConfigStore, ICStore]; } static calculateState(prevState, props) { @@ -51,7 +51,7 @@ class Dashboard extends Component { prevState = {}; } - const sessionToken = LoginStore.getState().token; + const sessionToken = localStorage.getItem("token"); let dashboard = DashboardStore.getState().find(d => d.id === parseInt(props.match.params.dashboard, 10)); if (dashboard == null){ @@ -73,20 +73,22 @@ class Dashboard extends Component { return thisWidgetHeight > maxHeightSoFar? thisWidgetHeight : maxHeightSoFar; }, 0); - if(dashboard.height === 0){ - dashboard.height = 400; - } - else if(maxHeight + 80 > dashboard.height) - { - dashboard.height = maxHeight + 80; - } + // filter component configurations to the ones that belong to this scenario let configs = [] let files = [] - if (dashboard !== null) { + if (dashboard !== undefined) { configs = ConfigStore.getState().filter(config => config.scenarioID === dashboard.scenarioID); files = FileStore.getState().filter(file => file.scenarioID === dashboard.scenarioID); + + if(dashboard.height === 0){ + dashboard.height = 400; + } + else if(maxHeight + 80 > dashboard.height) + { + dashboard.height = maxHeight + 80; + } } // filter signals to the ones belonging to the scenario at hand @@ -154,18 +156,46 @@ class Dashboard extends Component { AppDispatcher.dispatch({ type: 'widgets/start-load', token: this.state.sessionToken, - param: '?dashboardID=' + this.state.dashboard.id + param: '?dashboardID=' + parseInt(this.props.match.params.dashboard, 10), }); - // open web sockets if ICs are already known - if(this.state.ics.length > 0){ + // load ICs to enable that component configs and dashboards work with them + AppDispatcher.dispatch({ + type: 'ics/start-load', + token: this.state.sessionToken + }); + + + + } + + componentDidUpdate(prevProps: Readonly

    , prevState: Readonly, snapshot: SS) { + // open web sockets if ICs are already known and sockets are not opened yet + if(!Dashboard.webSocketsOpened && this.state.ics.length > 0){ console.log("Starting to open IC websockets:", this.state.ics); AppDispatcher.dispatch({ type: 'ics/open-sockets', data: this.state.ics }); - } else { - console.log("ICs unknown in componentDidMount", this.state.dashboard) + + Dashboard.webSocketsOpened = true; + } + + if(this.state.configs.length === 0 && this.state.dashboard !== undefined) { + // load configs + AppDispatcher.dispatch({ + type: 'configs/start-load', + token: this.state.sessionToken, + param: '?scenarioID=' + this.state.dashboard.scenarioID + }); + } + + if(this.state.files.length === 0 && this.state.dashboard !== undefined){ + AppDispatcher.dispatch({ + type: 'files/start-load', + param: '?scenarioID=' + this.state.dashboard.scenarioID, + token: this.state.sessionToken + }); } } @@ -398,6 +428,10 @@ class Dashboard extends Component { render() { + if (this.state.dashboard === undefined){ + return

    {"Loading Dashboard..."}
    + } + const grid = this.state.dashboard.grid; const boxClasses = classNames('section', 'box', { 'fullscreen-padding': this.props.isFullscreen }); let draggable = this.state.editing; diff --git a/src/ic/ics.js b/src/ic/ics.js index de97d21..aa275ec 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -75,7 +75,7 @@ class InfrastructureComponents extends Component { }); return { - sessionToken: LoginStore.getState().token, + sessionToken: localStorage.getItem("token"), ics: ics, modalIC: {}, deleteModal: false, diff --git a/src/router.js b/src/router.js index 348a231..05cf900 100644 --- a/src/router.js +++ b/src/router.js @@ -21,6 +21,13 @@ import { BrowserRouter, Route, Switch } from 'react-router-dom'; import App from './app'; import Login from './user/login'; import Logout from './user/logout'; +import Home from './common/home'; +import Scenarios from './scenario/scenarios'; +import Scenario from './scenario/scenario'; +import Dashboard from './dashboard/dashboard' +import InfrastructureComponents from './ic/ics'; +import Users from './user/users'; +import User from "./user/user"; class Root extends React.Component { render() { @@ -30,6 +37,14 @@ class Root extends React.Component { + + + + + + + + ); diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 44a332f..fcd1300 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -25,7 +25,6 @@ import ScenarioStore from './scenario-store'; import ICStore from '../ic/ic-store'; import DashboardStore from '../dashboard/dashboard-store'; import ConfigStore from '../componentconfig/config-store'; -import LoginStore from '../user/login-store'; import SignalStore from '../signal/signal-store' import AppDispatcher from '../common/app-dispatcher'; @@ -48,7 +47,7 @@ import WidgetStore from "../widget/widget-store"; class Scenario extends React.Component { static getStores() { - return [ ScenarioStore, ConfigStore, DashboardStore, ICStore, LoginStore, SignalStore, FileStore, WidgetStore]; + return [ ScenarioStore, ConfigStore, DashboardStore, ICStore, SignalStore, FileStore, WidgetStore]; } static calculateState(prevState, props) { @@ -57,10 +56,10 @@ class Scenario extends React.Component { } // get selected scenario - const sessionToken = LoginStore.getState().token; + const sessionToken = localStorage.getItem("token"); const scenario = ScenarioStore.getState().find(s => s.id === parseInt(props.match.params.scenario, 10)); - if (scenario == null) { + if (scenario === undefined) { AppDispatcher.dispatch({ type: 'scenarios/start-load', data: props.match.params.scenario, @@ -118,14 +117,14 @@ class Scenario extends React.Component { //load selected scenario AppDispatcher.dispatch({ type: 'scenarios/start-load', - data: this.state.scenario.id, + data: parseInt(this.props.match.params.scenario, 10), token: this.state.sessionToken }); AppDispatcher.dispatch({ type: 'scenarios/start-load-users', - data: this.state.scenario.id, + data: parseInt(this.props.match.params.scenario, 10), token: this.state.sessionToken }); @@ -418,7 +417,7 @@ class Scenario extends React.Component { this.setState({editOutputSignalsModal: false}); } } - + onEditFiles(){ let tempFiles = []; this.state.files.forEach( file => { @@ -508,10 +507,14 @@ class Scenario extends React.Component { const iconStyle = { color: '#007bff', - height: '25px', + height: '25px', width : '25px' } + if(this.state.scenario === undefined){ + return

    Loading Scenario...

    ; + } + return
    Add, edit or delete files of scenario } > @@ -655,7 +658,7 @@ class Scenario extends React.Component {

    Users sharing this scenario

    - + ); + return (); } return ( diff --git a/src/user/user.js b/src/user/user.js index 6ab4b82..6c7e0df 100644 --- a/src/user/user.js +++ b/src/user/user.js @@ -20,10 +20,8 @@ import { Container } from 'flux/utils'; import {Button, Col, Row} from 'react-bootstrap'; import AppDispatcher from '../common/app-dispatcher'; -import LoginStore from './login-store'; import UsersStore from './users-store'; - import Icon from '../common/icon'; import EditOwnUserDialog from './edit-own-user' import NotificationsDataManager from "../common/data-managers/notifications-data-manager" @@ -31,17 +29,15 @@ import NotificationsDataManager from "../common/data-managers/notifications-data class User extends Component { static getStores() { - return [ LoginStore, UsersStore ]; + return [ UsersStore ]; } static calculateState(prevState, props) { prevState = prevState || {}; - let user = LoginStore.getState().currentUser; - return { - currentUser: user, - token: LoginStore.getState().token, + currentUser: JSON.parse(localStorage.getItem("currentUser")), + token: localStorage.getItem("token"), editModal: false, }; } diff --git a/src/user/users.js b/src/user/users.js index d97c539..f6f03df 100644 --- a/src/user/users.js +++ b/src/user/users.js @@ -20,7 +20,6 @@ import { Container } from 'flux/utils'; import { Button } from 'react-bootstrap'; import AppDispatcher from '../common/app-dispatcher'; -import LoginStore from './login-store'; import UsersStore from './users-store'; import Icon from '../common/icon'; @@ -34,23 +33,23 @@ import NotificationsDataManager from "../common/data-managers/notifications-data class Users extends Component { static getStores() { - return [ LoginStore, UsersStore ]; + return [ UsersStore ]; } static calculateState(prevState, props) { - let tokenState = LoginStore.getState().token; + let token = localStorage.getItem("token"); // If there is a token available and this method was called as a result of loading users - if (!prevState && tokenState) { + if (!prevState && token) { AppDispatcher.dispatch({ type: 'users/start-load', - token: tokenState + token: token }); } return { - token: tokenState, + token: token, users: UsersStore.getState(), newModal: false,