diff --git a/src/app.js b/src/app.js index 9f1e67d..970b4f4 100644 --- a/src/app.js +++ b/src/app.js @@ -20,27 +20,22 @@ import { DndProvider } from 'react-dnd'; import { HTML5Backend }from 'react-dnd-html5-backend'; import NotificationSystem from 'react-notification-system'; import { Redirect, Route } from 'react-router-dom'; -import jwt from 'jsonwebtoken' - -import AppDispatcher from './common/app-dispatcher'; +import jwt from 'jsonwebtoken'; import NotificationsDataManager from './common/data-managers/notifications-data-manager'; - import Home from './common/home'; import Header from './common/header'; import Menu from './common/menu'; - import InfrastructureComponent from './pages/infrastructure/ic'; -import Dashboard from './dashboard/dashboard'; -import Scenarios from './scenario/scenarios'; -import Scenario from './scenario/scenario'; -import Users from './user/users'; -import User from './user/user'; +import Scenarios from './pages/scenarios/scenarios'; import APIBrowser from './common/api-browser'; - - +import Scenario from './pages/scenarios/scenario'; +import Users from './pages/users/users'; +import Dashboard from './pages/dashboards/dashboard'; +import Account from './pages/account/account'; import './styles/app.css'; import './styles/login.css'; import branding from './branding/branding'; +import Logout from './pages/login/logout'; import Infrastructure from './pages/infrastructure/infrastructure' @@ -54,31 +49,7 @@ class App extends React.Component { componentDidMount() { NotificationsDataManager.setSystem(this.refs.notificationSystem); - - AppDispatcher.dispatch({ - type: 'config/load', - }); - - // if token stored locally, we are already logged-in let token = localStorage.getItem("token"); - if (token != null && token !== '') { - - let isExpired = this.tokenIsExpired(token); - if (isExpired) { - console.log("Token expired") - AppDispatcher.dispatch({ - type: 'users/logout' - }); - } else { - let currentUser = JSON.parse(localStorage.getItem("currentUser")); - console.log("Logged-in as user ", currentUser.username) - AppDispatcher.dispatch({ - type: 'users/logged-in', - token: token, - currentUser: currentUser - }); - } - } } tokenIsExpired(token){ @@ -114,10 +85,21 @@ class App extends React.Component { { pages.home ? : '' } { pages.scenarios ? <> - - - - + + + + + + + + + + + + + + + : '' } { currentUser.role === "Admin" || pages.infrastructure ? <> @@ -129,9 +111,11 @@ class App extends React.Component { : '' } - { pages.account ? : '' } + { pages.account ? : '' } { currentUser.role === "Admin" ? - + + + : '' } { currentUser.role === "Admin" || pages.api ? @@ -145,5 +129,4 @@ class App extends React.Component { } } - -export default App +export default App; diff --git a/src/common/api/login-store.js b/src/common/api/login-store.js new file mode 100644 index 0000000..f5cea52 --- /dev/null +++ b/src/common/api/login-store.js @@ -0,0 +1,91 @@ +/** + * 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 { ReduceStore } from 'flux/utils'; + +import AppDispatcher from '../common/app-dispatcher'; +import UsersDataManager from './users-data-manager'; +import ICDataDataManager from '../ic/ic-data-data-manager'; +import ConfigReader from '../config-reader'; + +class LoginStore extends ReduceStore { + constructor() { + super(AppDispatcher); + } + + getInitialState() { + return { + currentUser: null, + token: null, + loginMessage: null, + config: null, + }; + } + + reduce(state, action) { + switch (action.type) { + case 'config/load': + ConfigReader.loadConfig(); + return state; + + case 'config/loaded': + return Object.assign({}, state, { config: action.data }); + + case 'config/load-error': + return Object.assign({}, state, { config: null}); + + case 'users/login': + UsersDataManager.login(action.username, action.password); + return Object.assign({}, state, { loginMessage: null }); + + case 'users/extlogin': + UsersDataManager.login(); + return Object.assign({}, state, { loginMessage: null }); + + case 'users/logout': + // disconnect from all infrastructure components + ICDataDataManager.closeAll(); + //remove token and current user from local storage + localStorage.clear(); + + // delete user, token and loginMessage + return Object.assign({}, state, { token: null, currentUser: null, loginMessage: null}); + + case 'users/logged-in': + // save login data in local storage and loginStore + let newState = state + if (action.token != null){ + localStorage.setItem('token', action.token); + newState = Object.assign({}, state, {token: action.token}) + } + localStorage.setItem('currentUser', JSON.stringify(action.currentUser)); + return Object.assign({}, newState, { currentUser: action.currentUser}); + + case 'users/login-error': + if (action.error && !action.error.handled) { + // If it was an error and hasn't been handled, the credentials must have been wrong. + state = Object.assign({}, state, { loginMessage: 'Wrong credentials! Please try again.' }); + } + return state; + + default: + return state; + } + } +} + +export default new LoginStore(); diff --git a/src/common/menu.js b/src/common/menu.js index 60506e7..93488a1 100644 --- a/src/common/menu.js +++ b/src/common/menu.js @@ -16,210 +16,187 @@ ******************************************************************************/ import React from 'react'; +import { useEffect, useState } from 'react'; import { NavLink } from 'react-router-dom'; import branding from '../branding/branding'; -import { Container } from 'flux/utils'; -import LoginStore from '../user/login-store'; -import AppDispatcher from './app-dispatcher'; +import { useGetConfigQuery } from '../store/apiSlice'; +import { currentUser } from '../localStorage'; +const SideBarMenu = (props) => { -class SidebarMenu extends React.Component { - constructor(props) { - super(props); + const values = branding.values; + const [isExternalAuth, setIsExternalAuth] = useState(false); + const [logoutLink, setLogoutLink] = useState(''); - this.state = { - externalAuth: false, - logoutLink: "", + const {data: configRes} = useGetConfigQuery(); + + useEffect(() => { + if(configRes) { + setLogoutLink(configRes.authentication.logout_url); } + }, [configRes]) + + const logout = async () => { + } - static getStores() { - return [LoginStore] - } + const getLinks = () => { + let links = []; - static calculateState(prevState, props) { - let config = LoginStore.getState().config; - let externalauth = _.get(config, ['authentication', 'external', 'enabled']); - let logout_url = _.get(config, ['authentication', 'logout_url']); - - if (externalauth && logout_url) { - return { - externalAuth: true, - logoutLink: logout_url, - } - } - - return { - externalAuth: false, - logoutLink: "/logout", - } - } - - logout() { - AppDispatcher.dispatch({ - type: 'users/logout' - }); - // The Login Store and local storage are deleted automatically - } - - render() { - const values = branding.values; - let links = [] if (values.links) { Object.keys(values.links).forEach(key => { links.push(
  • {key}
  • ); }) } - var logoStyle = { width: 110, margin: 'auto' }; - var logo = branding.getLogo(logoStyle); - return ( -
    - { logo ? -
    - {logo} -
    - : '' - } -
    -

    Menu

    + return links; + } - {this.state.externalAuth ? -
      - : '' + } +
    } + { + getLinks().length > 0 ? +
    +

    +

    Links

    +
      {getLinks()}
    +
    + : '' + }
    - ); - } + + +
    + ); } -let fluxContainerConverter = require('../common/FluxContainerConverter'); -export default Container.create(fluxContainerConverter.convert(SidebarMenu)); +export default SideBarMenu; diff --git a/src/index.js b/src/index.js index a899895..98db39e 100644 --- a/src/index.js +++ b/src/index.js @@ -17,13 +17,9 @@ import React from "react"; import ReactDOM from "react-dom"; - import Router from "./router"; - -// Redux import { Provider } from "react-redux"; import {store} from "./store/index"; - import "bootstrap/dist/css/bootstrap.css"; import "./styles/index.css"; diff --git a/src/pages/login/login-form.js b/src/pages/login/login-form.js index 5ce50d9..26dbc1e 100644 --- a/src/pages/login/login-form.js +++ b/src/pages/login/login-form.js @@ -17,8 +17,7 @@ import React, { useState, useEffect } from 'react'; import { Form, Button, Col } from 'react-bootstrap'; -import RecoverPassword from '../../user/recover-password' -import { useDispatch } from 'react-redux' +import { useDispatch } from 'react-redux'; import { login } from '../../store/userSlice'; import _ from 'lodash'; @@ -84,7 +83,7 @@ const LoginForm = (props) => { - setForgottenPassword(false)} sessionToken={props.sessionToken} /> + {/* setForgottenPassword(false)} sessionToken={props.sessionToken} /> */} ); diff --git a/src/pages/login/login.js b/src/pages/login/login.js index dc6d33a..3a202b6 100644 --- a/src/pages/login/login.js +++ b/src/pages/login/login.js @@ -19,30 +19,18 @@ import React, {useEffect, useRef} from 'react'; import { NavbarBrand } from 'react-bootstrap'; import NotificationSystem from 'react-notification-system'; import { Redirect } from 'react-router-dom'; - import { useSelector } from 'react-redux'; - import LoginForm from './login-form'; import Header from '../../common/header'; import NotificationsDataManager from '../../common/data-managers/notifications-data-manager'; -import AppDispatcher from '../../common/app-dispatcher'; import branding from '../../branding/branding'; const Login = (props) => { const notificationSystem = useRef() - useEffect(() => { NotificationsDataManager.setSystem(notificationSystem); - - console.log("redirected to login", currentUser) - - // load config in case the user goes directly to /login - // otherwise it will be loaded in app constructor - AppDispatcher.dispatch({ - type: 'config/load', - }); }, []); const config = null @@ -63,7 +51,6 @@ const Login = (props) => {
    Login -
    diff --git a/src/pages/login/logout.js b/src/pages/login/logout.js index ac5dae6..d6b2741 100644 --- a/src/pages/login/logout.js +++ b/src/pages/login/logout.js @@ -17,7 +17,6 @@ import React, {useEffect} from 'react'; import { Redirect } from 'react-router-dom'; - import { useDispatch } from 'react-redux' import { logout } from '../../store/userSlice'; diff --git a/src/router.js b/src/router.js index 798093b..ca4b07f 100644 --- a/src/router.js +++ b/src/router.js @@ -20,14 +20,12 @@ import { BrowserRouter, Route, Switch } from "react-router-dom"; import App from "./app"; import Login from "./pages/login/login"; import Logout from "./pages/login/logout"; -import LoginComplete from "./user/login-complete"; class Root extends React.Component { render() { return ( -