diff --git a/.gitignore b/.gitignore index 699692c..bae9627 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ yarn-error.log* .vscode/ *.code-workspace package-lock.json +.eslintcache diff --git a/package.json b/package.json index af5f894..a19b1cc 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, - "proxy": "http://localhost:4000", + "proxy": "https://villas.k8s.eonerc.rwth-aachen.de", "browserslist": { "production": [ ">0.2%", diff --git a/src/app.js b/src/app.js index 90581f7..bf4d491 100644 --- a/src/app.js +++ b/src/app.js @@ -20,7 +20,6 @@ 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 { Col } from 'react-bootstrap'; import { Hidden } from 'react-grid-system' import AppDispatcher from './common/app-dispatcher'; @@ -29,8 +28,7 @@ import NotificationsDataManager from './common/data-managers/notifications-data- import Home from './common/home'; import Header from './common/header'; import Footer from './common/footer'; -import SidebarMenu from './common/menu-sidebar'; -import HeaderMenu from './common/header-menu'; +import Menu from './common/menu'; import InfrastructureComponents from './ic/ics'; import Dashboard from './dashboard/dashboard'; @@ -55,11 +53,8 @@ class App extends React.Component { type: 'config/load', }); - this.state = { - showSidebarMenu: false, - } - this.setBrandingStyle(); + this.state = {} } changeHead() { @@ -128,14 +123,6 @@ class App extends React.Component { } } - showSidebarMenu = () => { - this.setState({ showSidebarMenu: true }); - }; - - hideSidebarMenu = () => { - this.setState({ showSidebarMenu: false }); - }; - render() { let token = localStorage.getItem("token"); @@ -148,46 +135,32 @@ class App extends React.Component { let currentUser = JSON.parse(currentUserRaw); - return ( - -
- {/* - - */} - - - - - + return +
+ +
-
- +
+ -
- -
- - - - -
- - - - - - - - - -
+
+ + + + + + + + +
- -
+ +
- - ) + } } diff --git a/src/branding/branding.js b/src/branding/branding.js index 98f0a12..0d5f4c2 100644 --- a/src/branding/branding.js +++ b/src/branding/branding.js @@ -25,12 +25,15 @@ import { slew_home } from './slew/slew_home'; class Branding { constructor(chosenbrand) { + // TODO: simplify; error only for "wrong" brand, not for missing brand var brand = _.get(brands, [chosenbrand]); if (!brand) { console.error("Branding '" + chosenbrand + "' not available, will use 'villasweb' branding"); brand = _.get(brands, ['villasweb']); chosenbrand = 'villasweb'; this.default = true; + } else if (chosenbrand === 'villasweb') { + this.default = true; } else { this.default = false; } diff --git a/src/branding/villasweb/villasweb-home.js b/src/branding/villasweb/villasweb-home.js index 60b6f06..ffd3734 100644 --- a/src/branding/villasweb/villasweb-home.js +++ b/src/branding/villasweb/villasweb-home.js @@ -18,51 +18,51 @@ import React from 'react'; import { NavLink } from 'react-router-dom'; export function villasweb_home(title, username, userid, role) { - return ( -
- Logo VILLASweb -

Home

-

- Welcome to {title}! -

-

- You are logged in as user {username} with ID {userid} and role {role}. -

-

Credits

-

VILLASweb is an open source project developed by the Institute for Automation of Complex Power Systems at RWTH Aachen University.

- Logo ACS - -

Links

- -

Funding

-

The development of VILLASframework projects has received funding from

-
    -

    SLEW: Second Life for Energiewende, an Exploratory Teaching Space project funded by RWTH Aachen University

    -

    ERIgrid 2.0: An EU Horizon 2020 research and innovation action project for connecting European Smart Grid Infrastructures (grant agreement No 870620)

    -

    - Logo EU - Logo ERIgrid 2.0 -

    -

    Urban Energy Lab 4.0: A project funded by EFRE.NRW (European Regional Development Fund) for the setup of a novel energy research infrastructure.

    -

    - Logo UEL OP EFRE NRW - Logo UEL -

    -

    RESERVE: An EU Horizon 2020 research and innovation project (grant agreement No 727481)

    -

    - Logo EU - Logo RESERVE -

    -

    JARA-ENERGY: Jülich-Aachen Research Alliance (JARA) is an initiative of RWTH Aachen University and Forschungszentrum Jülich.

    -
-
) + return ( +
+ Logo VILLASweb +

Home

+

+ Welcome to {title}! +

+

+ You are logged in as user {username} with ID {userid} and role {role}. +

+

Credits

+

VILLASweb is an open source project developed by the Institute for Automation of Complex Power Systems at RWTH Aachen University.

+ Logo ACS + +

Links

+ +

Funding

+

The development of VILLASframework projects has received funding from

+
    +

    SLEW: Second Life for Energiewende, an Exploratory Teaching Space project funded by RWTH Aachen University

    +

    ERIgrid 2.0: An EU Horizon 2020 research and innovation action project for connecting European Smart Grid Infrastructures (grant agreement No 870620)

    +

    + Logo EU + Logo ERIgrid 2.0 +

    +

    Urban Energy Lab 4.0: A project funded by EFRE.NRW (European Regional Development Fund) for the setup of a novel energy research infrastructure.

    +

    + Logo UEL OP EFRE NRW + Logo UEL +

    +

    RESERVE: An EU Horizon 2020 research and innovation project (grant agreement No 727481)

    +

    + Logo EU + Logo RESERVE +

    +

    JARA-ENERGY: Jülich-Aachen Research Alliance (JARA) is an initiative of RWTH Aachen University and Forschungszentrum Jülich.

    +
+
) } \ No newline at end of file diff --git a/src/common/dialogs/delete-dialog.js b/src/common/dialogs/delete-dialog.js index a4499e5..32e583a 100644 --- a/src/common/dialogs/delete-dialog.js +++ b/src/common/dialogs/delete-dialog.js @@ -16,8 +16,8 @@ ******************************************************************************/ import React from 'react'; -import { Button, Modal, FormLabel } from 'react-bootstrap'; -import {Collapse} from 'react-collapse'; +import { Button, Modal, Form } from 'react-bootstrap'; +import { Collapse } from 'react-collapse'; class DeleteDialog extends React.Component { onModalKeyPress = (event) => { @@ -37,7 +37,7 @@ class DeleteDialog extends React.Component { Are you sure you want to delete the {this.props.title} '{this.props.name}'? - The IC will be deleted if the respective manager sends "gone" state and no component config is using the IC anymore + The IC will be deleted if the respective manager sends "gone" state and no component config is using the IC anymore diff --git a/src/common/dialogs/dialog.js b/src/common/dialogs/dialog.js index 9c5c2ce..7af1406 100644 --- a/src/common/dialogs/dialog.js +++ b/src/common/dialogs/dialog.js @@ -51,7 +51,7 @@ class Dialog extends React.Component { }; return ( - + {this.props.title} diff --git a/src/common/editable-header.js b/src/common/editable-header.js index a10b48d..03a666a 100644 --- a/src/common/editable-header.js +++ b/src/common/editable-header.js @@ -17,7 +17,7 @@ // TODO remove this file (not used!) import React from 'react'; import PropTypes from 'prop-types'; -import { FormControl, Button } from 'react-bootstrap'; +import { Form, Button } from 'react-bootstrap'; import Icon from './icon'; class EditableHeader extends React.Component { @@ -79,12 +79,25 @@ class EditableHeader extends React.Component { }; return
-
- - +
+ + - - + +
; } diff --git a/src/common/header-menu.js b/src/common/header-menu.js deleted file mode 100644 index 9c6f7eb..0000000 --- a/src/common/header-menu.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * 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 from 'react'; -import { Button } from 'react-bootstrap'; -import { NavLink } from 'react-router-dom'; - -export default class HeaderMenu extends React.Component { - render() { - return
- - - -
    -
  • Home
  • -
  • Scenarios
  • -
  • Infrastructure Components
  • - { this.props.currentRole === 'Admin' ? -
  • User Management
  • : '' - } -
  • Account
  • -
  • Logout
  • -
-
; - } -} diff --git a/src/common/header.js b/src/common/header.js index 69b0980..2889202 100644 --- a/src/common/header.js +++ b/src/common/header.js @@ -16,30 +16,16 @@ ******************************************************************************/ import React from 'react'; -import { Col, Button } from 'react-bootstrap'; -import { Hidden } from 'react-grid-system' -import Icon from './icon'; import Branding from '../branding/branding'; class Header extends React.Component { render() { return (
- -

{Branding.instance.brand.title} - {Branding.instance.brand.subtitle}

- - - - {this.props.showMenuButton && - - } - - +

{Branding.instance.brand.title} - {Branding.instance.brand.subtitle}

); } } -export default Header; +export default Header; \ No newline at end of file diff --git a/src/common/icon-button.js b/src/common/icon-button.js new file mode 100644 index 0000000..a3dd0b3 --- /dev/null +++ b/src/common/icon-button.js @@ -0,0 +1,56 @@ +/** + * 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 from 'react'; + +import { Button, Tooltip, OverlayTrigger } from 'react-bootstrap'; + +import Icon from '../common/icon'; + + +class IconButton extends React.Component { + + render() { + const altButtonStyle = { + marginLeft: '10px', + } + + const iconStyle = { + height: '30px', + width: '30px' + } + + return {this.props.tooltip}} > + + + } +} + +export default IconButton; diff --git a/src/common/icon.js b/src/common/icon.js index 25155b4..f062c44 100644 --- a/src/common/icon.js +++ b/src/common/icon.js @@ -21,7 +21,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { library } from '@fortawesome/fontawesome-svg-core'; import { fas } from '@fortawesome/free-solid-svg-icons'; -//import '@fortawesome/free-regular-svg-icons'; library.add(fas); diff --git a/src/common/menu-sidebar.js b/src/common/menu.js similarity index 67% rename from src/common/menu-sidebar.js rename to src/common/menu.js index 41b302f..b82a78b 100644 --- a/src/common/menu-sidebar.js +++ b/src/common/menu.js @@ -74,49 +74,34 @@ class SidebarMenu extends React.Component { }) } - if (this.state.externalAuth) { - return ( -
-

Menu

+ return ( +
+

Menu

+ + {this.state.externalAuth ?
    - - { this.props.currentRole === 'Admin' ? -
  • User Management
  • : '' + + {this.props.currentRole === 'Admin' ? +
  • Users
  • : '' } Logout
- { - links.length > 0 ? -
-

-

Links

-
    {links}
-
- : '' - } -
- ); - } + :
    + + + + {this.props.currentRole === 'Admin' ? +
  • Users
  • : '' + } + +
  • Logout
  • + +
} - return ( -
-

Menu

- -
    - - - - {this.props.currentRole === 'Admin' ? -
  • User Management
  • : '' - } - -
  • Logout
  • - -
{ links.length > 0 ?
@@ -132,4 +117,4 @@ class SidebarMenu extends React.Component { } let fluxContainerConverter = require('../common/FluxContainerConverter'); -export default Container.create(fluxContainerConverter.convert(SidebarMenu)); \ No newline at end of file +export default Container.create(fluxContainerConverter.convert(SidebarMenu)); diff --git a/src/common/table-column.js b/src/common/table-column.js index 460eb4b..fb9905a 100644 --- a/src/common/table-column.js +++ b/src/common/table-column.js @@ -39,16 +39,19 @@ class TableColumn extends Component { checkboxKey: '', checkboxDisabled: null, labelStyle: null, - labelModifier: null - + labelModifier: null, + align: 'left' }; render() { - return ( - - {this.props.title} - - ); + let style = { + textAlign: this.props.align, + width: this.props.width + }; + + return + {this.props.title} + ; } } diff --git a/src/common/table.js b/src/common/table.js index f54335e..686d352 100644 --- a/src/common/table.js +++ b/src/common/table.js @@ -17,7 +17,7 @@ import React, { Component } from 'react'; import _ from 'lodash'; -import { Table, Button, FormControl, FormLabel, FormCheck, Tooltip, OverlayTrigger } from 'react-bootstrap'; +import { Table, Button, Form, Tooltip, OverlayTrigger } from 'react-bootstrap'; import { Link } from 'react-router-dom'; import Icon from './icon'; @@ -39,7 +39,7 @@ class CustomTable extends Component { }; onClick(event, row, column) { - this.setState({ editCell: [column, row] }); // x, y + this.setState({ editCell: [column, row] }); // x, y } static addCell(data, index, child) { @@ -83,12 +83,13 @@ class CustomTable extends Component { Download {contentvalue}} > + overlay={Download {contentvalue}} + > ); @@ -111,56 +112,56 @@ class CustomTable extends Component { cell.push(   - + {labelContent} - + ); } - if (child.props.dataIndex) { cell.push(index); } // add buttons - let showEditButton = true - if (child.props.showEditButton !== null) - { - showEditButton = child.props.showEditButton(index) - } - if(showEditButton){ - if (child.props.editButton) { - cell.push( - Edit }> - - ); - } - } + let showEditButton = child.props.showEditButton !== null + ? child.props.showEditButton(index) + : true; + if (child.props.editButton && showEditButton) { + cell.push( + Edit } + > + + + ); + } if (child.props.checkbox) { const checkboxKey = child.props.checkboxKey; - let isDisabled = false; - if (child.props.checkboxDisabled != null){ - isDisabled = child.props.checkboxDisabled(index) - } + let isDisabled = child.props.checkboxDisabled != null + ? child.props.checkboxDisabled(index) + : false; + cell.push( - child.props.onChecked(data, e)} - />); + /> + ); } if (child.props.exportButton) { @@ -168,14 +169,16 @@ class CustomTable extends Component { Export } > + overlay={ Export } + > - ); + + ); } if (child.props.duplicateButton) { @@ -190,7 +193,8 @@ class CustomTable extends Component { disabled={child.props.onDuplicate == null}> - ); + + ); } if (child.props.addRemoveFilesButton) { @@ -205,7 +209,8 @@ class CustomTable extends Component { disabled={child.props.onAddRemove == null}> - ); + + ); } if (child.props.downloadAllButton) { @@ -220,35 +225,32 @@ class CustomTable extends Component { disabled={child.props.onDownloadAll == null}> - ); + + ); } - let showDeleteButton = true; - if (child.props.showDeleteButton !== null){ - showDeleteButton = child.props.showDeleteButton(index) + let showDeleteButton = child.props.showDeleteButton !== null + ? child.props.showDeleteButton(index) + : true; + + if (child.props.deleteButton && showDeleteButton) { + cell.push( + Delete } > + + + ); } - if (showDeleteButton){ - if (child.props.deleteButton) { - cell.push( - Delete } > - - ); - } - } - - - return cell; - } // addCell + } static getDerivedStateFromProps(props, state) { const rows = CustomTable.getRows(props); @@ -311,49 +313,53 @@ class CustomTable extends Component { { - this.state.rows.map((row, rowIndex) => ( + this.state.rows.map((row, rowIndex) => { row.map((cell, cellIndex) => { let isCellInlineEditable = children[cellIndex].props.inlineEditable === true; - let tabIndex = isCellInlineEditable ? 0 : -1; - let evtHdls = isCellInlineEditable ? { onCellClick: (event) => this.onClick(event, rowIndex, cellIndex), onCellFocus: () => this.onCellFocus({ cell: cellIndex, row: rowIndex }), onCellBlur: () => this.cellLostFocus() } : { - onCellClick: () => { }, - onCellFocus: () => { }, - onCellBlur: () => { } - }; + onCellClick: () => { }, + onCellFocus: () => { }, + onCellBlur: () => { } + }; + let cellStyle = { + textAlign: children[cellIndex].props.align + }; - return ( - {(this.state.editCell[0] === cellIndex && this.state.editCell[1] === rowIndex) ? ( - + {(this.state.editCell[0] === cellIndex && this.state.editCell[1] === rowIndex) ? + children[cellIndex].props.onInlineChange(event, rowIndex, cellIndex)} ref={ref => { this.activeInput = ref; }} /> - ) : ( - - {cell.map((element, elementIndex) => ( + : + { + cell.map((element, elementIndex) => {element} - ))} - - )} - ) + ) + } + + } + }) } - )) + ) } diff --git a/src/componentconfig/edit-config.js b/src/componentconfig/edit-config.js index 2277331..2ee19ec 100644 --- a/src/componentconfig/edit-config.js +++ b/src/componentconfig/edit-config.js @@ -16,8 +16,8 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel} from 'react-bootstrap'; -import { Multiselect } from 'multiselect-react-dropdown' +import { Form } from 'react-bootstrap'; +import { Multiselect } from 'multiselect-react-dropdown' import Dialog from '../common/dialogs/dialog'; import ParametersEditor from '../common/parameters-editor'; @@ -141,29 +141,29 @@ class EditConfigDialog extends React.Component { onReset={() => this.resetState()} valid={this.valid} > -
- - Name - + + Name + this.handleChange(e)} /> - - + + - - Infrastructure Component - + Infrastructure Component + this.handleChange(e)} > {ICOptions} - - + + - - Start Parameters + + Start Parameters this.handleParameterChange(data)} /> - - + + ); } diff --git a/src/componentconfig/import-config.js b/src/componentconfig/import-config.js index b11a69e..2b69d9a 100644 --- a/src/componentconfig/import-config.js +++ b/src/componentconfig/import-config.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -102,15 +102,15 @@ class ImportConfigDialog extends React.Component { onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid} > -
- - Component Configuration File - - + + + Component Configuration File + + - - Name - + Name + this.handleChange(e)} /> - - -
+ + + ); } diff --git a/src/dashboard/dashboard.js b/src/dashboard/dashboard.js index b8a627b..d627c77 100644 --- a/src/dashboard/dashboard.js +++ b/src/dashboard/dashboard.js @@ -22,7 +22,7 @@ import classNames from 'classnames'; import EditWidget from '../widget/edit-widget/edit-widget'; import EditFiles from '../file/edit-files'; -import EditSignalMapping from "../signal/edit-signal-mapping"; +import EditSignalMappingDialog from "../signal/edit-signal-mapping"; import WidgetContextMenu from '../widget/widget-context-menu'; import WidgetToolbox from '../widget/widget-toolbox'; import WidgetArea from '../widget/widget-area'; @@ -569,7 +569,7 @@ class Dashboard extends Component { scenarioID={this.state.dashboard.scenarioID} /> - this.closeEditSignalsModal(direction)} direction="Output" @@ -578,7 +578,7 @@ class Dashboard extends Component { configs={this.state.configs} sessionToken={this.state.sessionToken} /> - this.closeEditSignalsModal(direction)} direction="Input" @@ -587,8 +587,6 @@ class Dashboard extends Component { configs={this.state.configs} sessionToken={this.state.sessionToken} /> - -
; } diff --git a/src/dashboard/edit-dashboard.js b/src/dashboard/edit-dashboard.js index 2df61bf..42b5230 100644 --- a/src/dashboard/edit-dashboard.js +++ b/src/dashboard/edit-dashboard.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -71,14 +71,21 @@ class EditDashboardDialog extends React.Component { render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Name - this.handleChange(e)} /> - - -
+ this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid} + > +
+ + Name + this.handleChange(e)} /> + + +
); } diff --git a/src/dashboard/import-dashboard.js b/src/dashboard/import-dashboard.js index 47e5216..519a552 100644 --- a/src/dashboard/import-dashboard.js +++ b/src/dashboard/import-dashboard.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -100,15 +100,15 @@ class ImportDashboardDialog extends React.Component { onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Dashboard File - this.loadFile(e.target.files)} /> - + + + Dashboard File + this.loadFile(e.target.files)} /> + - - Name - + Name + this.handleChange(e)} /> - - -
+ + +
); } diff --git a/src/dashboard/new-dashboard.js b/src/dashboard/new-dashboard.js index a023ba4..5cc8a3e 100644 --- a/src/dashboard/new-dashboard.js +++ b/src/dashboard/new-dashboard.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -67,14 +67,21 @@ class NewDashboardDialog extends React.Component { render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Name - this.handleChange(e)} /> - - -
+ this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid} + > +
+ + Name + this.handleChange(e)} /> + + +
); } diff --git a/src/file/edit-file-content.js b/src/file/edit-file-content.js index 34a142e..7f9534d 100644 --- a/src/file/edit-file-content.js +++ b/src/file/edit-file-content.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, Button, Col} from 'react-bootstrap'; +import { Form, Button, Col } from 'react-bootstrap'; import AppDispatcher from "../common/app-dispatcher"; import Dialog from '../common/dialogs/dialog'; @@ -28,7 +28,6 @@ class EditFileContent extends React.Component { this.state = { uploadFile: null, - }; } @@ -50,31 +49,33 @@ class EditFileContent extends React.Component { this.setState({ uploadFile: null }); }; - onClose = () => { this.props.onClose(); }; - - - render() { - return this.onClose()} blendOutCancel = {true} valid={true}> - - this.onClose()} + blendOutCancel = {true} + valid={true} + > + + this.selectUploadFile(event)} /> - + - + - - + ; } } diff --git a/src/file/edit-files.js b/src/file/edit-files.js index d15102b..dca4f28 100644 --- a/src/file/edit-files.js +++ b/src/file/edit-files.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, Button, Col, ProgressBar} from 'react-bootstrap'; +import { Form, Button, Col, ProgressBar } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; import AppDispatcher from "../common/app-dispatcher"; import Table from "../common/table"; @@ -27,7 +27,6 @@ import EditFileContent from "./edit-file-content"; class EditFilesDialog extends React.Component { valid = true; - constructor(props) { super(props); @@ -40,7 +39,6 @@ class EditFilesDialog extends React.Component { } onClose() { - this.props.onClose(); } @@ -71,29 +69,17 @@ class EditFilesDialog extends React.Component { } else { this.setState({ uploadProgress: 0 }); } - }; clearProgress = (newFileID) => { - /*if (this.props.onChange != null) { - let event = {} - event["target"] = {} - event.target["value"] = newFileID - this.props.onChange(event); - } - */ this.setState({ uploadProgress: 0 }); - - }; - closeEditModal(){ - - this.setState({editModal: false}); + closeEditModal() { + this.setState({editModal: false}); } deleteFile(index){ - let file = this.props.files[index] AppDispatcher.dispatch({ type: 'files/start-remove', @@ -102,9 +88,7 @@ class EditFilesDialog extends React.Component { }); } - render() { - let fileOptions = []; if (this.props.files.length > 0){ fileOptions.push( @@ -122,33 +106,51 @@ class EditFilesDialog extends React.Component { marginTop: '-40px' }; - return ( - this.onClose()} blendOutCancel = {true} valid={true} size = 'lg'> -
+ this.onClose()} + blendOutCancel = {true} + valid={true} + > + + + + + + this.deleteFile(index)} + editButton + onEdit={index => this.setState({ editModal: true, modalFile: this.props.files[index] })} + /> +
- - - - - - this.deleteFile(index)} - editButton - onEdit={index => this.setState({ editModal: true, modalFile: this.props.files[index] })} - /> -
+ + this.selectUploadFile(event)} + /> + - - this.selectUploadFile(event)} /> - - - +
- - ); } } diff --git a/src/file/select-file.js b/src/file/select-file.js index bf7469a..42c9c54 100644 --- a/src/file/select-file.js +++ b/src/file/select-file.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, Button, Col, ProgressBar } from 'react-bootstrap'; +import { Form, Button, Col, ProgressBar } from 'react-bootstrap'; import AppDispatcher from '../common/app-dispatcher'; class SelectFile extends React.Component { @@ -88,39 +88,39 @@ class SelectFile extends React.Component { }; return
- - + + {this.props.name} - + - - + this.props.onChange(event)}> {fileOptions} - - - + + + - - + this.selectUploadFile(event)} /> - + - + - + - + - +
; } diff --git a/src/ic/edit-ic.js b/src/ic/edit-ic.js index 69ba89b..be77e27 100644 --- a/src/ic/edit-ic.js +++ b/src/ic/edit-ic.js @@ -16,9 +16,8 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, FormCheck } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import _ from 'lodash'; -import {Collapse} from 'react-collapse'; import Dialog from '../common/dialogs/dialog'; import ParametersEditor from '../common/parameters-editor'; @@ -37,7 +36,8 @@ class EditICDialog extends React.Component { type: '', category: '', managedexternally: false, - startParameterScheme: {}, + startParameterSchema: {}, + properties: {} }; } @@ -50,14 +50,9 @@ class EditICDialog extends React.Component { data.name = this.state.name; } - data.websocketurl = this.state.websocketurl; - - - data.apiurl = this.state.apiurl; - if (this.state.location != null && this.state.location !== this.props.ic.location) { data.location = this.state.location; } @@ -73,13 +68,17 @@ class EditICDialog extends React.Component { if (this.state.category != null && this.state.category !== "" && this.state.category !== this.props.ic.category) { data.category = this.state.category; } - if (this.state.startParameterScheme !== {}) { - data.startParameterScheme = this.state.startParameterScheme + + if (this.state.startParameterSchema !== {}) { + data.startParameterSchema = this.state.startParameterSchema; + } + + if (this.state.properties !== {}) { + data.properties = this.state.properties; } data.managedexternally = this.state.managedexternally; - this.props.onClose(data); this.setState({managedexternally: false}); } @@ -98,8 +97,12 @@ class EditICDialog extends React.Component { } } - handleStartParameterSchemeChange(data) { - this.setState({ startParameterScheme: data }); + handleStartParameterSchemaChange(data) { + this.setState({ startParameterSchema: data }); + } + + handlePropertiesChange(data) { + this.setState({ properties: data }); } resetState() { @@ -112,7 +115,8 @@ class EditICDialog extends React.Component { description: this.props.ic.description, category: this.props.ic.category, managedexternally: false, - startParameterScheme: this.props.ic.startParameterScheme, + startParameterSchema: this.props.ic.startParameterSchema, + properties: this.props.ic.properties, }); } @@ -120,7 +124,7 @@ class EditICDialog extends React.Component { let typeOptions = []; switch(this.state.category){ case "simulator": - typeOptions = ["dummy","generic","dpsim","rtlab","rscad", "opalrt"]; + typeOptions = ["dummy","generic","dpsim","rtlab","rscad","rtlab","kubernetes"]; break; case "manager": typeOptions = ["villas-node","villas-relay","generic"]; @@ -145,63 +149,70 @@ class EditICDialog extends React.Component { onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid} - size='lg' > -
- UUID: {this.props.ic.uuid} - - Name - this.handleChange(e)} /> - - - - Category - this.handleChange(e)}> + + UUID: {this.props.ic.uuid} + + Name + this.handleChange(e)} /> + + + + Category + this.handleChange(e)}> - - - - Type - this.handleChange(e)}> + + + + Type + this.handleChange(e)}> {typeOptions.map((name,index) => ( ))} - - - - Websocket URL - this.handleChange(e)} /> - - - - API URL - this.handleChange(e)} /> - - - - Location - this.handleChange(e)} /> - - - - Description - this.handleChange(e)} /> - - - - Start parameter scheme of IC + + + + Websocket URL + this.handleChange(e)} /> + + + + API URL + this.handleChange(e)} /> + + + + Location + this.handleChange(e)} /> + + + + Description + this.handleChange(e)} /> + + + + Start parameter schema of IC this.handleStartParameterSchemeChange(data)} + onChange={(data) => this.handleStartParameterSchemaChange(data)} /> - -
+ + + Properties + this.handlePropertiesChange(data)} + /> + +
); } diff --git a/src/ic/ic-action.js b/src/ic/ic-action.js index 2d08af4..df4c17f 100644 --- a/src/ic/ic-action.js +++ b/src/ic/ic-action.js @@ -16,23 +16,24 @@ ******************************************************************************/ import React from 'react'; -import { Button, DropdownButton, Dropdown, InputGroup, FormControl } from 'react-bootstrap'; +import { Form, SplitButton, Dropdown } from 'react-bootstrap'; import AppDispatcher from "../common/app-dispatcher"; import NotificationsFactory from "../common/data-managers/notifications-factory"; import NotificationsDataManager from "../common/data-managers/notifications-data-manager"; + +Number.prototype.pad = function(size) { + var s = String(this); + while (s.length < (size || 2)) { + s = "0" + s; + } + return s; +} + class ICAction extends React.Component { constructor(props) { super(props); - let t = new Date() - - Number.prototype.pad = function(size) { - var s = String(this); - while (s.length < (size || 2)) {s = "0" + s;} - return s; - } - let time = new Date(); time.setMinutes(5 * Math.round(time.getMinutes() / 5 + 1)) @@ -55,13 +56,12 @@ class ICAction extends React.Component { } runAction(action, when) { - if (action.data.action === 'none') { console.warn("No command selected. Nothing was sent."); return; } - if (!this.props.hasConfigs){ + if (!this.props.configs) { let newAction = {}; newAction["action"] = action.data.action newAction["when"] = when @@ -71,38 +71,29 @@ class ICAction extends React.Component { let icID = ic.id; /* VILLAScontroller protocol - see: https://villas.fein-aachen.org/doc/controller-protocol.html + * see: https://villas.fein-aachen.org/doc/controller-protocol.html + */ - RESET SHUTDOWN - { - "action": "reset/shutdown/stop/pause/resume" - "when": "1234567" - } - - DELETE - { - "action": "delete" - "parameters":{ - "uuid": "uuid-of-the-manager-for-this-IC" - } - "when": "1234567" - } - - CREATE is not possible within ICAction (see add IC) - */ - - if (newAction.action === "delete"){ + if (newAction.action == "create" || newAction.action === "delete") { // prepare parameters for delete incl. correct IC id newAction["parameters"] = {}; - newAction.parameters["uuid"] = ic.uuid; + + if (newAction.action == "delete") { + newAction.parameters["uuid"] = ic.uuid; + } + else if (newAction.action == "create") { + newAction.parameters = ic.statusupdateraw.properties; + } + // get the ID of the manager IC let managerIC = null; - for (let i of this.props.ics){ - if (i.uuid === ic.manager){ + for (let i of this.props.ics) { + if (i.uuid === ic.manager) { managerIC = i; } } - if (managerIC == null){ + + if (managerIC == null) { NotificationsDataManager.addNotification(NotificationsFactory.DELETE_ERROR("Could not find manager IC with UUID " + ic.manager)); continue; } @@ -120,38 +111,9 @@ class ICAction extends React.Component { } // end for loop over selected ICs } else { - - /*VILLAScontoller protocol - see: https://villas.fein-aachen.org/doc/controller-protocol.html - * - * STOP PAUSE RESUME - { - "action": "reset/shutdown/stop/pause/resume" - "when": "1234567" - } - * - * START - { - "action": "start" - "when": 1234567 - "parameters": { - Start parameters for this IC as configured in the component config - } - "model": { - "type": "url" - "url": "https://villas.k8s.eonerc.rwth-aachen.de/api/v2/files/{fileID}" where fileID is the model file configured in the component config - "token": "asessiontoken" - } - "results":{ - "type": "url" - "url" : "https://villas.k8s.eonerc.rwth-aachen.de/api/v2/results/{resultID}/file" where resultID is the ID of the result created for this run - "token": "asessiontoken" - } - } - * - * - * */ - + /* VILLAScontoller protocol + * see: https://villas.fein-aachen.org/doc/controller-protocol.html + */ let newActions = []; for (let config of this.props.selectedConfigs) { @@ -177,14 +139,13 @@ class ICAction extends React.Component { if (newAction.action === 'start') { newAction["parameters"] = config.startParameters; - - if (config.fileIDs.length > 0){ + if (config.fileIDs && config.fileIDs.length > 0) { newAction["model"] = {} - newAction.model["type"] = "url" + newAction.model["type"] = "url-list" newAction.model["token"] = this.props.token let fileURLs = [] - for (let fileID of config.fileIDs){ + for (let fileID of config.fileIDs) { fileURLs.push("/files/" + fileID.toString()) } newAction.model["url"] = fileURLs @@ -194,7 +155,6 @@ class ICAction extends React.Component { newAction.results["type"] = "url" newAction.results["token"] = this.props.token newAction.results["url"] = "/results/RESULTID/file" // RESULTID serves as placeholder and is replaced later - } // add the new action @@ -202,11 +162,10 @@ class ICAction extends React.Component { } // end for loop over selected configs - let newResult = {} newResult["result"] = {} - if (action.data.action === 'start') { + if (action.data.action === 'start') { let configSnapshots = []; // create config snapshots in case action is start for (let config of this.props.selectedConfigs) { @@ -220,7 +179,6 @@ class ICAction extends React.Component { newResult.result["configSnapshots"] = configSnapshots } - console.log("Dispatching actions for configs", newActions, newResult) AppDispatcher.dispatch({ type: 'ics/start-action', @@ -246,13 +204,15 @@ class ICAction extends React.Component { render() { - let sendCommandDisabled = false; - if (!this.props.hasConfigs && this.props.selectedICs.length === 0 || this.state.selectedAction == null || this.state.selectedAction.id === "-1"){ - sendCommandDisabled = true; - } - if (this.props.hasConfigs && this.props.selectedConfigs.length === 0|| this.state.selectedAction == null || this.state.selectedAction.id === "-1"){ - sendCommandDisabled = true; - } + let disabled = this.state.selectedAction == null || + (this.props.configs + ? this.props.selectedConfigs.length === 0 + : this.props.selectedICs.length === 0 + ); + + let splitButtonStyle = { + marginLeft: '10px' + }; let time = this.state.time.getFullYear().pad(4) + '-' + this.state.time.getMonth().pad(2) + '-' + @@ -266,29 +226,25 @@ class ICAction extends React.Component { )); - return
- - - - {actionList} - - - - - - Select time for synced command execution -
; + return
+
+ + this.runAction(this.state.selectedAction, this.state.time)}> + {actionList} + + + Select time for synced command execution +
; } } diff --git a/src/ic/ic-dialog.js b/src/ic/ic-dialog.js index cba6291..197eb45 100644 --- a/src/ic/ic-dialog.js +++ b/src/ic/ic-dialog.js @@ -1,11 +1,11 @@ import React from 'react'; -import {Button, Row, Col} from 'react-bootstrap'; +import { Button, Row, Col } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; import Icon from "../common/icon"; import ConfirmCommand from './confirm-command'; import ReactJson from 'react-json-view'; import FileSaver from 'file-saver'; - +import moment from 'moment'; class ICDialog extends React.Component { valid = true; @@ -46,7 +46,6 @@ class ICDialog extends React.Component { FileSaver.saveAs(blob, this.props.ic.name + ".svg"); } - render() { let graphURL = "" @@ -54,11 +53,10 @@ class ICDialog extends React.Component { graphURL = this.props.ic.apiurl + "/graph.svg" } - return ( this.onClose(c)} valid={true} @@ -68,27 +66,62 @@ class ICDialog extends React.Component {
-
State: {this.props.ic.state}
-
Category: {this.props.ic.category}
-
Type: {this.props.ic.type}
-
Uptime: {this.props.ic.uptime}
-
Location: {this.props.ic.location}
-
Description: {this.props.ic.description}
-
Websocket URL: {this.props.ic.websocketurl}
-
API URL: {this.props.ic.apiurl}
-
Start parameter scheme:
- + + Name + {this.props.ic.name} + + + UUID + {this.props.ic.uuid} + + + State + {this.props.ic.state} + + + Category + {this.props.ic.category} + + + Type + {this.props.ic.type} + + + Uptime + {moment.duration(this.props.ic.uptime, "seconds").humanize()} + + + Location + {this.props.ic.location} + + + Description + {this.props.ic.description} + + + Websocket URL + {this.props.ic.websocketurl} + + + API URL + {this.props.ic.apiurl} + + + Start parameter schema + + + + -
Raw Status:
- {this.props.ic.type === "villas-node" || this.props.ic.type === "villas-relay" ? ( + {this.props.ic.type === "villas-node" ? <>
- {this.props.userRole === "Admin" ? ( -
-
Controls:
-
- - -
-
) - : (
)} - + {this.props.user.role === "Admin" ? +
+
Controls:
+
+ + +
+
+ :
+ } this.closeConfirmModal(c)}/> - - ) : (
)} + + :
+ }
- ); } } diff --git a/src/ic/ic-store.js b/src/ic/ic-store.js index b852b94..d892c7d 100644 --- a/src/ic/ic-store.js +++ b/src/ic/ic-store.js @@ -117,12 +117,7 @@ class InfrastructureComponentStore extends ArrayStore { if(!tempIC.managedexternally){ tempIC.state = action.data.state; tempIC.uptime = action.data.time_now - action.data.time_started; - if (tempIC.statusupdateraw === null || tempIC.statusupdateraw === undefined){ - tempIC.statusupdateraw = {}; - tempIC.statusupdateraw["status"] = action.data; - } else { - tempIC.statusupdateraw["status"] = action.data; - } + tempIC.statusupdateraw = action.data AppDispatcher.dispatch({ type: 'ics/start-edit', data: tempIC, @@ -138,12 +133,10 @@ class InfrastructureComponentStore extends ArrayStore { case 'ics/nodestats-received': let tempIC2 = action.ic; if(!tempIC2.managedexternally){ - if (tempIC2.statusupdateraw === null || tempIC2.statusupdateraw === undefined){ + if (tempIC2.statusupdateraw === null || tempIC2.statusupdateraw === undefined) { tempIC2.statusupdateraw = {}; - tempIC2.statusupdateraw["statistics"] = action.data; - } else { - tempIC2.statusupdateraw["statistics"] = action.data; } + tempIC2.statusupdateraw["statistics"] = action.data; AppDispatcher.dispatch({ type: 'ics/start-edit', data: tempIC2, diff --git a/src/ic/ics.js b/src/ic/ics.js index 6152c17..b0a5016 100644 --- a/src/ic/ics.js +++ b/src/ic/ics.js @@ -17,7 +17,7 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import {Button, Badge, Tooltip, OverlayTrigger} from 'react-bootstrap'; +import { Button, Badge } from 'react-bootstrap'; import FileSaver from 'file-saver'; import _ from 'lodash'; import moment from 'moment' @@ -38,6 +38,7 @@ import ICAction from './ic-action'; import DeleteDialog from '../common/dialogs/delete-dialog'; import NotificationsDataManager from "../common/data-managers/notifications-data-manager"; import NotificationsFactory from "../common/data-managers/notifications-factory"; +import IconButton from '../common/icon-button'; class InfrastructureComponents extends Component { static getStores() { @@ -64,7 +65,11 @@ class InfrastructureComponents extends Component { } } - static calculateState() { + static calculateState(prevState, props) { + if (prevState == null) { + prevState = {}; + } + const ics = InfrastructureComponentStore.getState().sort((a, b) => { if (a.state !== b.state) { return InfrastructureComponents.statePrio(a.state) > InfrastructureComponents.statePrio(b.state); @@ -88,7 +93,6 @@ class InfrastructureComponents extends Component { let services = ics.filter(ic => ic.category === "service") let equipment = ics.filter(ic => ic.category === "equipment") - return { sessionToken: localStorage.getItem("token"), ics: ics, @@ -101,7 +105,7 @@ class InfrastructureComponents extends Component { modalIC: {}, deleteModal: false, icModal: false, - selectedICs: [], + selectedICs: prevState.selectedICs || [], currentUser: JSON.parse(localStorage.getItem("currentUser")) }; } @@ -112,7 +116,7 @@ class InfrastructureComponents extends Component { token: this.state.sessionToken, }); - // Start timer for periodic refresh + // Start timer for periodic refresh this.timer = window.setInterval(() => this.refresh(), 10000); } @@ -121,7 +125,6 @@ class InfrastructureComponents extends Component { } refresh() { - if (this.state.editModal || this.state.deleteModal || this.state.icModal){ // do nothing since a dialog is open at the moment } @@ -160,8 +163,9 @@ class InfrastructureComponents extends Component { } else { // externally managed IC: dispatch create action to selected manager let newAction = {}; + newAction["action"] = "create"; - newAction["parameters"] = data; + newAction["parameters"] = data.parameters; newAction["when"] = new Date() // find the manager IC @@ -178,7 +182,6 @@ class InfrastructureComponents extends Component { result: null, token: this.state.sessionToken }); - } } } @@ -240,7 +243,6 @@ class InfrastructureComponents extends Component { } onICChecked(ic, event) { - let index = this.state.ics.indexOf(ic); const selectedICs = Object.assign([], this.state.selectedICs); for (let key in selectedICs) { @@ -266,8 +268,6 @@ class InfrastructureComponents extends Component { this.setState({ selectedICs: selectedICs }); } - - static isICOutdated(component) { if (!component.stateUpdateAt) return true; @@ -323,18 +323,18 @@ class InfrastructureComponents extends Component { style.push('badge-default'); /* Possible states of ICs - * 'error': ['resetting', 'error'], - 'idle': ['resetting', 'error', 'idle', 'starting', 'shuttingdown'], - 'starting': ['resetting', 'error', 'running'], - 'running': ['resetting', 'error', 'pausing', 'stopping'], - 'pausing': ['resetting', 'error', 'paused'], - 'paused': ['resetting', 'error', 'resuming', 'stopping'], - 'resuming': ['resetting', 'error', 'running'], - 'stopping': ['resetting', 'error', 'idle'], - 'resetting': ['resetting', 'error', 'idle'], - 'shuttingdown': ['shutdown', 'error'], - 'shutdown': ['starting', 'error'] - * */ + * 'error': ['resetting', 'error'], + * 'idle': ['resetting', 'error', 'idle', 'starting', 'shuttingdown'], + * 'starting': ['resetting', 'error', 'running'], + * 'running': ['resetting', 'error', 'pausing', 'stopping'], + * 'pausing': ['resetting', 'error', 'paused'], + * 'paused': ['resetting', 'error', 'resuming', 'stopping'], + * 'resuming': ['resetting', 'error', 'running'], + * 'stopping': ['resetting', 'error', 'idle'], + * 'resetting': ['resetting', 'error', 'idle'], + * 'shuttingdown': ['shutdown', 'error'], + * 'shutdown': ['starting', 'error'] + */ } return style.join(' ') @@ -409,6 +409,13 @@ class InfrastructureComponents extends Component { onChecked={(ic, event) => this.onICChecked(ic, event)} width='30' /> + {this.state.currentUser.role === "Admin" ? + + : <> + } this.isLocalIC(index, ics)} exportButton @@ -481,26 +489,23 @@ class InfrastructureComponents extends Component { return (
-

Infrastructure Components +

Infrastructure {this.state.currentUser.role === "Admin" ? - ( - Add Infrastructure Component } > - - - Import Infrastructure Component } > - - - ) - : - ( ) + + this.setState({newModal: true})} + icon='plus' + /> + this.setState({importModal: true})} + icon='upload' + /> + + : }

@@ -513,20 +518,18 @@ class InfrastructureComponents extends Component { {this.state.currentUser.role === "Admin" && this.state.numberOfExternalICs > 0 ?
- : -
+ :
}
@@ -540,9 +543,8 @@ class InfrastructureComponents extends Component { onClose={data => this.closeICModal(data)} ic={this.state.modalIC} token={this.state.sessionToken} - userRole={this.state.currentUser.role} + user={this.state.currentUser} sendControlCommand={(command, ic) => this.sendControlCommand(command, ic)}/> -
); } diff --git a/src/ic/import-ic.js b/src/ic/import-ic.js index a165af6..51a992b 100644 --- a/src/ic/import-ic.js +++ b/src/ic/import-ic.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import _ from 'lodash'; import Dialog from '../common/dialogs/dialog'; @@ -111,29 +111,36 @@ class ImportICDialog extends React.Component { render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Infrastructure Component File - this.loadFile(e.target.files)} /> - + this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid} + > + + + Infrastructure Component File + this.loadFile(e.target.files)} /> + - - Name - this.handleChange(e)} /> - - - - Websocket URL - this.handleChange(e)} /> - - - - UUID - this.handleChange(e)} /> - - - + + Name + this.handleChange(e)} /> + + + + Websocket URL + this.handleChange(e)} /> + + + + UUID + this.handleChange(e)} /> + + +
); } diff --git a/src/ic/new-ic.js b/src/ic/new-ic.js index 39aeebd..3fe9fb8 100644 --- a/src/ic/new-ic.js +++ b/src/ic/new-ic.js @@ -16,8 +16,9 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, FormCheck, OverlayTrigger, Tooltip} from 'react-bootstrap'; +import { Form, OverlayTrigger, Tooltip} from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; +import ParametersEditor from '../common/parameters-editor'; class NewICDialog extends React.Component { valid = false; @@ -35,30 +36,39 @@ class NewICDialog extends React.Component { managedexternally: false, description: '', location: '', - manager: '' + manager: '', + properties: {} }; } onClose(canceled) { if (canceled === false) { if (this.valid) { - const data = { + const parameters = { name: this.state.name, type: this.state.type, category: this.state.category, uuid: this.state.uuid, - managedexternally: this.state.managedexternally, location: this.state.location, description: this.state.description, - manager: this.state.manager - }; - - if (this.state.websocketurl != null && this.state.websocketurl !== "" && this.state.websocketurl !== 'http://') { - data.websocketurl = this.state.websocketurl; } - if (this.state.apiurl != null && this.state.apiurl !== "" && this.state.apiurl !== 'http://') { - data.apiurl = this.state.apiurl; + const data = { + managedexternally: this.state.managedexternally, + manager: this.state.manager, + parameters: parameters + }; + + // Add custom properties + if (this.state.managedexternally) + Object.assign(parameters, this.state.properties); + + if (this.state.websocketurl != null && this.state.websocketurl !== "") { + parameters.websocketurl = this.state.websocketurl; + } + + if (this.state.apiurl != null && this.state.apiurl !== "") { + parameters.apiurl = this.state.apiurl; } this.props.onClose(data); @@ -75,12 +85,29 @@ class NewICDialog extends React.Component { this.setState({ managedexternally : !this.state.managedexternally}); } else{ - this.setState({ [e.target.id]: e.target.value }); + this.setState({ [e.target.id]: e.target.value }); } } + handlePropertiesChange = properties => { + this.setState({ + properties: properties + }); + }; + resetState() { - this.setState({ name: '', websocketurl: 'http://', apiurl: 'http://', uuid: this.uuidv4(), type: '', category: '', managedexternally: false, description: '', location: ''}); + this.setState({ + name: '', + websocketurl: '', + apiurl: '', + uuid: this.uuidv4(), + type: '', + category: '', + managedexternally: false, + description: '', + location: '', + properties: {} + }); } validateForm(target) { @@ -137,10 +164,10 @@ class NewICDialog extends React.Component { let typeOptions = []; switch(this.state.category){ case "simulator": - typeOptions = ["dummy","generic","dpsim","rtlab","rscad","opalrt"]; + typeOptions = ["dummy","generic","dpsim","rtlab","rscad","rtlab","kubernetes"]; break; case "manager": - typeOptions = ["villas-node","villas-relay","generic"]; + typeOptions = ["villas-node","villas-relay","generic","kubernetes"]; break; case "gateway": typeOptions = ["villas-node","villas-relay"]; @@ -163,94 +190,109 @@ class NewICDialog extends React.Component { ); } - return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.validateForm()}> -
+ this.onClose(c)} + onReset={() => this.resetState()} + valid={this.validateForm()} + > + {this.props.managers.length > 0 ? <> - + An externally managed component is created and managed by an IC manager via AMQP} > - this.handleChange(e)}> - + this.handleChange(e)}> + - + {this.state.managedexternally === true ? - + Required field } > - Manager to create new IC * + Manager to create new IC * - this.handleChange(e)}> + this.handleChange(e)}> {managerOptions} - - + + :
- } :
} - - Required field } > - Name * - - this.handleChange(e)} /> - - - + + Required field } > + Name * + + this.handleChange(e)} /> + + + {this.state.managedexternally === false ? + + UUID + this.handleChange(e)}/> + + + :
+ } + + Location + this.handleChange(e)} /> + + + + Description + this.handleChange(e)} /> + + + Required field } > - Category of component * + Category of component * - this.handleChange(e)}> + this.handleChange(e)}> - - - - - - - - + + + + + + + + Required field } > - Type of component * + Type of component * - this.handleChange(e)}> + this.handleChange(e)}> {typeOptions.map((name,index) => ( ))} - - - - Websocket URL - this.handleChange(e)} /> - - - - API URL - this.handleChange(e)} /> - - - - Location - this.handleChange(e)} /> - - - - Description - this.handleChange(e)} /> - - - {this.state.managedexternally === false ? - - UUID - this.handleChange(e)}/> - - + + + + Websocket URL + this.handleChange(e)} /> + + + + API URL + this.handleChange(e)} /> + + + {this.state.managedexternally === true ? + + Properties + this.handlePropertiesChange(data)} + /> + :
} - +
); } diff --git a/src/result/edit-result.js b/src/result/edit-result.js index 024a410..2b8b13f 100644 --- a/src/result/edit-result.js +++ b/src/result/edit-result.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, Col, Row, Button, ProgressBar } from 'react-bootstrap'; +import { Form, Col, Row, Button, ProgressBar } from 'react-bootstrap'; import AppDispatcher from "../common/app-dispatcher"; import FileStore from "../file/file-store" @@ -131,78 +131,90 @@ class EditResultDialog extends React.Component { } render() { - - return this.onClose()} blendOutCancel={true} valid={true} - size='lg'> + > + + + + Description + + + + + + + + + + + + + + + + this.deleteFile(index)} + /> +
-
- - - - Description - - - - - - - - - - - - - - - - - this.deleteFile(index)} - /> -
- -
-
Add result file
- - - this.selectUploadFile(event)} /> - - - - - -
- -

- - - - - +
+
Add result file
+ + + this.selectUploadFile(event)} /> + + + + +
+ +
+ + + +
; } } -export default EditResultDialog; \ No newline at end of file +export default EditResultDialog; diff --git a/src/result/new-result.js b/src/result/new-result.js index 73d5e85..2529d02 100644 --- a/src/result/new-result.js +++ b/src/result/new-result.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -45,7 +45,7 @@ class NewResultDialog extends React.Component { } resetState() { - this.setState({ + this.setState({ ConfigSnapshots: '', Description: '', ResultFileIDs: [], @@ -54,14 +54,21 @@ class NewResultDialog extends React.Component { render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={true}> -
- - Description - this.handleChange(e)} /> - - -
+ this.onClose(c)} + onReset={() => this.resetState()} + valid={true} + > +
+ + Description + this.handleChange(e)} /> + + +
); } diff --git a/src/result/result-configs-dialog.js b/src/result/result-configs-dialog.js index 8dfc220..b0fcea5 100644 --- a/src/result/result-configs-dialog.js +++ b/src/result/result-configs-dialog.js @@ -15,6 +15,7 @@ * along with VILLASweb. If not, see . ******************************************************************************/ import React from 'react'; +import { Form } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; import ReactJson from 'react-json-view'; @@ -46,16 +47,16 @@ class ResultConfigDialog extends React.Component { size="lg" blendOutCancel={true} > -
- - +
+ +
); } diff --git a/src/scenario/edit-scenario.js b/src/scenario/edit-scenario.js index d3f90c6..22fe3a9 100644 --- a/src/scenario/edit-scenario.js +++ b/src/scenario/edit-scenario.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel, Col} from 'react-bootstrap'; +import { Form, Col } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; import ParametersEditor from '../common/parameters-editor'; @@ -53,13 +53,11 @@ class EditScenarioDialog extends React.Component { this.setState({ [event.target.id]: event.target.value }); let name = true; - if (this.state.name === '') { name = false; } this.valid = name; - }; resetState = () => { @@ -76,20 +74,26 @@ class EditScenarioDialog extends React.Component { }; render() { - return -
- - Name - - - - - - Start Parameters + return + + + Name + + + + + Start Parameters - -
+ +
; } } diff --git a/src/scenario/import-scenario.js b/src/scenario/import-scenario.js index a6b9a23..f0eff99 100644 --- a/src/scenario/import-scenario.js +++ b/src/scenario/import-scenario.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel, Col} from 'react-bootstrap'; +import { Form, Col } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; import ParametersEditor from '../common/parameters-editor'; @@ -93,26 +93,32 @@ class ImportScenarioDialog extends React.Component { } render() { - return -
- - Scenario File - - + return + + + Scenario File + + - - Name - this.handleChange(e)} /> - - + + Name + this.handleChange(e)} /> + + - - Start Parameters + + Start Parameters - - - + +
; } } diff --git a/src/scenario/new-scenario.js b/src/scenario/new-scenario.js index c582a3c..7535994 100644 --- a/src/scenario/new-scenario.js +++ b/src/scenario/new-scenario.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel, Col} from 'react-bootstrap'; +import { Form, Col} from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; import ParametersEditor from '../common/parameters-editor'; @@ -70,20 +70,26 @@ class NewScenarioDialog extends React.Component { } render() { - return -
- - Name - - - + return + + + Name + + + - - Start Parameters + + Start Parameters - - + +
; } } diff --git a/src/scenario/scenario.js b/src/scenario/scenario.js index 1f8dee2..73767c9 100644 --- a/src/scenario/scenario.js +++ b/src/scenario/scenario.js @@ -17,7 +17,7 @@ import React from 'react'; import { Container } from 'flux/utils'; -import { Button, InputGroup, FormControl, Tooltip, OverlayTrigger } from 'react-bootstrap'; +import { Button, InputGroup, Form } from 'react-bootstrap'; import FileSaver from 'file-saver'; @@ -31,6 +31,7 @@ import AppDispatcher from '../common/app-dispatcher'; import Icon from '../common/icon'; import Table from '../common/table'; import TableColumn from '../common/table-column'; +import IconButton from '../common/icon-button'; import ImportConfigDialog from '../componentconfig/import-config'; import ImportDashboardDialog from "../dashboard/import-dashboard"; import NewDashboardDialog from "../dashboard/new-dashboard"; @@ -44,7 +45,7 @@ import ResultConfigDialog from '../result/result-configs-dialog'; import ICAction from '../ic/ic-action'; import DeleteDialog from '../common/dialogs/delete-dialog'; import EditConfigDialog from "../componentconfig/edit-config"; -import EditSignalMapping from "../signal/edit-signal-mapping"; +import EditSignalMappingDialog from "../signal/edit-signal-mapping"; import FileStore from "../file/file-store" import WidgetStore from "../widget/widget-store"; import ResultStore from "../result/result-store" @@ -63,6 +64,7 @@ class Scenario extends React.Component { if (prevState == null) { prevState = {}; } + // get selected scenario const sessionToken = localStorage.getItem("token"); @@ -109,7 +111,7 @@ class Scenario extends React.Component { deleteConfigModal: false, importConfigModal: false, newConfig: prevState.newConfig || false, - selectedConfigs: [], + selectedConfigs: prevState.selectedConfigs || [], filesEditModal: prevState.filesEditModal || false, filesEditSaveState: prevState.filesEditSaveState || [], @@ -376,7 +378,7 @@ class Scenario extends React.Component { let ic = null; for (let component of this.state.ics) { - if (component.id === this.state.configs[index].icID) { + if (component.id === icID) { ic = component; } } @@ -391,7 +393,6 @@ class Scenario extends React.Component { } return false - } getICName(icID) { @@ -581,22 +582,18 @@ class Scenario extends React.Component { * File modification methods ############################################## */ - getListOfFiles(fileIDs, types) { - - let fileList = ''; + getListOfFiles(files, fileIDs) { + let fileList = []; for (let id of fileIDs) { - for (let file of this.state.files) { - if (file.id === id && types.some(e => file.type.includes(e))) { - if (fileList === '') { - fileList = file.name - } else { - fileList = fileList + ';' + file.name; - } + for (let file of files) { + if (file.id === id) { + fileList.push(file.name) } } } - return fileList; + + return fileList.join(';'); } /* ############################################## @@ -738,63 +735,14 @@ class Scenario extends React.Component { return

Loading Scenario...

; } - let resulttable; - if (this.state.results && this.state.results.length > 0) { - resulttable =
- - this.modifyResultNoColumn(id, result)} - /> - - - - this.downloadResultData(index)} - /> - this.setState({ editResultsModal: true, modalResultsIndex: index })} - onDownloadAll={(index) => this.downloadResultData(this.state.results[index])} - onDelete={(index) => this.setState({ deleteResultsModal: true, modalResultsData: this.state.results[index], modalResultsIndex: index })} - /> -
- - - this.closeDeleteResultsModal(e)} /> - -
- } - return
- Add, edit or delete files of scenario } > - - +

{this.state.scenario.name}

@@ -810,34 +758,37 @@ class Scenario extends React.Component { {/*Component Configurations table*/}

Component Configurations - Add Component Configuration } > - - - Import Component Configuration } > - - - + this.addConfig()} + icon='plus' + /> + this.setState({ importConfigModal: true })} + icon='upload' + /> +

this.usesExternalIC(index)} + checkboxDisabled={(index) => !this.usesExternalIC(index)} onChecked={(index, event) => this.onConfigChecked(index, event)} - width='30' /> - - this.getListOfFiles(fileIDs, ['json', 'JSON'])} /> + width='30' + /> + {this.state.currentUser.role === "Admin" ? + + : <> + } this.getListOfFiles(fileIDs, ['xml'])} - editButton - onEdit={(index) => this.startPintura(index)} + title='Name' + dataKey='name' /> this.setState({ editInputSignalsModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })} /> this.signalsAutoConf(index)} /> - this.getICName(icID)} /> + this.getICName(icID)} + />
- {this.state.ExternalICInUse ? ( + {this.state.ExternalICInUse ?
this.copyConfig(index)} token = {this.state.sessionToken} actions={[ - { id: '-1', title: 'Action', data: { action: 'none' } }, { id: '0', title: 'Start', data: { action: 'start' } }, { id: '1', title: 'Stop', data: { action: 'stop' } }, { id: '2', title: 'Pause', data: { action: 'pause' } }, { id: '3', title: 'Resume', data: { action: 'resume' } } ]} />
- ) : (
) + :
} - < div style={{ clear: 'both' }} /> +
- - this.importConfig(data)} ics={this.state.ics} /> - this.closeDeleteConfigModal(c)} /> - - this.importConfig(data)} + ics={this.state.ics} + /> + this.closeDeleteConfigModal(c)} + /> + this.closeEditSignalsModal(direction)} direction="Output" @@ -913,7 +874,7 @@ class Scenario extends React.Component { configID={this.state.modalConfigData.id} sessionToken={this.state.sessionToken} /> - this.closeEditSignalsModal(direction)} direction="Input" @@ -925,26 +886,41 @@ class Scenario extends React.Component { {/*Dashboard table*/}

Dashboards - Add Dashboard } > - - - Import Dashboard } > - - - + this.setState({ newDashboardModal: true })} + icon='plus' + /> + this.setState({ importDashboardModal: true })} + icon='upload' + /> +

- - + {this.state.currentUser.role === "Admin" ? + + : <> + } + +
- this.closeNewDashboardModal(data)} /> - this.closeEditDashboardModal(data)} /> - this.closeImportDashboardModal(data)} /> - - this.closeDeleteDashboardModal(e)} /> + this.closeNewDashboardModal(data)} + /> + this.closeEditDashboardModal(data)} + /> + this.closeImportDashboardModal(data)} + /> + this.closeDeleteDashboardModal(e)} + /> {/*Result table*/}

Results - Add Result } > - - - + this.setState({ newResultModal: true })} + icon='plus' + /> +

- {resulttable} - this.closeNewResultModal(data)} /> + + + this.modifyResultNoColumn(id, result)} + /> + + + + this.downloadResultData(index)} + /> + this.setState({ editResultsModal: true, modalResultsIndex: index })} + onDownloadAll={(index) => this.downloadResultData(this.state.results[index])} + onDelete={(index) => this.setState({ deleteResultsModal: true, modalResultsData: this.state.results[index], modalResultsIndex: index })} + /> +
+ + + this.closeDeleteResultsModal(e)} + /> + + this.closeNewResultModal(data)} + /> {/*Scenario Users table*/}

Users sharing this scenario

-
- - - +
+ {this.state.currentUser.role === "Admin" ? this.setState({ deleteUserModal: true, deleteUserName: this.state.scenario.users[index].username, modalUserIndex: index })} + title='ID' + dataKey='id' /> -
+ : <> + } + + + this.setState({ + deleteUserModal: true, + deleteUserName: this.state.scenario.users[index].username, + modalUserIndex: index + })} + /> + - - this.onUserInputChange(e)} - value={this.state.userToAdd} - type="text" - /> - + + this.onUserInputChange(e)} + value={this.state.userToAdd} + type="text" + /> + - - -

-
- - this.closeDeleteUserModal(c)} /> - + + + +
+
+ this.closeDeleteUserModal(c)} + />
; } } diff --git a/src/scenario/scenarios.js b/src/scenario/scenarios.js index aef0740..afd10f2 100644 --- a/src/scenario/scenarios.js +++ b/src/scenario/scenarios.js @@ -17,7 +17,6 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import {Button, OverlayTrigger, Tooltip} from 'react-bootstrap'; import FileSaver from 'file-saver'; import AppDispatcher from '../common/app-dispatcher'; @@ -35,6 +34,7 @@ import EditScenarioDialog from './edit-scenario'; import ImportScenarioDialog from './import-scenario'; import DeleteDialog from '../common/dialogs/delete-dialog'; +import IconButton from '../common/icon-button'; class Scenarios extends Component { @@ -43,7 +43,10 @@ class Scenarios extends Component { return [ScenarioStore, DashboardStore, WidgetStore, ConfigStore, SignalStore]; } - static calculateState() { + static calculateState(prevState, props) { + if (prevState == null) { + prevState = {}; + } return { scenarios: ScenarioStore.getState(), @@ -57,8 +60,8 @@ class Scenarios extends Component { editModal: false, importModal: false, modalScenario: {}, - - selectedScenarios: [] + selectedScenarios: prevState.selectedScenarios || [], + currentUser: JSON.parse(localStorage.getItem("currentUser")) }; } @@ -225,50 +228,50 @@ class Scenarios extends Component { } modifyRunningColumn(running){ - - if(running){ - return - } else { - return - } - + return } render() { - const buttonStyle = { - marginLeft: '10px', - }; - - const iconStyle = { - height: '30px', - width: '30px' - } - - return ( -
+ return

Scenarios - Add Scenario } > - - - Import Scenario } > - - - + this.setState({ newModal: true })} + icon='plus' + /> + this.setState({ importModal: true })} + icon='upload' + /> +

- - - this.modifyRunningColumn(running)}/> + {this.state.currentUser.role === "Admin" ? + + : <> + } + + this.modifyRunningColumn(running)} + /> this.closeImportModal(data)} nodes={this.state.nodes} /> this.closeDeleteModal(e)} /> - - ); + ; } } diff --git a/src/signal/edit-signal-mapping.js b/src/signal/edit-signal-mapping.js index 3b75386..e5bba88 100644 --- a/src/signal/edit-signal-mapping.js +++ b/src/signal/edit-signal-mapping.js @@ -17,27 +17,26 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {Button, FormGroup, FormLabel, FormText, OverlayTrigger, Tooltip} from 'react-bootstrap'; -import {Collapse} from 'react-collapse'; +import { Button, Form, OverlayTrigger, Tooltip } from 'react-bootstrap'; +import { Collapse } from 'react-collapse'; import Table from '../common/table'; import TableColumn from '../common/table-column'; import Dialog from "../common/dialogs/dialog"; import Icon from "../common/icon"; import AppDispatcher from "../common/app-dispatcher"; -class EditSignalMapping extends React.Component { +class EditSignalMappingDialog extends React.Component { constructor(props) { super(props); let dir = ""; - if ( this.props.direction === "Output"){ + if ( this.props.direction === "Output") { dir = "out"; - } else if ( this.props.direction === "Input" ){ + } else if ( this.props.direction === "Input" ) { dir = "in"; } - this.state = { dir, signals: [], @@ -46,38 +45,37 @@ class EditSignalMapping extends React.Component { }; } - static getDerivedStateFromProps(props, state){ + static getDerivedStateFromProps(props, state) { // filter all signals by configID and direction let signals = []; - if(props.signalID != null || typeof props.configs === "undefined"){ + if (props.signalID != null || typeof props.configs === "undefined") { signals = props.signals.filter((sig) => { return (sig.configID === props.configID) && (sig.direction === state.dir); }); } - else{ - for(let i = 0; i < props.configs.length; i++){ + else { + for (let i = 0; i < props.configs.length; i++) { let temp = props.signals.filter((sig) => { return (sig.configID === props.configs[i].id) && (sig.direction === state.dir); }) - signals = signals.concat(temp); + signals = signals.concat(temp); + } } - } - - signals.forEach(signal => { - if(signal.checked === undefined) signal.checked = false - }); + signals.forEach(signal => { + if (signal.checked === undefined) { + signal.checked = false; + } + }); return { signals: signals, }; } - onClose(canceled) { - - for (let signalID of this.state.modifiedSignalIDs){ + for (let signalID of this.state.modifiedSignalIDs) { let sig = this.state.signals.find(s => s.id === signalID); @@ -100,23 +98,23 @@ class EditSignalMapping extends React.Component { console.log("HandleMappingChange", row, column) if (column === 2) { // Name change signals[row].name = event.target.value; - if (modifiedSignals.find(id => id === signals[row].id) === undefined){ + if (modifiedSignals.find(id => id === signals[row].id) === undefined) { modifiedSignals.push(signals[row].id); } } else if (column === 3) { // unit change signals[row].unit = event.target.value; - if (modifiedSignals.find(id => id === signals[row].id) === undefined){ + if (modifiedSignals.find(id => id === signals[row].id) === undefined) { modifiedSignals.push(signals[row].id); } } else if (column === 4) { // scaling factor change signals[row].scalingFactor = parseFloat(event.target.value); - if (modifiedSignals.find(id => id === signals[row].id) === undefined){ + if (modifiedSignals.find(id => id === signals[row].id) === undefined) { modifiedSignals.push(signals[row].id); } } else if (column === 1) { //index change console.log("Index change") signals[row].index =parseInt(event.target.value, 10); - if (modifiedSignals.find(id => id === signals[row].id) === undefined){ + if (modifiedSignals.find(id => id === signals[row].id) === undefined) { modifiedSignals.push(signals[row].id); } } @@ -125,11 +123,9 @@ class EditSignalMapping extends React.Component { signals: signals, modifiedSignalIDs: modifiedSignals }) - }; handleDelete = (index) => { - let data = this.state.signals[index] AppDispatcher.dispatch({ @@ -137,11 +133,9 @@ class EditSignalMapping extends React.Component { data: data, token: this.props.sessionToken }); - }; handleRemove = () => { - let checkedSignals = this.state.signals.filter(signal => signal.checked === true); checkedSignals.forEach(signal => { @@ -150,23 +144,20 @@ class EditSignalMapping extends React.Component { data: signal, token: this.props.sessionToken }); - }) - } handleAdd = (configID = null) => { - - if(typeof this.props.configs !== "undefined"){ - - if(configID === null){ + if (typeof this.props.configs !== "undefined") { + if (configID === null) { this.setState({openCollapse: true}); - return - } - } - else{ - configID = this.props.configID; + return; } + } + else { + configID = this.props.configID; + } + let newSignal = { configID: configID, direction: this.state.dir, @@ -186,7 +177,6 @@ class EditSignalMapping extends React.Component { }; resetState() { - let signals = this.props.signals.filter((sig) => { return (sig.configID === this.props.configID) && (sig.direction === this.state.dir); }); @@ -201,83 +191,136 @@ class EditSignalMapping extends React.Component { tempSignals[index].checked = !tempSignals[index].checked; this.setState({signals: tempSignals}); - } - checkAll(){ + checkAll() { let tempSignals = this.state.signals; let allChecked = true; - tempSignals.forEach(signal => - { - if(signal.checked === false){ + tempSignals.forEach(signal => { + if (signal.checked === false) { signal.checked = true; allChecked = false; } - }); + }); - if(allChecked){ + if (allChecked) { tempSignals.forEach(signal => signal.checked = false); } + this.setState({signals: tempSignals}); } render() { - const buttonStyle = { marginLeft: '10px', }; - return( + return this.onClose(c)} + onReset={() => this.resetState()} + valid={true} + > + + {this.props.direction} Mapping + Click Index, Name or Unit cell to edit +
this.onSignalChecked(signal)} data={this.state.signals}> + this.onSignalChecked(index, event)} + checkboxKey='checked' + width='30' + /> + this.handleMappingChange(e, row, column)} + /> + this.handleMappingChange(e, row, column)} + /> + this.handleMappingChange(e, row, column)} + /> + this.handleMappingChange(e, row, column)} + /> + this.handleDelete(index)} + /> +
- this.onClose(c)} - onReset={() => this.resetState()} - valid={true} - size='lg'> - - - {this.props.direction} Mapping - Click Index, Name or Unit cell to edit - this.onSignalChecked(signal)} data={this.state.signals}> - this.onSignalChecked(index, event)} checkboxKey='checked' width='30' /> - this.handleMappingChange(e, row, column)} /> - this.handleMappingChange(e, row, column)} /> - this.handleMappingChange(e, row, column)} /> - this.handleMappingChange(e, row, column)} /> - this.handleDelete(index)} /> -
- -
- Check/Uncheck All } > - - - - +
+ Check/Uncheck All } + > + + + + +
+
+ +
Choose a Component Configuration to add the signal to:
+
+ {typeof this.props.configs !== "undefined" && this.props.configs.map(config => ( + + ))}
-
- -
Choose a Component Configuration to add the signal to:
-
- {typeof this.props.configs !== "undefined" && this.props.configs.map(config => ( - - - - ))} -
-
-
- -
- ); + +
+ +
; } } -EditSignalMapping.propTypes = { +EditSignalMappingDialog.propTypes = { name: PropTypes.string, length: PropTypes.number, signals: PropTypes.arrayOf( @@ -293,4 +336,4 @@ EditSignalMapping.propTypes = { onChange: PropTypes.func }; -export default EditSignalMapping; +export default EditSignalMappingDialog; diff --git a/src/styles/app.css b/src/styles/app.css index 721b57f..00cccbf 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -39,38 +39,18 @@ body { hyphens: auto; } -.app-body { - /*height: 100%;*/ -} - .app-header { width: 100%; - height: 60px; - padding: 10px 0 0 0; color: var(--highlights); background-color: #fff; } .app-header h1 { - width: 100%; + padding: 5px 0; margin: 0; - - text-align: left; -} - -@media (min-width: 768px) { - .app-header h1 { - text-align: center !important; - } -} - -/* can be deleted when header-menu gets removed */ -.app-header .menu-icon { - color: var(--secondarytext); - right: 5px; - - padding: 6px 0 0 0; + width: 100%; + text-align: center; } .btn-link { @@ -93,12 +73,7 @@ body { } .app-body-spacing { - padding: 15px 5px 0px 5px; -} - -.app-body-spacing > div { - margin-left: 7px; - margin-right: 7px; + padding: 20px; } .app-content-fullscreen { @@ -106,7 +81,7 @@ body { } .app-content { - padding: 15px 20px; + padding: 15px 20px 20px 20px; width: auto; min-height: 300px; @@ -116,10 +91,8 @@ body { 0 9px 18px 0 rgba(0, 0, 0, 0.1); } -@media (min-width: 768px) { - .app-content-margin-left { - margin-left: 275px !important; - } +.app-content-margin-left { + margin-left: 180px !important; } .verticalhorizontal { @@ -132,10 +105,9 @@ body { /** * Menus */ -.menu-sidebar { - /*display: inline-table;*/ - padding: 20px 25px 20px 25px; - width: 250px; +.menu { + padding: 20px; + width: 160px; float: left; background-color: #fff; @@ -143,12 +115,12 @@ body { 0 9px 18px 0 rgba(0, 0, 0, 0.1); } -.menu-sidebar a { +.menu a { color: var(--primarytext); text-decoration:none; } -.menu-sidebar a:hover, .menu-sidebar a:focus { +.menu a:hover, .menu a:focus { text-decoration:none; } @@ -156,13 +128,17 @@ body { font-weight: bold; } -.menu-sidebar ul { +.menu ul { padding-top: 10px; + margin-bottom: 0; list-style: none; white-space: nowrap; } +.menu li { + margin: 5px 0; +} -.menu-sidebar a::after { +.menu a::after { /* Trick to make menu items to be as wide as in bold */ display: block; content: attr(title); @@ -260,6 +236,10 @@ hr { /** * Tables */ +.table th,td { + padding: 0.5em 0.5em !important; +} + .table th { background-color: var(--highlights); color: #fff; @@ -268,16 +248,13 @@ hr { /** * Buttons */ -.table-control-button { - border: none; - - background: none; - - padding: 0 5px; +.btn-table-control-button { + padding: 0 0.5em !important; + line-height: 1em !important; } -.table-control-button:hover { - color: #888; +.btn-table-control-button:hover { + color: #888 !important; } .table-control-checkbox input { @@ -474,3 +451,15 @@ hr { .badge-outdated { opacity: 0.4; } + + +/** + * Swagger UI + */ +.swagger-ui .wrapper { + padding: 0 !important; +} + +.swagger-ui .info { + margin-top: 10px; +} diff --git a/src/user/edit-own-user.js b/src/user/edit-own-user.js index 4b7a639..a5b7756 100644 --- a/src/user/edit-own-user.js +++ b/src/user/edit-own-user.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel, Col} from 'react-bootstrap'; +import { Form, Col } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -28,17 +28,15 @@ class EditOwnUserDialog extends React.Component { super(props); this.state = { - username: '', - id: '', - mail: '', + username: this.props.user.username, + id: this.props.user.id, + mail: this.props.user.mail, password: '', oldPassword: '', - confirmpassword: '' + confirmPassword: '' } } - - onClose(canceled) { if (canceled === false) { if (this.valid) { @@ -49,8 +47,6 @@ class EditOwnUserDialog extends React.Component { } } - - handleChange(e) { this.setState({ [e.target.id]: e.target.value }); @@ -59,73 +55,69 @@ class EditOwnUserDialog extends React.Component { let mail = true; let pw = true; let oldPassword = true; - let confirmpassword = true; + let confirmPassword = true; if (this.state.username === '') { username = false; } - if(this.state.mail === ''){ + if (this.state.mail === '') { mail = false; } - if(this.state.password === ''){ + if (this.state.password === '') { pw = false; } - if(this.state.oldPassword === ''){ + if (this.state.oldPassword === '') { oldPassword = false; } - if(this.state.confirmpassword === ''){ - confirmpassword = false; + if (this.state.confirmPassword === '') { + confirmPassword = false; } - // form is valid if the following condition is met - this.valid = username || mail || (oldPassword && pw && confirmpassword); - + this.valid = username || mail || (oldPassword && pw && confirmPassword); } resetState() { this.setState({ - username: '', - mail: '', - oldPassword: '', - confirmpassword: '', - password: '', + username: this.props.user.username, id: this.props.user.id, + mail: this.props.user.mail, + oldPassword: '', + confirmPassword: '', + password: '', }); } render() { return ( this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Username - this.handleChange(e)} /> - - - - E-mail - this.handleChange(e)} /> - - - Old Password - this.handleChange(e)} /> - - - - New Password - this.handleChange(e)} /> - - - - Confirm New Password - this.handleChange(e)} /> - -
+
+ + Username + this.handleChange(e)} autocomplete="username" /> + + + + E-mail + this.handleChange(e)} autocomplete="email" /> + + + Old Password + this.handleChange(e)} autocomplete="current-password" /> + + + New Password + this.handleChange(e)} autocomplete="new-password" /> + + + Confirm New Password + this.handleChange(e)} autocomplete="new-password" /> + +
); } diff --git a/src/user/edit-user.js b/src/user/edit-user.js index 12ee58a..5d20bf4 100644 --- a/src/user/edit-user.js +++ b/src/user/edit-user.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel, Col} from 'react-bootstrap'; +import { Form, Col } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -27,13 +27,13 @@ class EditUserDialog extends React.Component { super(props); this.state = { - username: '', - mail: '', - role: '', - id: '', + username: props.user.username, + mail: props.user.mail, + role: props.user.role, + id: props.user.id, + active: props.user.active, password: '', - active: '', - confirmpassword: '', + confirmPassword: '', oldPassword: '' } } @@ -57,47 +57,45 @@ class EditUserDialog extends React.Component { var mail = true; var pw = true; var active = true; - var confirmpassword = true; - var oldPW = true; - + var confirmPassword = true; + var oldPassword = true; if (this.state.username === '') { username = false; } - if (this.state.role === ''){ + if (this.state.role === '') { role = false; } - if(this.state.mail === ''){ + if (this.state.mail === '') { mail = false; } - if(this.state.password === ''){ + if (this.state.password === '') { pw = false; } - if(this.state.active === ''){ + if (this.state.active === '') { active = false; } - if(this.state.confirmpassword === ''){ - confirmpassword = false; + if (this.state.confirmPassword === '') { + confirmPassword = false; } - if(this.state.oldPassword === ''){ - oldPW = false; + if (this.state.oldPassword === '') { + oldPassword = false; } // form is valid if any of the fields contain somethig - this.valid = username || role || mail || pw || active || confirmpassword || oldPW; - + this.valid = username || role || mail || pw || active || confirmPassword || oldPassword; } resetState() { this.setState({ - //username: this.props.user.username, - //mail: this.props.user.mail, + username: this.props.user.username, + mail: this.props.user.mail, role: this.props.user.role, id: this.props.user.id }); @@ -106,46 +104,44 @@ class EditUserDialog extends React.Component { render() { return ( this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Username - this.handleChange(e)} /> - - - - E-mail - this.handleChange(e)} /> - - - Admin Password - this.handleChange(e)} /> - - - Password - this.handleChange(e)} /> - - - Confirm New Password - this.handleChange(e)} /> - - - Role - this.handleChange(e)}> + + + Username + this.handleChange(e)} /> + + + + E-mail + this.handleChange(e)} /> + + + Admin Password + this.handleChange(e)} /> + + + Password + this.handleChange(e)} /> + + + Confirm New Password + this.handleChange(e)} /> + + + Role + this.handleChange(e)}> - - - - - Active - this.handleChange(e)}> + + + + Active + this.handleChange(e)}> - - - -
+ + +
); } diff --git a/src/user/login-complete.js b/src/user/login-complete.js index 4fd4922..9ed2fc7 100644 --- a/src/user/login-complete.js +++ b/src/user/login-complete.js @@ -26,7 +26,7 @@ class LoginComplete extends React.Component { constructor(props) { console.log("LoginComplete constructor"); super(props); - + AppDispatcher.dispatch({ type: 'users/extlogin', }); @@ -42,8 +42,6 @@ class LoginComplete extends React.Component { this.startTimer = this.startTimer.bind(this); this.countDown = this.countDown.bind(this); this.stopTimer = this.stopTimer.bind(this); - - } componentDidMount() { @@ -51,7 +49,6 @@ class LoginComplete extends React.Component { this.setState({secondsToWait: 5}); } - static getStores(){ return [LoginStore] } @@ -97,11 +94,15 @@ class LoginComplete extends React.Component { this.stopTimer(); return (); } else { - return (
- Waiting Dog
); + return
+ Waiting Dog +
; } } } let fluxContainerConverter = require('../common/FluxContainerConverter'); -export default Container.create(fluxContainerConverter.convert(LoginComplete)); \ No newline at end of file +export default Container.create(fluxContainerConverter.convert(LoginComplete)); diff --git a/src/user/login-form.js b/src/user/login-form.js index fedfa26..ef38ee9 100644 --- a/src/user/login-form.js +++ b/src/user/login-form.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React, { Component } from 'react'; -import { Form, Button, FormGroup, FormControl, FormLabel, Col } from 'react-bootstrap'; +import { Form, Button, Col } from 'react-bootstrap'; import RecoverPassword from './recover-password' import AppDispatcher from '../common/app-dispatcher'; import _ from 'lodash'; @@ -69,19 +69,19 @@ class LoginForm extends Component { villaslogin() { return (
- - Username + + Username - this.handleChange(e)} /> + this.handleChange(e)} /> - + - - Password + + Password - this.handleChange(e)} /> + this.handleChange(e)} /> - + {this.props.loginMessage &&
@@ -91,17 +91,16 @@ class LoginForm extends Component {
} - + - + this.closeRecoverPassword()} sessionToken={this.props.sessionToken} /> - ); } diff --git a/src/user/login.js b/src/user/login.js index ea38f89..f265342 100644 --- a/src/user/login.js +++ b/src/user/login.js @@ -32,7 +32,7 @@ class Login extends Component { constructor(props) { super(props); - // load config in case the user goes directly to /login + // Load config in case the user goes directly to /login // otherwise it will be loaded in app constructor AppDispatcher.dispatch({ type: 'config/load', diff --git a/src/user/new-user.js b/src/user/new-user.js index 2d0c434..7d6baa9 100644 --- a/src/user/new-user.js +++ b/src/user/new-user.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, FormText, Col } from 'react-bootstrap'; +import { Form, Col } from 'react-bootstrap'; import Dialog from '../common/dialogs/dialog'; @@ -54,7 +54,6 @@ class NewUserDialog extends React.Component { let mail = this.state.mail !== ''; this.valid = username && password && role && mail; - } resetState() { @@ -68,33 +67,40 @@ class NewUserDialog extends React.Component { render() { return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
- - Username - this.handleChange(e)} /> - - Min 3 characters. - - - E-mail - this.handleChange(e)} /> - - - - Password - this.handleChange(e)} /> - - - - Role - this.handleChange(e)}> + this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid} + > + + + Username + this.handleChange(e)} /> + + Min 3 characters. + + + E-mail + this.handleChange(e)} /> + + + + Password + this.handleChange(e)} /> + + + + Role + this.handleChange(e)}> - - -
+ + +
); } diff --git a/src/user/recover-password.js b/src/user/recover-password.js index 2602d9c..4105f4f 100644 --- a/src/user/recover-password.js +++ b/src/user/recover-password.js @@ -35,13 +35,20 @@ class RecoverPassword extends React.Component { render() { return ( - this.onClose(c)} blendOutCancel = {true} valid={true} size = 'lg'> + this.onClose(c)} + blendOutCancel={true} + valid={true} + >
-
Please contact:
-
{this.state.admin.name}
-
E-Mail:
- {this.state.admin.mail} -
+
Please contact:
+
{this.state.admin.name}
+
E-Mail:
+ {this.state.admin.mail} +
); } diff --git a/src/user/user.js b/src/user/user.js index e85f5ac..26bd161 100644 --- a/src/user/user.js +++ b/src/user/user.js @@ -17,7 +17,7 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import {Button, Col, Row, FormGroup} from 'react-bootstrap'; +import { Button, Form, Row, Col } from 'react-bootstrap'; import AppDispatcher from '../common/app-dispatcher'; import UsersStore from './users-store'; @@ -46,7 +46,6 @@ class User extends Component { } componentDidMount() { - let currentUserID = JSON.parse(localStorage.getItem("currentUser")).id; AppDispatcher.dispatch({ @@ -54,93 +53,102 @@ class User extends Component { data: parseInt(currentUserID, 10), token: this.state.token }); - } closeEditModal(data) { - this.setState({ editModal: false }); + let updatedData = {} - updatedData.id = this.state.currentUser.id; let updatedUser = this.state.currentUser; let hasChanged = false; let pwChanged = false; - if(data){ - if (data.username !== ''){ - hasChanged = true; - updatedData.username = data.username; - updatedUser.username = data.username - } - if (data.mail !== ''){ - hasChanged = true; - updatedData.mail = data.mail; - updatedUser.mail = data.mail; - } - if (data.password !== '' && data.oldPassword !== '' && data.password === data.confirmpassword ){ - pwChanged = true; - updatedData.password = data.password; - updatedData.oldPassword = data.oldPassword; - } else if (data.password !== '' && data.password !== data.confirmpassword) { - NotificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR('New password not correctly confirmed')); - return - } + updatedData.id = this.state.currentUser.id; - if (hasChanged || pwChanged) { - - if(hasChanged){ - this.setState({currentUser: updatedUser}) + if (data) { + if (data.username !== this.state.currentUser.username) { + hasChanged = true; + updatedData.username = data.username; + updatedUser.username = data.username } - AppDispatcher.dispatch({ - type: 'users/start-edit', - data: updatedData, - token: this.state.token - }); - } else { - NotificationsDataManager.addNotification(NotificationsFactory.UPDATE_WARNING('No update requested, no input data')); + if (data.mail !== this.state.currentUser.mail) { + hasChanged = true; + updatedData.mail = data.mail; + updatedUser.mail = data.mail; + } + + if (data.password !== '' && data.oldPassword !== '' && data.password === data.confirmPassword ) { + pwChanged = true; + updatedData.password = data.password; + updatedData.oldPassword = data.oldPassword; + } else if (data.password !== '' && data.password !== data.confirmPassword) { + NotificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR('New password not correctly confirmed')); + return + } + + if (hasChanged || pwChanged) { + if (hasChanged){ + this.setState({ currentUser: updatedUser }) + } + + AppDispatcher.dispatch({ + type: 'users/start-edit', + data: updatedData, + token: this.state.token + }); + } else { + NotificationsDataManager.addNotification(NotificationsFactory.UPDATE_WARNING('No update requested, no input data')); + } } } - } - - - 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() { + let user = this.state.currentUser; return (
-

Your User Account

+

Account

- {this.state.currentUser !== undefined && this.state.currentUser !== null ? + {user ? + <> +
+ + Username + + + + + + E-mail + + + + + + Role + + + + + + Created at + + + + + +
-
- - - -
Username:
-
E-mail:
-
Role:
-
- -
{this.state.currentUser.username}
-
{this.state.currentUser.mail}
-
{this.state.currentUser.role}
- - - -
-
- - this.closeEditModal(data)} - user={this.state.currentUser} /> - - : "Loading user data..." + this.closeEditModal(data)} + user={user} + /> + + :
}
); diff --git a/src/user/users-store.js b/src/user/users-store.js index 8bda26a..fccb4a9 100644 --- a/src/user/users-store.js +++ b/src/user/users-store.js @@ -50,7 +50,6 @@ class UsersStore extends ArrayStore { return super.reduce(state, action); } } - } export default new UsersStore(); diff --git a/src/user/users.js b/src/user/users.js index 96b1e4c..ca68323 100644 --- a/src/user/users.js +++ b/src/user/users.js @@ -17,12 +17,12 @@ import React, { Component } from 'react'; import { Container } from 'flux/utils'; -import {Button, OverlayTrigger, Tooltip} from 'react-bootstrap'; import AppDispatcher from '../common/app-dispatcher'; import UsersStore from './users-store'; import Icon from '../common/icon'; +import IconButton from '../common/icon-button'; import Table from '../common/table'; import TableColumn from '../common/table-column'; import NewUserDialog from './new-user'; @@ -38,7 +38,6 @@ class Users extends Component { } static calculateState(prevState, props) { - let token = localStorage.getItem("token"); // If there is a token available and this method was called as a result of loading users @@ -56,7 +55,8 @@ class Users extends Component { newModal: false, editModal: false, deleteModal: false, - modalData: {} + modalData: {}, + currentUser: JSON.parse(localStorage.getItem("currentUser")) }; } @@ -90,26 +90,18 @@ class Users extends Component { this.setState({ editModal: false }); if (data) { - if(data.password === data.confirmpassword) { - + if (data.password === data.confirmPassword) { AppDispatcher.dispatch({ type: 'users/start-edit', data: data, token: this.state.token }); - } else{ - + } else { NotificationsDataManager.addNotification(NotificationsFactory.UPDATE_ERROR("New password not correctly confirmed")) } } } - 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] : ''; - } - onModalKeyPress = (event) => { if (event.key === 'Enter') { event.preventDefault(); @@ -118,55 +110,69 @@ class Users extends Component { } }; - modifyActiveColumn(active){ - - if(active){ - return - } else { - return - } - + modifyActiveColumn(active) { + return } render() { - - const buttonStyle = { - marginLeft: '10px', - }; - - const iconStyle = { - height: '30px', - width: '30px' - } - - return ( -
+ return

Users - Add User } > - - - + this.setState({ newModal: true })} + icon='plus' + /> +

- - - - this.getHumanRoleName(role)} /> - this.modifyActiveColumn(active)} /> - this.setState({ editModal: true, modalData: this.state.users[index] })} onDelete={index => this.setState({ deleteModal: true, modalData: this.state.users[index] })} /> + {this.state.currentUser.role === "Admin" ? + + : <> + } + + + + this.modifyActiveColumn(active)} + /> + this.setState({ + editModal: true, + modalData: this.state.users[index] + })} + onDelete={index => this.setState({ + deleteModal: true, + modalData: this.state.users[index] + })} + />
this.closeNewModal(data)} /> this.closeEditModal(data)} user={this.state.modalData} /> - this.closeDeleteModal(e)} /> -
- ); +
; } } diff --git a/src/widget/edit-widget/color-picker.js b/src/widget/edit-widget/color-picker.js index a8e6615..8c148c0 100644 --- a/src/widget/edit-widget/color-picker.js +++ b/src/widget/edit-widget/color-picker.js @@ -16,6 +16,7 @@ ******************************************************************************/ import React from 'react'; +import { Form } from 'react-bootstrap'; import { SketchPicker } from 'react-color'; import Dialog from '../../common/dialogs/dialog'; @@ -31,8 +32,7 @@ class ColorPicker extends React.Component { }; } - static getDerivedStateFromProps(props, state){ - + static getDerivedStateFromProps(props, state) { return { widget: props.widget }; @@ -49,25 +49,24 @@ class ColorPicker extends React.Component { } handleChangeComplete = (color) => { - let temp = this.state.widget; - if(this.props.controlId === 'strokeStyle'){ + if (this.props.controlId === 'strokeStyle'){ temp.customProperties.zones[this.props.zoneIndex]['strokeStyle'] = color.hex; } - else if(this.props.controlId === 'lineColor'){ + else if (this.props.controlId === 'lineColor'){ temp.customProperties.lineColors[this.props.lineIndex] = color.hex; } - else{ - let parts = this.props.controlId.split('.'); - let isCustomProperty = true; + else { + let parts = this.props.controlId.split('.'); + let isCustomProperty = true; - if (parts.length === 1){ - isCustomProperty = false; - } + if (parts.length === 1){ + isCustomProperty = false; + } - isCustomProperty ? temp[parts[0]][parts[1]] = color.hex : temp[this.props.controlId] = color.hex; - isCustomProperty ? temp[parts[0]][parts[1] + "_opacity"] = color.rgb.a : temp[this.props.controlId +"_opacity"] = color.rgb.a; + isCustomProperty ? temp[parts[0]][parts[1]] = color.hex : temp[this.props.controlId] = color.hex; + isCustomProperty ? temp[parts[0]][parts[1] + "_opacity"] = color.rgb.a : temp[this.props.controlId +"_opacity"] = color.rgb.a; } this.setState({ widget: temp }); @@ -88,46 +87,45 @@ class ColorPicker extends React.Component { }; render() { - let hexColor; let opacity = 1; let parts = this.props.controlId.split('.'); let isCustomProperty = true; - if (parts.length === 1){ + if (parts.length === 1) { isCustomProperty = false; } - if(this.props.controlId === 'strokeStyle'){ - if(typeof this.state.widget.customProperties.zones[this.props.zoneIndex] !== 'undefined'){ + if (this.props.controlId === 'strokeStyle') { + if (typeof this.state.widget.customProperties.zones[this.props.zoneIndex] !== 'undefined') { hexColor = this.state.widget.customProperties.zones[this.props.zoneIndex]['strokeStyle']; } } - else if(this.props.controlId === 'lineColor'){ - if(typeof this.state.widget.customProperties.lineColors[this.props.lineIndex] !== 'undefined'){ + else if (this.props.controlId === 'lineColor') { + if (typeof this.state.widget.customProperties.lineColors[this.props.lineIndex] !== 'undefined') { hexColor = this.state.widget.customProperties.lineColors[this.props.lineIndex]; } } else{ - hexColor = isCustomProperty ? this.state.widget[parts[0]][parts[1]]: this.state.widget[this.props.controlId]; - opacity = isCustomProperty ? this.state.widget[parts[0]][parts[1] + "_opacity"]: this.state.widget[this.props.controlId + "_opacity"]; - + hexColor = isCustomProperty ? this.state.widget[parts[0]][parts[1]]: this.state.widget[this.props.controlId]; + opacity = isCustomProperty ? this.state.widget[parts[0]][parts[1] + "_opacity"]: this.state.widget[this.props.controlId + "_opacity"]; } - let rgbColor = this.hexToRgb(hexColor, opacity); - - - - return this.onClose(c)} valid={true}> -
+ return this.onClose(c)} + valid={true} + > + - - +
; } } diff --git a/src/widget/edit-widget/edit-widget-aspect-control.js b/src/widget/edit-widget/edit-widget-aspect-control.js index 3186584..a41d360 100644 --- a/src/widget/edit-widget/edit-widget-aspect-control.js +++ b/src/widget/edit-widget/edit-widget-aspect-control.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormCheck } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetAspectControl extends React.Component { constructor(props) { @@ -41,15 +41,15 @@ class EditWidgetAspectControl extends React.Component { } return ( - - + this.props.handleChange(e)}> - - + onChange={e => this.props.handleChange(e)} + /> + ); } } diff --git a/src/widget/edit-widget/edit-widget-checkbox-control.js b/src/widget/edit-widget/edit-widget-checkbox-control.js index 8a4113f..6dd8ce0 100644 --- a/src/widget/edit-widget/edit-widget-checkbox-control.js +++ b/src/widget/edit-widget/edit-widget-checkbox-control.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormCheck } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetCheckboxControl extends React.Component { constructor(props) { @@ -45,16 +45,15 @@ class EditWidgetCheckboxControl extends React.Component { } render() { - return - + this.handleCheckboxChange(e)}> - - - ; + onChange={e => this.handleCheckboxChange(e)} + /> + ; } } diff --git a/src/widget/edit-widget/edit-widget-color-control.js b/src/widget/edit-widget/edit-widget-color-control.js index aba342e..ada958f 100644 --- a/src/widget/edit-widget/edit-widget-color-control.js +++ b/src/widget/edit-widget/edit-widget-color-control.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, OverlayTrigger, Tooltip , FormLabel, Button } from 'react-bootstrap'; +import { Form, OverlayTrigger, Tooltip, Button } from 'react-bootstrap'; import ColorPicker from './color-picker' import Icon from "../../common/icon"; @@ -77,7 +77,7 @@ class EditWidgetColorControl extends Component { let style = { backgroundColor: color, opacity: opacity, - width: '260px', + width: '260px', height: '40px' } @@ -86,23 +86,20 @@ class EditWidgetColorControl extends Component { tooltipText = "Change border color"; } - - return ( - - {this.props.label} -
+ return + {this.props.label} + +
{tooltipText} } > -
+
- this.closeEditModal(data)} widget={this.state.widget} controlId={this.props.controlId} disableOpacity={this.props.disableOpacity}/> -
- - ) + this.closeEditModal(data)} widget={this.state.widget} controlId={this.props.controlId} disableOpacity={this.props.disableOpacity}/> + ; } } diff --git a/src/widget/edit-widget/edit-widget-color-zones-control.js b/src/widget/edit-widget/edit-widget-color-zones-control.js index 6ef3fcd..dd990bb 100644 --- a/src/widget/edit-widget/edit-widget-color-zones-control.js +++ b/src/widget/edit-widget/edit-widget-color-zones-control.js @@ -16,11 +16,11 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, Table, FormLabel, Button, Tooltip, OverlayTrigger } from 'react-bootstrap'; +import { Form, Table, Button, Tooltip, OverlayTrigger } from 'react-bootstrap'; import ColorPicker from './color-picker' import Icon from '../../common/icon'; -import {Collapse} from 'react-collapse'; +import { Collapse } from 'react-collapse'; class EditWidgetColorZonesControl extends React.Component { constructor(props) { @@ -51,8 +51,8 @@ class EditWidgetColorZonesControl extends React.Component { // add row const widget = this.state.widget; widget.customProperties.zones.push({ strokeStyle: '#d3cbcb', min: 0, max: 100 }); - - if(widget.customProperties.zones.length > 0){ + + if(widget.customProperties.zones.length > 0){ let length = widget.customProperties.zones.length for(let i= 0 ; i < length; i++){ @@ -67,14 +67,14 @@ class EditWidgetColorZonesControl extends React.Component { } removeZones = () => { - + let temp = this.state.widget; temp.customProperties.zones.splice(this.state.selectedIndex, 1); - if(temp.customProperties.zones.length > 0){ + if(temp.customProperties.zones.length > 0){ let length = temp.customProperties.zones.length - + for(let i= 0 ; i < length; i++){ temp.customProperties.zones[i].min = i* 100/length; temp.customProperties.zones[i].max = (i+1)* 100/length; @@ -111,8 +111,8 @@ class EditWidgetColorZonesControl extends React.Component { } } - openColorPicker = () =>{ - + openColorPicker = () => { + let color = this.state.selectedZone.strokeStyle; this.setState({showColorPicker: true, originalColor: color}); @@ -124,7 +124,7 @@ class EditWidgetColorZonesControl extends React.Component { let temp = this.state.selectedZone; temp.strokeStyle = this.state.originalColor; - + this.setState({ selectedZone : temp }); } } @@ -155,7 +155,7 @@ class EditWidgetColorZonesControl extends React.Component { if(this.state.selectedIndex !== this.state.widget.customProperties.zones.length -1){ temp.customProperties.zones[this.state.selectedIndex + 1]['min'] = e.target.value } - + this.setState({ widget: temp }); } @@ -171,17 +171,17 @@ class EditWidgetColorZonesControl extends React.Component { this.props.handleChange(event); } - + render() { const buttonStyle = { - marginBottom: '10px', + marginBottom: '10px', marginLeft: '120px', }; const iconStyle = { - height: '25px', + height: '25px', width : '25px' } @@ -194,72 +194,75 @@ class EditWidgetColorZonesControl extends React.Component { let pickerStyle = { backgroundColor: tempColor, - width: '260px', + width: '260px', height: '40px', marginTop: '20px' } - - return - Color zones + + return + Color Zones - +
{ - this.state.widget.customProperties.zones.map((zone, idx) => { - let color = zone.strokeStyle; - let width = (zone.max - zone.min)*(260/100); - let style = { - backgroundColor: color, - width: width, - height: '40px' - } - - return ( - ) + this.state.widget.customProperties.zones.map((zone, idx) => { + let color = zone.strokeStyle; + let width = (zone.max - zone.min)*(260/100); + let style = { + backgroundColor: color, + width: width, + height: '40px' } + return ( ) - + }) } -
- - Change color} > - - - - - - - - - -
- Min: - this.handleMinChange(e)} /> - - Max: - this.handleMaxChange(e)} /> -
- - - +
+ + Change color} > + + + + + + + + + +
+ Min: + this.handleMinChange(e)} /> + + Max: + this.handleMaxChange(e)} /> +
+ + +
- this.closeEditModal(data)} widget={this.state.widget} zoneIndex={this.state.selectedIndex} controlId={'strokeStyle'} /> - ; + ; } } diff --git a/src/widget/edit-widget/edit-widget-file-control.js b/src/widget/edit-widget/edit-widget-file-control.js index 7185f16..8c2aa44 100644 --- a/src/widget/edit-widget/edit-widget-file-control.js +++ b/src/widget/edit-widget/edit-widget-file-control.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel} from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditFileWidgetControl extends React.Component { @@ -59,13 +59,13 @@ class EditFileWidgetControl extends React.Component { } return
- - File - + File + this.handleFileChange(e)}>{fileOptions} - + onChange={(e) => this.handleFileChange(e)}>{fileOptions} +
; } } diff --git a/src/widget/edit-widget/edit-widget-html-content.js b/src/widget/edit-widget/edit-widget-html-content.js index 1df71d5..1bf2080 100644 --- a/src/widget/edit-widget/edit-widget-html-content.js +++ b/src/widget/edit-widget/edit-widget-html-content.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetHTMLContent extends React.Component { constructor(props) { @@ -60,20 +60,25 @@ class EditWidgetHTMLContent extends React.Component { handleKeyIgnore(event){ // This function prevents a keystroke from beeing handled by dialog.js - event.stopPropagation(); - } - + event.stopPropagation(); + } render() { return ( - - HTML Content - this.props.handleChange(e)} /> - - + + HTML Content + this.props.handleChange(e)} + /> + + ); } } - export default EditWidgetHTMLContent; diff --git a/src/widget/edit-widget/edit-widget-ic-control.js b/src/widget/edit-widget/edit-widget-ic-control.js index 7e90f81..acf2626 100644 --- a/src/widget/edit-widget/edit-widget-ic-control.js +++ b/src/widget/edit-widget/edit-widget-ic-control.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {FormGroup, FormControl, FormLabel} from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetICControl extends React.Component { @@ -60,13 +60,13 @@ class EditWidgetICControl extends React.Component { } return
- - IC - + IC + this.handleICChange(e)}>{icOptions} - + onChange={(e) => this.handleICChange(e)}>{icOptions} +
; } } diff --git a/src/widget/edit-widget/edit-widget-min-max-control.js b/src/widget/edit-widget/edit-widget-min-max-control.js index f25f23a..88e7442 100644 --- a/src/widget/edit-widget/edit-widget-min-max-control.js +++ b/src/widget/edit-widget/edit-widget-min-max-control.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel, FormCheck, Table } from 'react-bootstrap'; +import { Form, Table } from 'react-bootstrap'; class EditWidgetMinMaxControl extends React.Component { constructor(props) { @@ -75,20 +75,20 @@ class EditWidgetMinMaxControl extends React.Component { render() { - return - {this.props.label} - + {this.props.label} + this.handleCheckboxChange(e)}> - +
Min: - Max: -
-
; + ; } } diff --git a/src/widget/edit-widget/edit-widget-number-control.js b/src/widget/edit-widget/edit-widget-number-control.js index 3b3101f..18e2d90 100644 --- a/src/widget/edit-widget/edit-widget-number-control.js +++ b/src/widget/edit-widget/edit-widget-number-control.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetNumberControl extends Component { constructor(props) { @@ -48,14 +48,14 @@ class EditWidgetNumberControl extends Component { } return ( - - {this.props.label} - + {this.props.label} + this.props.handleChange(e)} /> - + ); } } diff --git a/src/widget/edit-widget/edit-widget-orientation.js b/src/widget/edit-widget/edit-widget-orientation.js index 5ac835f..7ff5252 100644 --- a/src/widget/edit-widget/edit-widget-orientation.js +++ b/src/widget/edit-widget/edit-widget-orientation.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, Col, Row, FormCheck, FormLabel } from 'react-bootstrap'; +import { Col, Row, Form } from 'react-bootstrap'; import WidgetSlider from '../widgets/slider'; @@ -50,12 +50,11 @@ class EditWidgetOrientation extends Component { } render() { - // The tag shouldn't be necessary, but it gives height to the row while combining horizontal and vertical forms return ( - + - + Orientation @@ -64,14 +63,20 @@ class EditWidgetOrientation extends Component { let value = WidgetSlider.OrientationTypes[type].value; let name = WidgetSlider.OrientationTypes[type].name; - return ( - this.handleOrientationChange(value)}> - ) + return this.handleOrientationChange(value)} + /> }) } - + ); } } diff --git a/src/widget/edit-widget/edit-widget-parameters-control.js b/src/widget/edit-widget/edit-widget-parameters-control.js index 4117fd6..d589c2e 100644 --- a/src/widget/edit-widget/edit-widget-parameters-control.js +++ b/src/widget/edit-widget/edit-widget-parameters-control.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; import ParametersEditor from '../../common/parameters-editor'; class EditWidgetParametersControl extends Component { @@ -45,10 +45,13 @@ class EditWidgetParametersControl extends Component { render() { return ( - - {this.props.label} - this.handleChange(v)} /> - + + {this.props.label} + this.handleChange(v)} + /> + ); } } diff --git a/src/widget/edit-widget/edit-widget-plot-colors-control.js b/src/widget/edit-widget/edit-widget-plot-colors-control.js index a612277..271cec2 100644 --- a/src/widget/edit-widget/edit-widget-plot-colors-control.js +++ b/src/widget/edit-widget/edit-widget-plot-colors-control.js @@ -16,11 +16,11 @@ ******************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, OverlayTrigger, Tooltip , FormLabel, Button } from 'react-bootstrap'; +import { OverlayTrigger, Tooltip , Button } from 'react-bootstrap'; import ColorPicker from './color-picker' import Icon from "../../common/icon"; -import {scaleOrdinal} from "d3-scale"; -import {schemeCategory10} from "d3-scale-chromatic"; +import { scaleOrdinal } from "d3-scale"; +import { schemeCategory10 } from "d3-scale-chromatic"; // schemeCategory20 no longer available in d3 @@ -80,33 +80,40 @@ class EditWidgetPlotColorsControl extends Component { render() { return ( - - Line Colors + + Line Colors +
+ { + this.state.widget.signalIDs.map((signalID, idx) => { + let color = this.state.widget.customProperties.lineColors[signalID]; + let width = 260 / this.state.widget.signalIDs.length; + let style = { + backgroundColor: color, + width: width, + height: '40px' + } -
- { - this.state.widget.signalIDs.map((signalID, idx) => { - let color = this.state.widget.customProperties.lineColors[signalID]; - let width = 260 / this.state.widget.signalIDs.length; - let style = { - backgroundColor: color, - width: width, - height: '40px' - } + let signal = this.props.signals.find(signal => signal.id === signalID); - let signal = this.props.signals.find(signal => signal.id === signalID); - - return ({signal.name}}> - - - ) - }) - } + return {signal.name}} + > + + ; + }) + }
this.closeEditModal(data)} widget={this.state.widget} lineIndex={this.state.selectedIndex} controlId={'lineColor'} disableOpacity={true}/> - + ) } diff --git a/src/widget/edit-widget/edit-widget-signal-control.js b/src/widget/edit-widget/edit-widget-signal-control.js index cc9135d..d9667e3 100644 --- a/src/widget/edit-widget/edit-widget-signal-control.js +++ b/src/widget/edit-widget/edit-widget-signal-control.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetSignalControl extends Component { constructor(props) { @@ -48,9 +48,9 @@ class EditWidgetSignalControl extends Component { render() { return ( - - Select signal - this.handleSignalChange(e)}> + + Select signal + this.handleSignalChange(e)}> { this.state.signals.length === 0 ? ( @@ -61,8 +61,8 @@ class EditWidgetSignalControl extends Component { )) ) } - - + + ); } } diff --git a/src/widget/edit-widget/edit-widget-signals-control.js b/src/widget/edit-widget/edit-widget-signals-control.js index ad4658b..007b1fe 100644 --- a/src/widget/edit-widget/edit-widget-signals-control.js +++ b/src/widget/edit-widget/edit-widget-signals-control.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, FormCheck, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetSignalsControl extends Component { constructor(props) { @@ -55,25 +55,25 @@ class EditWidgetSignalsControl extends Component { render() { return ( - - Signals + + Signals { this.state.signals === 0 || !this.state.widget.hasOwnProperty(this.props.controlId)? ( - No signals available + No signals available ) : ( this.state.signals.map((signal, index) => ( - id === signal.id) !== undefined} onChange={(e) => this.handleSignalChange(e.target.checked, signal.id)}> - + )) ) } - + ); } } diff --git a/src/widget/edit-widget/edit-widget-text-control.js b/src/widget/edit-widget/edit-widget-text-control.js index 22aac97..5392ca1 100644 --- a/src/widget/edit-widget/edit-widget-text-control.js +++ b/src/widget/edit-widget/edit-widget-text-control.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetTextControl extends Component { constructor(props) { @@ -60,11 +60,11 @@ class EditWidgetTextControl extends Component { render() { return ( - - {this.props.label} - this.props.handleChange(e)} /> - - + + {this.props.label} + this.props.handleChange(e)} /> + + ); } } diff --git a/src/widget/edit-widget/edit-widget-text-size-control.js b/src/widget/edit-widget/edit-widget-text-size-control.js index 10e7922..ce3b131 100644 --- a/src/widget/edit-widget/edit-widget-text-size-control.js +++ b/src/widget/edit-widget/edit-widget-text-size-control.js @@ -16,21 +16,21 @@ **********************************************************************************/ import React from 'react'; -import { FormGroup, FormControl, FormLabel } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetTextSizeControl extends React.Component { render() { const sizes = [11, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 46, 52, 60, 72]; return ( - - Text size - this.props.handleChange(e)}> + + Text size + this.props.handleChange(e)}> {sizes.map((size, index) => ( ))} - - + + ); } } diff --git a/src/widget/edit-widget/edit-widget-time-control.js b/src/widget/edit-widget/edit-widget-time-control.js index 23fb368..ea4eeff 100644 --- a/src/widget/edit-widget/edit-widget-time-control.js +++ b/src/widget/edit-widget/edit-widget-time-control.js @@ -16,7 +16,7 @@ **********************************************************************************/ import React, { Component } from 'react'; -import { FormGroup, FormControl, FormLabel, FormText } from 'react-bootstrap'; +import { Form } from 'react-bootstrap'; class EditWidgetTimeControl extends Component { constructor(props) { @@ -43,9 +43,9 @@ class EditWidgetTimeControl extends Component { } return ( - - Time - + Time + this.props.handleChange(e)} /> - Time in seconds - + Time in seconds + ); } } diff --git a/src/widget/edit-widget/edit-widget.js b/src/widget/edit-widget/edit-widget.js index 5d0d601..e7792a8 100644 --- a/src/widget/edit-widget/edit-widget.js +++ b/src/widget/edit-widget/edit-widget.js @@ -16,13 +16,13 @@ ******************************************************************************/ import React from 'react'; +import { Form } from 'react-bootstrap'; import Dialog from '../../common/dialogs/dialog'; import CreateControls from './edit-widget-control-creator'; class EditWidgetDialog extends React.Component { valid = true; - constructor(props) { super(props); @@ -37,7 +37,6 @@ class EditWidgetDialog extends React.Component { }; } - onClose(canceled) { if (canceled === false) { this.props.onClose(this.state.temporal); @@ -52,9 +51,9 @@ class EditWidgetDialog extends React.Component { const file = this.props.files.find(element => element.id === fileId); // scale width to match aspect - if(file.imageWidth && file.imageHeight){ - const aspectRatio = file.imageWidth / file.imageHeight; - changeObject.width = parseInt(this.state.temporal.height * aspectRatio,10); + if (file.imageWidth && file.imageHeight) { + const aspectRatio = file.imageWidth / file.imageHeight; + changeObject.width = parseInt(this.state.temporal.height * aspectRatio,10); } return changeObject; @@ -69,26 +68,21 @@ class EditWidgetDialog extends React.Component { return metrics.width; } - setMaxWidth(changeObject){ - if(changeObject.type === 'Label'){ + setMaxWidth(changeObject) { + if (changeObject.type === 'Label') { changeObject.customProperties.maxWidth = Math.ceil(this.getTextWidth(changeObject.name, changeObject.customProperties.textSize)); changeObject.width = changeObject.customProperties.maxWidth; } - /*else if (changeObject.type === 'Value'){ - changeObject.customProperties.maxWidth = Math.ceil(this.getTextWidth(changeObject.name, changeObject.customProperties.textSize)); - } - if(this.state.temporal.width > changeObject.customProperties.maxWidth){ - changeObject.width = changeObject.customProperties.maxWidth; - }*/ + return changeObject; } - setNewLockRestrictions(changeObject){ - if(changeObject.customProperties.orientation === 0){ + setNewLockRestrictions(changeObject) { + if (changeObject.customProperties.orientation === 0) { changeObject.customProperties.resizeTopBottomLock = true; changeObject.customProperties.resizeRightLeftLock = false; } - else if(changeObject.customProperties.orientation === 1){ + else if (changeObject.customProperties.orientation === 1) { changeObject.customProperties.resizeTopBottomLock = false; changeObject.customProperties.resizeRightLeftLock = true; } @@ -96,7 +90,6 @@ class EditWidgetDialog extends React.Component { } handleChange(e) { - // TODO: check what we really need in this function. Can we reduce its complexity? let parts = e.target.id.split('.'); let changeObject = this.state.temporal; @@ -174,10 +167,17 @@ class EditWidgetDialog extends React.Component { } return ( - this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}> -
+ this.onClose(c)} + onReset={() => this.resetState()} + valid={this.valid} + > + { controls || '' } - +
); } diff --git a/src/widget/widget-plot/plot-legend.js b/src/widget/widget-plot/plot-legend.js index 4dd7459..00d1b77 100644 --- a/src/widget/widget-plot/plot-legend.js +++ b/src/widget/widget-plot/plot-legend.js @@ -17,7 +17,7 @@ import React from 'react'; import { scaleOrdinal} from 'd3-scale'; -import {schemeCategory10} from 'd3-scale-chromatic' +import { schemeCategory10 } from 'd3-scale-chromatic' function Legend(props){ @@ -44,7 +44,6 @@ function Legend(props){ ) } - } class PlotLegend extends React.Component { @@ -60,7 +59,6 @@ class PlotLegend extends React.Component { )) } -
; } diff --git a/src/widget/widget-plot/plot.js b/src/widget/widget-plot/plot.js index 6f314fe..17e61fc 100644 --- a/src/widget/widget-plot/plot.js +++ b/src/widget/widget-plot/plot.js @@ -17,7 +17,7 @@ import React from 'react'; import { scaleLinear, scaleTime, scaleOrdinal} from 'd3-scale'; -import {schemeCategory10} from 'd3-scale-chromatic' +import { schemeCategory10 } from 'd3-scale-chromatic' import { extent } from 'd3-array'; import { line } from 'd3-shape'; import { axisBottom, axisLeft } from 'd3-axis'; @@ -103,7 +103,6 @@ class Plot extends React.Component { const xAxis = axisBottom().scale(xScale).ticks(5).tickFormat(timeFormat("%M:%S")); const yAxis = axisLeft().scale(yScale).ticks(5).tickFormat(format(".3s")); - return{ stopTime: stopTime, data: null, @@ -113,7 +112,6 @@ class Plot extends React.Component { }; } - // only show data in requested time let data = props.data; let icDataset = data.find(function(element) { @@ -138,8 +136,6 @@ class Plot extends React.Component { if (prevProps.time !== this.props.time) { this.createInterval(); } - - } createInterval() { @@ -222,7 +218,6 @@ class Plot extends React.Component { } render() { - const yLabelPos = { x: 12, y: this.props.height / 2 diff --git a/src/widget/widget-toolbox.js b/src/widget/widget-toolbox.js index ee48d37..65e856e 100644 --- a/src/widget/widget-toolbox.js +++ b/src/widget/widget-toolbox.js @@ -16,12 +16,11 @@ ******************************************************************************/ import React from 'react'; +import { Collapse } from 'react-collapse'; import PropTypes from 'prop-types'; import Slider from 'rc-slider'; import { Button, OverlayTrigger, Tooltip } from 'react-bootstrap'; import Icon from "../common/icon"; -import {Collapse} from 'react-collapse'; - import ToolboxItem from './toolbox-item'; class WidgetToolbox extends React.Component { @@ -101,8 +100,8 @@ class WidgetToolbox extends React.Component { } const buttonStyle = { - marginRight: '3px', - height: '40px', + marginRight: '3px', + height: '40px', } const thereIsTopologyWidget = this.props.widgets != null && Object.values(this.props.widgets).filter(w => w.type === 'Topology').length > 0; diff --git a/src/widget/widgets/gauge.js b/src/widget/widgets/gauge.js index b33494a..28dff4f 100644 --- a/src/widget/widgets/gauge.js +++ b/src/widget/widgets/gauge.js @@ -17,7 +17,6 @@ import React, { Component } from 'react'; import { Gauge } from 'gaugeJS'; -//import {update} from "immutable"; class WidgetGauge extends Component { constructor(props) { @@ -70,7 +69,6 @@ class WidgetGauge extends Component { this.gauge.set(this.state.value); this.updateLabels(this.state.minValue, this.state.maxValue) } - } static getDerivedStateFromProps(props, state){ @@ -79,12 +77,12 @@ class WidgetGauge extends Component { return{ value: 0, minValue: 0, maxValue: 10}; } - // get the signal with the selected signal ID + // Get the signal with the selected signal ID let signalID = props.widget.signalIDs[0]; let signal = props.signals.filter(s => s.id === signalID) if(signal.length > 0) { - // determine ID of infrastructure component related to signal[0] (there is only one signal for a lamp widget) + // Determine ID of infrastructure component related to signal[0] (there is only one signal for a lamp widget) let icID = props.icIDs[signal[0].id]; let returnState = {} @@ -100,9 +98,9 @@ class WidgetGauge extends Component { returnState["scalingFactor"] = signal[0].scalingFactor; } - // update value + // Update value - // check if data available + // Check if data available if (props.data == null || props.data[icID] == null || props.data[icID].output == null @@ -114,12 +112,12 @@ class WidgetGauge extends Component { return returnState; } - // memorize if min or max value is updated + // Memorize if min or max value is updated let updateValue = false; let updateMinValue = false; let updateMaxValue = false; - // check if value has changed + // Check if value has changed const data = props.data[icID].output.values[signal[0].index - 1]; // Take just 3 decimal positions // Note: Favor this method over Number.toFixed(n) in order to avoid a type conversion, since it returns a String @@ -129,10 +127,10 @@ class WidgetGauge extends Component { let maxValue = null; if ((state.value !== value && value != null) || props.widget.customProperties.valueUseMinMax || state.useMinMaxChange) { - //value has changed + // Value has changed updateValue = true; - // update min-max if needed + // Update min-max if needed let updateLabels = false; minValue = state.minValue; @@ -157,7 +155,6 @@ class WidgetGauge extends Component { maxValue = props.widget.customProperties.valueMax; updateMaxValue = true; updateLabels = true; - } if (updateLabels === false && state.gauge) { @@ -178,7 +175,7 @@ class WidgetGauge extends Component { returnState["useMinMax"] = props.widget.customProperties.valueUseMinMax; } - // prepare returned state + // Prepare returned state if (updateValue === true) { returnState["value"] = value; } @@ -190,7 +187,7 @@ class WidgetGauge extends Component { } - } // if there is signal data + } // If there is signal data if (JSON.stringify(returnState) !== JSON.stringify({})) { return returnState; @@ -198,8 +195,8 @@ class WidgetGauge extends Component { return null; } } - return null; + return null; } updateLabels(minValue, maxValue, force) { @@ -223,17 +220,17 @@ class WidgetGauge extends Component { }); } - if(this.state.signalID !== ''){ - this.gauge.setOptions({ - staticLabels: { - font: '10px "Helvetica Neue"', - labels, - color: "#000000", - fractionDigits: 1 - }, - staticZones: zones - }); - } + if (this.state.signalID !== '') { + this.gauge.setOptions({ + staticLabels: { + font: '10px "Helvetica Neue"', + labels, + color: "#000000", + fractionDigits: 1 + }, + staticZones: zones + }); + } } computeGaugeOptions(widget) { @@ -267,8 +264,6 @@ class WidgetGauge extends Component { this.gaugeCanvas = node} />
{this.state.unit + scaleText}
{this.state.value}
- -
); } diff --git a/src/widget/widgets/input.js b/src/widget/widgets/input.js index 142f4e2..21c0421 100644 --- a/src/widget/widgets/input.js +++ b/src/widget/widgets/input.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React, { Component } from 'react'; -import { Form, FormGroup, Col, FormLabel, FormControl, InputGroup } from 'react-bootstrap'; +import { Form, Col, InputGroup } from 'react-bootstrap'; class WidgetInput extends Component { @@ -87,13 +87,13 @@ class WidgetInput extends Component { return (
- - + + {this.props.widget.name} - - +
); diff --git a/src/widget/widgets/time-offset.js b/src/widget/widgets/time-offset.js index ee429e8..9e931b2 100644 --- a/src/widget/widgets/time-offset.js +++ b/src/widget/widgets/time-offset.js @@ -17,8 +17,7 @@ import React, { Component } from 'react'; import TrafficLight from 'react-trafficlight'; -import {OverlayTrigger, Tooltip } from 'react-bootstrap'; - +import { OverlayTrigger, Tooltip } from 'react-bootstrap'; class WidgetTimeOffset extends Component { constructor(props) { @@ -51,7 +50,7 @@ class WidgetTimeOffset extends Component { let serverTime = props.data[state.icID].output.timestamp; let localTime = Date.now(); let absoluteOffset = Math.abs(serverTime - localTime); - + if(typeof websocket === 'undefined'){ return {timeOffset: Number.parseFloat(absoluteOffset/1000).toPrecision(5)} } @@ -68,25 +67,25 @@ class WidgetTimeOffset extends Component { } return (
- {this.props.widget.customProperties.icID !== -1 ? + {this.props.widget.customProperties.icID !== -1 ? () : (no IC) } - {this.props.widget.customProperties.icID !== -1 && this.props.widget.customProperties.showName ? + {this.props.widget.customProperties.icID !== -1 && this.props.widget.customProperties.showName ? ({this.state.icName}) : () - } + } - {this.props.widget.customProperties.icID !== -1 ? - ({this.state.icName}

Offset: {this.state.timeOffset + "s"}
) - : + {this.props.widget.customProperties.icID !== -1 ? + ({this.state.icName}

Offset: {this.state.timeOffset + "s"}
) + : (Please select Infrastructure Component)} - }> + }>
- {this.props.widget.customProperties.icID !== -1 ? + {this.props.widget.customProperties.icID !== -1 ? ( {icSelected}) : diff --git a/src/widget/widgets/topology.js b/src/widget/widgets/topology.js index 1eb64fc..d87cca0 100644 --- a/src/widget/widgets/topology.js +++ b/src/widget/widgets/topology.js @@ -16,7 +16,7 @@ ******************************************************************************/ import React from 'react'; -import {UncontrolledReactSVGPanZoom} from 'react-svg-pan-zoom'; +import { UncontrolledReactSVGPanZoom } from 'react-svg-pan-zoom'; import '../../styles/simple-spinner.css'; import { cimsvg } from 'libcimsvg'; import AppDispatcher from "../../common/app-dispatcher"; @@ -94,7 +94,7 @@ class WidgetTopology extends React.Component { } static getDerivedStateFromProps(props, state){ - // find the selected file of the widget, is undefined if no file is selected + // Find the selected file of the widget, is undefined if no file is selected let file = props.files.find(file => file.id === parseInt(props.widget.customProperties.file, 10)); let dashboardState = state.dashboardState; @@ -104,7 +104,7 @@ class WidgetTopology extends React.Component { dashboardState = 'show_message'; message = 'Select a topology model.' } else if (!file.hasOwnProperty('data') && dashboardState === 'show_message'){ - // data of file is missing, start download + // Data of file is missing, start download dashboardState = 'loading'; message = ''; AppDispatcher.dispatch({ @@ -113,7 +113,7 @@ class WidgetTopology extends React.Component { token: props.token }); } else if (file.hasOwnProperty('data') && (dashboardState === 'loading'|| dashboardState === 'show_message')){ - //file is available set state to ready + // File is available set state to ready dashboardState = 'ready' message = ''; } @@ -135,8 +135,6 @@ class WidgetTopology extends React.Component { window.onMouseMove = function() {}; } - //this.Viewer.fitToViewer(); - // Query the file referenced by the widget (if any) if (this.state.file !== undefined) { this.setState({dashboardState: 'loading'}); @@ -155,7 +153,7 @@ class WidgetTopology extends React.Component { componentDidUpdate(prevProps: Readonly

, prevState: Readonly, snapshot: SS): void { if(this.state.dashboardState === 'ready'){ - //Topology file incl data downloaded, init SVG (should happen only once!) + // Topology file incl data downloaded, init SVG (should happen only once!) if (this.svgElem) { let cimsvgInstance = new cimsvg(this.svgElem.current); cimsvg.setCimsvg(cimsvgInstance);