1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/web/ synced 2025-03-09 00:00:01 +01:00

Merge branch 'fix-router' into 'develop'

Fix router

See merge request acs/public/villas/web!61
This commit is contained in:
Sonja Happ 2020-07-21 10:53:55 +02:00
commit c7af7bd82e
12 changed files with 112 additions and 52 deletions

View file

@ -87,8 +87,13 @@ class App extends React.Component {
};
render() {
if (this.state.token == null) {
return (<Redirect to="/login" />);
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 (<Redirect to="/logout" />);
}
return (
@ -99,7 +104,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.currentUser.role} />
<HeaderMenu onClose={this.hideSidebarMenu} currentRole={currentUser.role} />
</Col>
</Hidden>
@ -110,17 +115,17 @@ class App extends React.Component {
<div className={`app-body app-body-spacing`} >
<Col xs={false}>
<SidebarMenu currentRole={this.state.currentUser.role} />
<SidebarMenu currentRole={currentUser.role} />
</Col>
<div className={`app-content app-content-margin-left`}>
<Route exact path="/" component={Home} />
<Route path="/home" component={Home} />
<Route path="/dashboards/:dashboard" component={Dashboard} />
<Route exact path="/scenarios" component={Scenarios} />
<Route path="/scenarios/:scenario" component={Scenario} />
<Route path="/dashboards/:dashboard" component={Dashboard} />
<Route path="/infrastructure" component={InfrastructureComponents} />
<Route path="/user" component={User} />
<Route path="/account" component={User} />
<Route path="/users" component={Users} />
</div>
</div>

View file

@ -27,11 +27,12 @@ export default class HeaderMenu extends React.Component {
<ul>
<li><NavLink to="/home" activeClassName="active" title="Home" onClick={this.props.onClose}>Home</NavLink></li>
<li><NavLink to="/scenario" activeClassName="active" title="Scenarios" onClick={this.props.onClose}>Scenarios</NavLink></li>
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios" onClick={this.props.onClose}>Scenarios</NavLink></li>
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure Components" onClick={this.props.onClose}>Infrastructure Components</NavLink></li>
{ this.props.currentRole === 'Admin' ?
<li><NavLink to="/users" activeClassName="active" title="User Management" onClick={this.props.onClose}>User Management</NavLink></li> : ''
}
<li><NavLink to="/account" title="Account">Account</NavLink></li>
<li><NavLink to="/logout" title="Logout" onClick={this.props.onClose}>Logout</NavLink></li>
</ul>
</div>;

View file

@ -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 (<Redirect to="/logout" />);
}
return (
<div className="home-container">
<img style={{height: 120, float: 'right'}} src={require('../img/villas_web.svg')} alt="Logo VILLASweb" />
@ -47,7 +55,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.currentUser.username}</b> with <b>ID {this.state.currentUser.id}</b> and role <b>{this.state.currentUser.role}</b>.
You are logged in as user <b>{currentUser.username}</b> with <b>ID {currentUser.id}</b> and role <b>{currentUser.role}</b>.
</p>
<h3>Data Model</h3>

View file

@ -31,7 +31,7 @@ class SidebarMenu extends React.Component {
{ this.props.currentRole === 'Admin' ?
<li><NavLink to="/users" activeClassName="active" title="User Management">User Management</NavLink></li> : ''
}
<li><NavLink to="/user" title="Account">Account</NavLink></li>
<li><NavLink to="/account" title="Account">Account</NavLink></li>
<li><NavLink to="/logout" title="Logout">Logout</NavLink></li>
</ul>
</div>

View file

@ -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<P>, prevState: Readonly<S>, 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 <div className="section-title"> <span>{"Loading Dashboard..."}</span> </div>
}
const grid = this.state.dashboard.grid;
const boxClasses = classNames('section', 'box', { 'fullscreen-padding': this.props.isFullscreen });
let draggable = this.state.editing;

View file

@ -75,7 +75,7 @@ class InfrastructureComponents extends Component {
});
return {
sessionToken: LoginStore.getState().token,
sessionToken: localStorage.getItem("token"),
ics: ics,
modalIC: {},
deleteModal: false,

View file

@ -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 {
<Route path='/login' component={Login} />
<Route path='/logout' component={Logout} />
<Route path='/' component={App} />
<Route path='/home' component={Home} />
<Route path='/scenarios' component={Scenarios} />
<Route path='/scenarios/:scenario' component={Scenario} />
<Route path='/dashboards/:dashboard' component={Dashboard} />
<Route path='/infrastructure' component={InfrastructureComponents} />
<Route path='/users' component={Users} />
<Route path='/account' component={User} />
</Switch>
</BrowserRouter>
);

View file

@ -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 <h1>Loading Scenario...</h1>;
}
return <div className='section'>
<div className='section-buttons-group-right'>
<OverlayTrigger key={0} placement={'bottom'} overlay={<Tooltip id={`tooltip-${"file"}`}> Add, edit or delete files of scenario </Tooltip>} >
@ -655,7 +658,7 @@ class Scenario extends React.Component {
<h2 style={tableHeadingStyle}>Users sharing this scenario</h2>
<div>
<Table data={this.state.scenario.users}>
<TableColumn title='Name' dataKey='username' link='/users/' linkKey='id' />
<TableColumn title='Name' dataKey='username'/>
<TableColumn title='Mail' dataKey='mail' />
<TableColumn
title=''

View file

@ -22,7 +22,6 @@ import FileSaver from 'file-saver';
import AppDispatcher from '../common/app-dispatcher';
import ScenarioStore from './scenario-store';
import LoginStore from '../user/login-store';
import DashboardStore from '../dashboard/dashboard-store';
import WidgetStore from "../widget/widget-store";
import ConfigStore from '../componentconfig/config-store';
@ -41,7 +40,7 @@ import DeleteDialog from '../common/dialogs/delete-dialog';
class Scenarios extends Component {
static getStores() {
return [ScenarioStore, LoginStore, DashboardStore, WidgetStore, ConfigStore, SignalStore];
return [ScenarioStore, DashboardStore, WidgetStore, ConfigStore, SignalStore];
}
static calculateState() {
@ -50,7 +49,7 @@ class Scenarios extends Component {
scenarios: ScenarioStore.getState(),
dashboards: DashboardStore.getState(),
configs: ConfigStore.getState(),
sessionToken: LoginStore.getState().token,
sessionToken: localStorage.getItem("token"),
newModal: false,
deleteModal: false,

View file

@ -73,7 +73,7 @@ class Login extends Component {
render() {
if (this.state.currentUser != null) {
return (<Redirect to="/" />);
return (<Redirect to="/home" />);
}
return (

View file

@ -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,
};
}

View file

@ -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,