mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Merge branch 'master' into react-update
# Conflicts: # src/app.js # src/dashboard/dashboard.js # src/ic/ic-dialog.js # src/user/login.js
This commit is contained in:
commit
84dbb81cb0
74 changed files with 2013 additions and 1791 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -18,3 +18,4 @@ yarn-error.log*
|
|||
.vscode/
|
||||
*.code-workspace
|
||||
package-lock.json
|
||||
.eslintcache
|
||||
|
|
72
src/app.js
72
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';
|
||||
|
@ -48,9 +46,7 @@ class App extends React.Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showSidebarMenu: false,
|
||||
}
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
static getStores() {
|
||||
|
@ -77,14 +73,6 @@ class App extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
showSidebarMenu = () => {
|
||||
this.setState({ showSidebarMenu: true });
|
||||
};
|
||||
|
||||
hideSidebarMenu = () => {
|
||||
this.setState({ showSidebarMenu: false });
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
let token = localStorage.getItem("token");
|
||||
|
@ -97,46 +85,32 @@ class App extends React.Component {
|
|||
|
||||
let currentUser = JSON.parse(currentUserRaw);
|
||||
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend} >
|
||||
<div>
|
||||
{/*
|
||||
<Col style={{ width: this.state.showSidebarMenu ? '280px' : '0px' }} smHidden mdHidden lgHidden className="sidenav">
|
||||
*/}
|
||||
<Hidden sm md lg xl xxl>
|
||||
<Col style={{ width: this.state.showSidebarMenu ? '280px' : '0px' }} className="sidenav">
|
||||
<HeaderMenu onClose={this.hideSidebarMenu} currentRole={currentUser.role} />
|
||||
</Col>
|
||||
</Hidden>
|
||||
return <DndProvider backend={HTML5Backend} >
|
||||
<div className="app">
|
||||
<NotificationSystem
|
||||
ref="notificationSystem"
|
||||
/>
|
||||
<Header />
|
||||
|
||||
<div className="app">
|
||||
<NotificationSystem ref="notificationSystem" />
|
||||
<div className='app-body app-body-spacing'>
|
||||
<Menu currentRole={currentUser.role} />
|
||||
|
||||
<Header onMenuButton={this.showSidebarMenu} showMenuButton={false} />
|
||||
|
||||
<div className={`app-body app-body-spacing`} >
|
||||
<Col xs={false}>
|
||||
<SidebarMenu currentRole={currentUser.role} />
|
||||
</Col>
|
||||
|
||||
<div className={`app-content app-content-margin-left`}>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/home" component={Home} />
|
||||
<Route exact path="/scenarios" component={Scenarios} />
|
||||
<Route path="/scenarios/:scenario" component={Scenario} />
|
||||
<Route path="/dashboards/:dashboard" component={Dashboard} />
|
||||
<Route path="/infrastructure" component={InfrastructureComponents} />
|
||||
<Route path="/account" component={User} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route path="/api" component={APIBrowser} />
|
||||
</div>
|
||||
<div className='app-content app-content-margin-left'>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/home" component={Home} />
|
||||
<Route exact path="/scenarios" component={Scenarios} />
|
||||
<Route path="/scenarios/:scenario" component={Scenario} />
|
||||
<Route path="/dashboards/:dashboard" component={Dashboard} />
|
||||
<Route path="/infrastructure" component={InfrastructureComponents} />
|
||||
<Route path="/account" component={User} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route path="/api" component={APIBrowser} />
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</DndProvider>
|
||||
)
|
||||
</DndProvider>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
|||
<Modal.Body>
|
||||
Are you sure you want to delete the {this.props.title} <strong>'{this.props.name}'</strong>?
|
||||
<Collapse isOpened={this.props.managedexternally} >
|
||||
<FormLabel size="sm">The IC will be deleted if the respective manager sends "gone" state and no component config is using the IC anymore</FormLabel>
|
||||
<Form.Label size="sm">The IC will be deleted if the respective manager sends "gone" state and no component config is using the IC anymore</Form.Label>
|
||||
</Collapse>
|
||||
</Modal.Body>
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class Dialog extends React.Component {
|
|||
};
|
||||
|
||||
return (
|
||||
<Modal size={this.props.size || 'sm'} keyboard show={this.props.show} onEnter={this.props.onReset} onHide={this.cancelModal} onKeyPress={this.onKeyPress}>
|
||||
<Modal size={this.props.size || 'lg'} keyboard show={this.props.show} onEnter={this.props.onReset} onHide={this.cancelModal} onKeyPress={this.onKeyPress}>
|
||||
<Modal.Header>
|
||||
<Modal.Title>{this.props.title}</Modal.Title>
|
||||
</Modal.Header>
|
||||
|
|
|
@ -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 <div>
|
||||
<form style={wrapperStyle}>
|
||||
<FormControl type='text' size='large' value={this.state.title} onChange={this.onChange} style={editStyle} autoFocus />
|
||||
</form>
|
||||
<Form style={wrapperStyle}>
|
||||
<Form.Control
|
||||
type='text'
|
||||
size='large'
|
||||
value={this.state.title}
|
||||
onChange={this.onChange}
|
||||
style={editStyle}
|
||||
autoFocus
|
||||
/>
|
||||
</Form>
|
||||
|
||||
<Button onClick={this.save}><Icon icon='check' style={iconStyle} /></Button>
|
||||
<Button onClick={this.cancel}><Icon icon='times' style={iconStyle} /></Button>
|
||||
<Button
|
||||
onClick={this.save}>
|
||||
<Icon icon='check' style={iconStyle} />
|
||||
</Button>
|
||||
<Button
|
||||
onClick={this.cancel}>
|
||||
<Icon icon='times' style={iconStyle} />
|
||||
</Button>
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
export default class HeaderMenu extends React.Component {
|
||||
render() {
|
||||
return <div>
|
||||
|
||||
<Button className="closeButton" variant="link" onClick={this.props.onClose}>×</Button>
|
||||
|
||||
<ul>
|
||||
<li><NavLink to="/home" activeClassName="active" title="Home" onClick={this.props.onClose}>Home</NavLink></li>
|
||||
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios" onClick={this.props.onClose}>Scenarios</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure Components" onClick={this.props.onClose}>Infrastructure Components</NavLink></li>
|
||||
{ this.props.currentRole === 'Admin' ?
|
||||
<li><NavLink to="/users" activeClassName="active" title="User Management" onClick={this.props.onClose}>User Management</NavLink></li> : ''
|
||||
}
|
||||
<li><NavLink to="/account" title="Account">Account</NavLink></li>
|
||||
<li><NavLink to="/logout" title="Logout" onClick={this.props.onClose}>Logout</NavLink></li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -25,18 +25,7 @@ class Header extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<header className="app-header">
|
||||
<Col xs={{span: 10}} sm={{span: 8, offset: 2}}>
|
||||
<h1>{config.instance} - {config.subtitle}</h1>
|
||||
</Col>
|
||||
<Hidden sm md lg xl>
|
||||
<Col xs={2} style={{ paddingLeft: 'auto', paddingRight: 0 }}>
|
||||
{this.props.showMenuButton &&
|
||||
<Button variant="link" onClick={this.props.onMenuButton} style={{ float: 'right', marginRight: '10px' }}>
|
||||
<Icon size="3x" icon="bars" className="menu-icon" />
|
||||
</Button>
|
||||
}
|
||||
</Col>
|
||||
</Hidden>
|
||||
<h1>{config.instance} - {config.subtitle}</h1>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -100,8 +100,8 @@ class Home extends React.Component {
|
|||
<h3>Funding</h3>
|
||||
<p>The development of <a href="http://fein-aachen.org/projects/villas-framework/">VILLASframework</a> projects has received funding from</p>
|
||||
<ul>
|
||||
<p>SLEW: Second Life for Energiewende, an Exploratory Teaching Space project funded by RWTH Aachen University</p>
|
||||
<p><a href="https://erigrid2.eu/"> ERIgrid 2.0: </a> An EU Horizon 2020 research and innovation action project for connecting European Smart Grid Infrastructures (grant agreement No 870620)</p>
|
||||
<p><a href="https://www.acs.eonerc.rwth-aachen.de/cms/E-ON-ERC-ACS/Forschung/Forschungsprojekte/Bildungsprojekte/~mikmu/SLEW-SECOND-LIFE-FOR-ENERGIEWENDE/">SLEW:</a> Second Life for Energiewende, an Exploratory Teaching Space project funded by RWTH Aachen University</p>
|
||||
<p><a href="https://erigrid2.eu/">ERIgrid 2.0:</a> An EU Horizon 2020 research and innovation action project for connecting European Smart Grid Infrastructures (grant agreement No 870620)</p>
|
||||
<p>
|
||||
<img height={100} src={require('../img/european_commission.svg').default} alt="Logo EU" />
|
||||
<img height={70} src={require('../img/erigrid2.png').default} alt="Logo ERIgrid 2.0" />
|
||||
|
|
56
src/common/icon-button.js
Normal file
56
src/common/icon-button.js
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
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 <OverlayTrigger
|
||||
key={this.props.key}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}>{this.props.tooltip}</Tooltip>} >
|
||||
<Button
|
||||
variant='light'
|
||||
onClick={this.props.onClick}
|
||||
style={altButtonStyle}
|
||||
>
|
||||
<Icon
|
||||
icon={this.props.icon}
|
||||
classname={'icon-color'}
|
||||
style={iconStyle}
|
||||
/>
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
}
|
||||
}
|
||||
|
||||
export default IconButton;
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -38,9 +38,10 @@ class SidebarMenu extends React.Component {
|
|||
|
||||
static calculateState(prevState, props) {
|
||||
let config = LoginStore.getState().config;
|
||||
let externalauth = _.get(config, ['authentication', 'external', 'enabled']);
|
||||
let logout_url = _.get(config, ['authentication', 'logout_url']);
|
||||
|
||||
if (logout_url) {
|
||||
if (externalauth && logout_url) {
|
||||
return {
|
||||
externalAuth: true,
|
||||
logoutLink: logout_url,
|
||||
|
@ -61,40 +62,33 @@ class SidebarMenu extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (this.state.externalAuth) {
|
||||
return (
|
||||
<div className="menu-sidebar">
|
||||
<h2>Menu</h2>
|
||||
return (
|
||||
<div className="menu">
|
||||
<h2>Menu</h2>
|
||||
|
||||
{this.state.externalAuth ?
|
||||
<ul>
|
||||
<li><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
|
||||
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure Components">Infrastructure Components</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure">Infrastructure</NavLink></li>
|
||||
{ this.props.currentRole === 'Admin' ?
|
||||
<li><NavLink to="/users" activeClassName="active" title="User Management">User Management</NavLink></li> : ''
|
||||
<li><NavLink to="/users" activeClassName="active" title="Users">Users</NavLink></li> : ''
|
||||
}
|
||||
<li><NavLink to="/account" title="Account">Account</NavLink></li>
|
||||
<a onClick={this.logout.bind(this)} href={this.state.logoutLink}>Logout</a>
|
||||
<li><NavLink to="/api" title="API Browser">API Browser</NavLink></li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="menu-sidebar">
|
||||
<h2>Menu</h2>
|
||||
|
||||
<ul>
|
||||
: <ul>
|
||||
<li><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
|
||||
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure Components">Infrastructure Components</NavLink></li>
|
||||
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure">Infrastructure</NavLink></li>
|
||||
{ this.props.currentRole === 'Admin' ?
|
||||
<li><NavLink to="/users" activeClassName="active" title="User Management">User Management</NavLink></li> : ''
|
||||
<li><NavLink to="/users" activeClassName="active" title="Users">Users</NavLink></li> : ''
|
||||
}
|
||||
<li><NavLink to="/account" title="Account">Account</NavLink></li>
|
||||
<li><NavLink to={this.state.logoutLink} title="Logout">Logout</NavLink></li>
|
||||
<li><NavLink to="/api" title="API Browser">API Browser</NavLink></li>
|
||||
</ul>
|
||||
</ul>}
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -39,16 +39,19 @@ class TableColumn extends Component {
|
|||
checkboxKey: '',
|
||||
checkboxDisabled: null,
|
||||
labelStyle: null,
|
||||
labelModifier: null
|
||||
|
||||
labelModifier: null,
|
||||
align: 'left'
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<th width={this.props.width}>
|
||||
{this.props.title}
|
||||
</th>
|
||||
);
|
||||
let style = {
|
||||
textAlign: this.props.align,
|
||||
width: this.props.width
|
||||
};
|
||||
|
||||
return <th style={style}>
|
||||
{this.props.title}
|
||||
</th>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
|||
<OverlayTrigger
|
||||
key={contentkey}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={`tooltip-${"export"}`}>Download {contentvalue}</Tooltip>} >
|
||||
overlay={<Tooltip id={`tooltip-${"export"}`}>Download {contentvalue}</Tooltip>}
|
||||
>
|
||||
<Button
|
||||
variant='table-control-button'
|
||||
onClick={() => child.props.onDownload(contentkey)}
|
||||
disabled={child.props.onDownload == null}>
|
||||
{contentkey + ' ' }
|
||||
{contentkey + ' '}
|
||||
<Icon icon='file-download' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
|
@ -111,56 +112,56 @@ class CustomTable extends Component {
|
|||
|
||||
cell.push(<span>
|
||||
|
||||
<FormLabel column={false} className={labelStyle}>
|
||||
<Form.Label
|
||||
column={false}
|
||||
className={labelStyle}>
|
||||
{labelContent}
|
||||
</FormLabel>
|
||||
</Form.Label>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
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(
|
||||
<OverlayTrigger
|
||||
key={0}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={`tooltip-${"edit"}`}> Edit </Tooltip>}>
|
||||
<Button
|
||||
variant='table-control-button'
|
||||
onClick={() => child.props.onEdit(index)}
|
||||
disabled={child.props.onEdit == null} >
|
||||
<Icon icon='edit' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
}
|
||||
}
|
||||
let showEditButton = child.props.showEditButton !== null && child.props.showEditButton !== undefined
|
||||
? child.props.showEditButton(index)
|
||||
: true;
|
||||
|
||||
if (child.props.editButton && showEditButton) {
|
||||
cell.push(
|
||||
<OverlayTrigger
|
||||
key={0}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={`tooltip-${"edit"}`}> Edit </Tooltip>}
|
||||
>
|
||||
<Button
|
||||
variant='table-control-button'
|
||||
onClick={() => child.props.onEdit(index)}
|
||||
disabled={child.props.onEdit == null} >
|
||||
<Icon icon='edit' />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
<FormCheck
|
||||
<Form.Check
|
||||
className="table-control-checkbox"
|
||||
inline
|
||||
disabled = {isDisabled}
|
||||
disabled={isDisabled}
|
||||
checked={checkboxKey ? data[checkboxKey] : null}
|
||||
onChange={e => child.props.onChecked(data, e)}
|
||||
/>);
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (child.props.exportButton) {
|
||||
|
@ -168,14 +169,16 @@ class CustomTable extends Component {
|
|||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={`tooltip-${"export"}`}> Export </Tooltip>} >
|
||||
overlay={<Tooltip id={`tooltip-${"export"}`}> Export </Tooltip>}
|
||||
>
|
||||
<Button
|
||||
variant='table-control-button'
|
||||
onClick={() => child.props.onExport(index)}
|
||||
disabled={child.props.onExport == null}>
|
||||
<Icon icon='download' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
if (child.props.duplicateButton) {
|
||||
|
@ -190,7 +193,8 @@ class CustomTable extends Component {
|
|||
disabled={child.props.onDuplicate == null}>
|
||||
<Icon icon='copy' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
if (child.props.addRemoveFilesButton) {
|
||||
|
@ -205,7 +209,8 @@ class CustomTable extends Component {
|
|||
disabled={child.props.onAddRemove == null}>
|
||||
<Icon icon='file' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
if (child.props.downloadAllButton) {
|
||||
|
@ -220,35 +225,32 @@ class CustomTable extends Component {
|
|||
disabled={child.props.onDownloadAll == null}>
|
||||
<Icon icon='file-download' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
let showDeleteButton = true;
|
||||
if (child.props.showDeleteButton !== null){
|
||||
showDeleteButton = child.props.showDeleteButton(index)
|
||||
let showDeleteButton = child.props.showDeleteButton !== null && child.props.showDeleteButton !== undefined
|
||||
? child.props.showDeleteButton(index)
|
||||
: true;
|
||||
|
||||
if (child.props.deleteButton && showDeleteButton) {
|
||||
cell.push(
|
||||
<OverlayTrigger
|
||||
key={5}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={`tooltip-${"delete"}`}> Delete </Tooltip>} >
|
||||
<Button
|
||||
variant='table-control-button'
|
||||
onClick={() => child.props.onDelete(index)}
|
||||
disabled={child.props.onDelete == null}>
|
||||
<Icon icon='trash' />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
if (showDeleteButton){
|
||||
if (child.props.deleteButton) {
|
||||
cell.push(
|
||||
<OverlayTrigger
|
||||
key={5}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={`tooltip-${"delete"}`}> Delete </Tooltip>} >
|
||||
<Button
|
||||
variant='table-control-button'
|
||||
onClick={() => child.props.onDelete(index)}
|
||||
disabled={child.props.onDelete == null}>
|
||||
<Icon icon='trash' />
|
||||
</Button>
|
||||
</OverlayTrigger>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return cell;
|
||||
} // addCell
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
const rows = CustomTable.getRows(props);
|
||||
|
@ -311,49 +313,53 @@ class CustomTable extends Component {
|
|||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
this.state.rows.map((row, rowIndex) => (
|
||||
this.state.rows.map((row, rowIndex) =>
|
||||
<tr key={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 (<td
|
||||
return <td
|
||||
key={cellIndex}
|
||||
style={cellStyle}
|
||||
tabIndex={tabIndex}
|
||||
onClick={evtHdls.onCellClick}
|
||||
onFocus={evtHdls.onCellFocus}
|
||||
onBlur={evtHdls.onCellBlur}>
|
||||
{(this.state.editCell[0] === cellIndex && this.state.editCell[1] === rowIndex) ? (
|
||||
<FormControl
|
||||
onBlur={evtHdls.onCellBlur}
|
||||
>
|
||||
{(this.state.editCell[0] === cellIndex && this.state.editCell[1] === rowIndex) ?
|
||||
<Form.Control
|
||||
as='input'
|
||||
type={children[cellIndex].props.inputType}
|
||||
value={cell}
|
||||
onChange={(event) => children[cellIndex].props.onInlineChange(event, rowIndex, cellIndex)}
|
||||
ref={ref => { this.activeInput = ref; }} />
|
||||
) : (
|
||||
<span>
|
||||
{cell.map((element, elementIndex) => (
|
||||
: <span>
|
||||
{
|
||||
cell.map((element, elementIndex) =>
|
||||
<span key={elementIndex}>{element}</span>
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
</td>)
|
||||
)
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</td>
|
||||
})
|
||||
}
|
||||
</tr>))
|
||||
</tr>)
|
||||
}
|
||||
</tbody>
|
||||
</Table>
|
||||
|
|
|
@ -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}
|
||||
>
|
||||
<form>
|
||||
<FormGroup controlId="name">
|
||||
<FormLabel column={false}>Name</FormLabel>
|
||||
<FormControl
|
||||
<Form>
|
||||
<Form.Group controlId="name">
|
||||
<Form.Label column={false}>Name</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
placeholder={this.props.config.name}
|
||||
value={this.state.name}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
/>
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup controlId="icID">
|
||||
<FormLabel column={false}> Infrastructure Component </FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId="icID">
|
||||
<Form.Label column={false}> Infrastructure Component </Form.Label>
|
||||
<Form.Control
|
||||
as="select"
|
||||
placeholder='Select infrastructure component'
|
||||
value={this.state.icID}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
>
|
||||
{ICOptions}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
|
||||
<Multiselect
|
||||
options={configFileOptions}
|
||||
|
@ -175,14 +175,14 @@ class EditConfigDialog extends React.Component {
|
|||
placeholder={'Select file(s)...'}
|
||||
/>
|
||||
|
||||
<FormGroup controlId='startParameters'>
|
||||
<FormLabel> Start Parameters </FormLabel>
|
||||
<Form.Group controlId='startParameters'>
|
||||
<Form.Label> Start Parameters </Form.Label>
|
||||
<ParametersEditor
|
||||
content={this.state.startParameters}
|
||||
onChange={(data) => this.handleParameterChange(data)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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} >
|
||||
<form>
|
||||
<FormGroup controlId='file'>
|
||||
<FormLabel>Component Configuration File</FormLabel>
|
||||
<FormControl type='file' onChange={this.loadFile} />
|
||||
</FormGroup>
|
||||
<Form>
|
||||
<Form.Group controlId='file'>
|
||||
<Form.Label>Component Configuration File</Form.Label>
|
||||
<Form.Control type='file' onChange={this.loadFile} />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup controlId="name" >
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId="name" >
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control
|
||||
readOnly={!this.imported}
|
||||
isValid={this.validateForm('name')}
|
||||
type="text"
|
||||
|
@ -118,9 +118,9 @@ class ImportConfigDialog extends React.Component {
|
|||
value={this.state.name}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
/>
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
|
||||
<EditSignalMapping
|
||||
<EditSignalMappingDialog
|
||||
show={this.state.editOutputSignalsModal}
|
||||
onCloseEdit={(direction) => this.closeEditSignalsModal(direction)}
|
||||
direction="Output"
|
||||
|
@ -578,7 +578,7 @@ class Dashboard extends Component {
|
|||
configs={this.state.configs}
|
||||
sessionToken={this.state.sessionToken}
|
||||
/>
|
||||
<EditSignalMapping
|
||||
<EditSignalMappingDialog
|
||||
show={this.state.editInputSignalsModal}
|
||||
onCloseEdit={(direction) => this.closeEditSignalsModal(direction)}
|
||||
direction="Input"
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="Edit Dashboard" buttonTitle="Save" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup controlId="name" valid={this.validateForm('name')}>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="Edit Dashboard"
|
||||
buttonTitle="Save"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={this.valid}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group controlId="name" valid={this.validateForm('name')}>
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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}>
|
||||
<form>
|
||||
<FormGroup controlId="file">
|
||||
<FormLabel>Dashboard File</FormLabel>
|
||||
<FormControl type="file" onChange={(e) => this.loadFile(e.target.files)} />
|
||||
</FormGroup>
|
||||
<Form>
|
||||
<Form.Group controlId="file">
|
||||
<Form.Label>Dashboard File</Form.Label>
|
||||
<Form.Control type="file" onChange={(e) => this.loadFile(e.target.files)} />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup controlId="name" >
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId="name" >
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control
|
||||
readOnly={!this.imported}
|
||||
isValid={this.validateForm('name')}
|
||||
type="text"
|
||||
|
@ -116,9 +116,9 @@ class ImportDashboardDialog extends React.Component {
|
|||
value={this.state.name}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
/>
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="New Dashboard" buttonTitle="Add" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup controlId="name" valid={this.validateForm('name')}>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="New Dashboard"
|
||||
buttonTitle="Add"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={this.valid}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group controlId="name" valid={this.validateForm('name')}>
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 <Dialog show={this.props.show} title='Edit File Content' buttonTitle='Close' onClose={() => this.onClose()} blendOutCancel = {true} valid={true}>
|
||||
<FormGroup as={Col} >
|
||||
<FormControl
|
||||
return <Dialog
|
||||
show={this.props.show}
|
||||
title='Edit File Content'
|
||||
buttonTitle='Close'
|
||||
onClose={() => this.onClose()}
|
||||
blendOutCancel = {true}
|
||||
valid={true}
|
||||
>
|
||||
<Form.Group as={Col} >
|
||||
<Form.Control
|
||||
disabled={false}
|
||||
type='file'
|
||||
onChange={(event) => this.selectUploadFile(event)} />
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<Form.Group as={Col} >
|
||||
<Button
|
||||
disabled={this.state.uploadFile === null}
|
||||
onClick={() => this.startEditContent()}>
|
||||
Upload
|
||||
</Button>
|
||||
</FormGroup>
|
||||
|
||||
</Form.Group>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="Edit Files of scenario" buttonTitle="Close" onClose={() => this.onClose()} blendOutCancel = {true} valid={true} size = 'lg'>
|
||||
<div>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="Edit Files of Scenario"
|
||||
buttonTitle="Close"
|
||||
onClose={() => this.onClose()}
|
||||
blendOutCancel = {true}
|
||||
valid={true}
|
||||
>
|
||||
<Table data={this.props.files}>
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKey='name'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Size (bytes)'
|
||||
dataKey='size'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Type'
|
||||
dataKey='type'
|
||||
/>
|
||||
<TableColumn
|
||||
title=''
|
||||
align='right'
|
||||
deleteButton
|
||||
onDelete={(index) => this.deleteFile(index)}
|
||||
editButton
|
||||
onEdit={index => this.setState({ editModal: true, modalFile: this.props.files[index] })}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<Table data={this.props.files}>
|
||||
<TableColumn title='ID' dataKey='id'/>
|
||||
<TableColumn title='Name' dataKey='name'/>
|
||||
<TableColumn title='Size (bytes)' dataKey='size'/>
|
||||
<TableColumn title='Type' dataKey='type'/>
|
||||
<TableColumn
|
||||
title=''
|
||||
deleteButton
|
||||
onDelete={(index) => this.deleteFile(index)}
|
||||
editButton
|
||||
onEdit={index => this.setState({ editModal: true, modalFile: this.props.files[index] })}
|
||||
/>
|
||||
</Table>
|
||||
<Form.Group as={Col} >
|
||||
<Form.Control
|
||||
disabled={this.props.disabled}
|
||||
type='file'
|
||||
onChange={(event) => this.selectUploadFile(event)}
|
||||
/>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<FormControl
|
||||
disabled={this.props.disabled}
|
||||
type='file'
|
||||
onChange={(event) => this.selectUploadFile(event)} />
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<Form.Group as={Col} >
|
||||
<span className='solid-button'>
|
||||
<Button
|
||||
variant='secondary'
|
||||
|
@ -157,25 +159,27 @@ class EditFilesDialog extends React.Component {
|
|||
Upload
|
||||
</Button>
|
||||
</span>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<ProgressBar
|
||||
striped={true}
|
||||
animated={true}
|
||||
now={this.state.uploadProgress}
|
||||
label={this.state.uploadProgress + '%'}
|
||||
style={progressBarStyle}
|
||||
/>
|
||||
</FormGroup>
|
||||
<div style={{ clear: 'both' }} />
|
||||
<Form.Group as={Col} >
|
||||
<ProgressBar
|
||||
striped={true}
|
||||
animated={true}
|
||||
now={this.state.uploadProgress}
|
||||
label={this.state.uploadProgress + '%'}
|
||||
style={progressBarStyle}
|
||||
/>
|
||||
</Form.Group>
|
||||
|
||||
<EditFileContent show={this.state.editModal} onClose={(data) => this.closeEditModal(data)} sessionToken={this.props.sessionToken} file={this.state.modalFile} />
|
||||
<div style={{ clear: 'both' }} />
|
||||
|
||||
</div>
|
||||
<EditFileContent
|
||||
show={this.state.editModal}
|
||||
onClose={(data) => this.closeEditModal(data)}
|
||||
sessionToken={this.props.sessionToken}
|
||||
file={this.state.modalFile}
|
||||
/>
|
||||
</Dialog>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <div>
|
||||
<FormGroup>
|
||||
<FormLabel sm={3} md={2}>
|
||||
<Form.Group>
|
||||
<Form.Label sm={3} md={2}>
|
||||
{this.props.name}
|
||||
</FormLabel>
|
||||
</For.m.Label>
|
||||
|
||||
<FormGroup as={Col} sm={9} md={10}>
|
||||
<FormControl
|
||||
<Form.Group as={Col} sm={9} md={10}>
|
||||
<Form.Control
|
||||
as="select"
|
||||
value={this.props.value}
|
||||
disabled={this.props.disabled}
|
||||
placeholder='Select file'
|
||||
onChange={(event) => this.props.onChange(event)}>
|
||||
{fileOptions}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
</FormGroup>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<FormControl
|
||||
<Form.Group as={Col} >
|
||||
<Form.Control
|
||||
disabled={this.props.disabled}
|
||||
type='file'
|
||||
onChange={(event) => this.selectUploadFile(event)} />
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<Form.Group as={Col} >
|
||||
<Button
|
||||
disabled={this.state.uploadFile === null}
|
||||
onClick={() => this.startFileUpload()}>
|
||||
Upload
|
||||
</Button>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<Form.Group as={Col} >
|
||||
<ProgressBar
|
||||
striped={true}
|
||||
animated={true}
|
||||
|
@ -128,7 +128,7 @@ class SelectFile extends React.Component {
|
|||
label={this.state.uploadProgress + '%'}
|
||||
style={progressBarStyle}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
>
|
||||
<form>
|
||||
<FormLabel column={false}>UUID: {this.props.ic.uuid}</FormLabel>
|
||||
<FormGroup controlId="name">
|
||||
<FormLabel column={false}>Name</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.ic.name} value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="category">
|
||||
<FormLabel column={false}>Category</FormLabel>
|
||||
<FormControl as="select" value={this.state.category} onChange={(e) => this.handleChange(e)}>
|
||||
<Form>
|
||||
<Form.Label column={false}>UUID: {this.props.ic.uuid}</Form.Label>
|
||||
<Form.Group controlId="name">
|
||||
<Form.Label column={false}>Name</Form.Label>
|
||||
<Form.Control type="text" placeholder={this.props.ic.name} value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="category">
|
||||
<Form.Label column={false}>Category</Form.Label>
|
||||
<Form.Control as="select" value={this.state.category} onChange={(e) => this.handleChange(e)}>
|
||||
<option>simulator</option>
|
||||
<option>service</option>
|
||||
<option>gateway</option>
|
||||
<option>equipment</option>
|
||||
<option>manager</option>
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
<FormGroup controlId="type">
|
||||
<FormLabel column={false}>Type</FormLabel>
|
||||
<FormControl as="select" value={this.state.type} onChange={(e) => this.handleChange(e)}>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="type">
|
||||
<Form.Label column={false}>Type</Form.Label>
|
||||
<Form.Control as="select" value={this.state.type} onChange={(e) => this.handleChange(e)}>
|
||||
<option default>Select type</option>
|
||||
{typeOptions.map((name,index) => (
|
||||
<option key={index}>{name}</option>
|
||||
))}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
<FormGroup controlId="websocketurl">
|
||||
<FormLabel column={false}>Websocket URL</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.ic.websocketurl} value={this.state.websocketurl} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="apiurl">
|
||||
<FormLabel column={false}>API URL</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.ic.apiurl} value={this.state.apiurl} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="location">
|
||||
<FormLabel column={false}>Location</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.ic.location} value={this.state.location || '' } onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="description">
|
||||
<FormLabel column={false}>Description</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.ic.description} value={this.state.description || '' } onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId='startParameterScheme'>
|
||||
<FormLabel column={false}>Start parameter scheme of IC</FormLabel>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="websocketurl">
|
||||
<Form.Label column={false}>Websocket URL</Form.Label>
|
||||
<Form.Control type="text" placeholder={this.props.ic.websocketurl} value={this.state.websocketurl} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="apiurl">
|
||||
<Form.Label column={false}>API URL</Form.Label>
|
||||
<Form.Control type="text" placeholder={this.props.ic.apiurl} value={this.state.apiurl} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="location">
|
||||
<Form.Label column={false}>Location</Form.Label>
|
||||
<Form.Control type="text" placeholder={this.props.ic.location} value={this.state.location || '' } onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="description">
|
||||
<Form.Label column={false}>Description</Form.Label>
|
||||
<Form.Control type="text" placeholder={this.props.ic.description} value={this.state.description || '' } onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId='startParameterSchema'>
|
||||
<Form.Label column={false}>Start parameter schema of IC</Form.Label>
|
||||
<ParametersEditor
|
||||
content={this.state.startParameterScheme}
|
||||
content={this.state.startParameterSchema}
|
||||
disabled={false}
|
||||
onChange={(data) => this.handleStartParameterSchemeChange(data)}
|
||||
onChange={(data) => this.handleStartParameterSchemaChange(data)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Form.Group>
|
||||
<Form.Group controlId='properties'>
|
||||
<Form.Label column={false}>Properties</Form.Label>
|
||||
<ParametersEditor
|
||||
content={this.state.properties}
|
||||
disabled={true}
|
||||
onChange={(data) => this.handlePropertiesChange(data)}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 {
|
|||
</Dropdown.Item>
|
||||
));
|
||||
|
||||
return <div className='solid-button'>
|
||||
<InputGroup>
|
||||
<InputGroup.Prepend>
|
||||
<DropdownButton
|
||||
variant="secondary"
|
||||
title={this.state.selectedAction != null ? this.state.selectedAction.title : ''}
|
||||
id="action-dropdown"
|
||||
onSelect={this.setAction}>
|
||||
{actionList}
|
||||
</DropdownButton>
|
||||
<FormControl
|
||||
type="datetime-local"
|
||||
variant="outline-secondary"
|
||||
value={time}
|
||||
onChange={this.setTimeForAction} />
|
||||
</InputGroup.Prepend>
|
||||
<Button
|
||||
variant="secondary"
|
||||
disabled={sendCommandDisabled}
|
||||
onClick={() => this.runAction(this.state.selectedAction, this.state.time)}>Run</Button>
|
||||
</InputGroup>
|
||||
<small className="text-muted">Select time for synced command execution</small>
|
||||
</div>;
|
||||
return <div>
|
||||
<Form inline>
|
||||
<Form.Control
|
||||
type="datetime-local"
|
||||
value={time}
|
||||
onChange={this.setTimeForAction}
|
||||
/>
|
||||
<SplitButton
|
||||
style={splitButtonStyle}
|
||||
title={this.state.selectedAction != null ? this.state.selectedAction.title : ''}
|
||||
id="action-dropdown"
|
||||
onSelect={this.setAction}
|
||||
disabled={disabled}
|
||||
onClick={() => this.runAction(this.state.selectedAction, this.state.time)}>
|
||||
{actionList}
|
||||
</SplitButton>
|
||||
</Form>
|
||||
<small className="text-muted">Select time for synced command execution</small>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -70,11 +70,10 @@ class ICDialog extends React.Component {
|
|||
graphURL = this.props.ic.apiurl + "/graph.svg"
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title={this.props.ic.name + " ( " + this.props.ic.uuid + " )"}
|
||||
title={this.props.ic.name}
|
||||
buttonTitle="Close"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
valid={true}
|
||||
|
@ -84,27 +83,62 @@ class ICDialog extends React.Component {
|
|||
<form>
|
||||
<Row>
|
||||
<Col>
|
||||
<h5>State: {this.props.ic.state}</h5>
|
||||
<h5>Category: {this.props.ic.category}</h5>
|
||||
<h5>Type: {this.props.ic.type}</h5>
|
||||
<h5>Uptime: {this.props.ic.uptime}</h5>
|
||||
<h5>Location: {this.props.ic.location}</h5>
|
||||
<h5>Description: {this.props.ic.description}</h5>
|
||||
<h5>Websocket URL: {this.props.ic.websocketurl}</h5>
|
||||
<h5>API URL: {this.props.ic.apiurl}</h5>
|
||||
<h5>Start parameter scheme:</h5>
|
||||
<ReactJson
|
||||
src={this.props.ic.startParameterScheme}
|
||||
name={false}
|
||||
displayDataTypes={false}
|
||||
displayObjectSize={false}
|
||||
enableClipboard={false}
|
||||
collapsed={0}
|
||||
/>
|
||||
<Row>
|
||||
<Col><b>Name</b></Col>
|
||||
<Col>{this.props.ic.name}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>UUID</b></Col>
|
||||
<Col>{this.props.ic.uuid}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>State</b></Col>
|
||||
<Col>{this.props.ic.state}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Category</b></Col>
|
||||
<Col>{this.props.ic.category}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Type</b></Col>
|
||||
<Col>{this.props.ic.type}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Uptime</b></Col>
|
||||
<Col>{moment.duration(this.props.ic.uptime, "seconds").humanize()}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Location</b></Col>
|
||||
<Col>{this.props.ic.location}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Description</b></Col>
|
||||
<Col>{this.props.ic.description}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Websocket URL</b></Col>
|
||||
<Col>{this.props.ic.websocketurl}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>API URL</b></Col>
|
||||
<Col>{this.props.ic.apiurl}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col><b>Start parameter schema</b></Col>
|
||||
<Col>
|
||||
<ReactJson
|
||||
src={this.props.ic.startParameterSchema}
|
||||
name={false}
|
||||
displayDataTypes={false}
|
||||
displayObjectSize={false}
|
||||
enableClipboard={false}
|
||||
collapsed={0}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
<Col>
|
||||
|
||||
<h5>Raw Status:</h5>
|
||||
{this.isJSON(this.props.ic.statusupdateraw) ?
|
||||
<ReactJson
|
||||
|
@ -120,7 +154,7 @@ class ICDialog extends React.Component {
|
|||
}
|
||||
|
||||
|
||||
{this.props.ic.type === "villas-node" || this.props.ic.type === "villas-relay" ? (
|
||||
{this.props.ic.type === "villas-node" ?
|
||||
<>
|
||||
<div className='section-buttons-group-right'>
|
||||
<Button style={{margin: '5px'}} size='sm' onClick={() => this.downloadGraph(graphURL)}><Icon
|
||||
|
@ -131,29 +165,29 @@ class ICDialog extends React.Component {
|
|||
<img alt={"Graph image download failed and/or incorrect image API URL"} src={graphURL}/>
|
||||
</div>
|
||||
|
||||
{this.props.userRole === "Admin" ? (
|
||||
<div>
|
||||
<h5>Controls:</h5>
|
||||
<div className='solid-button'>
|
||||
<Button variant='secondary' style={{margin: '5px'}} size='lg'
|
||||
onClick={() => this.setState({confirmCommand: true, command: 'restart'})}>Restart</Button>
|
||||
<Button variant='secondary' style={{margin: '5px'}} size='lg' onClick={() => this.setState({
|
||||
confirmCommand: true,
|
||||
command: 'shutdown'
|
||||
})}>Shutdown</Button>
|
||||
</div>
|
||||
</div>)
|
||||
: (<div/>)}
|
||||
|
||||
{this.props.user.role === "Admin" ?
|
||||
<div>
|
||||
<h5>Controls:</h5>
|
||||
<div className='solid-button'>
|
||||
<Button variant='secondary' style={{margin: '5px'}} size='lg'
|
||||
onClick={() => this.setState({confirmCommand: true, command: 'restart'})}>Restart</Button>
|
||||
<Button variant='secondary' style={{margin: '5px'}} size='lg' onClick={() => this.setState({
|
||||
confirmCommand: true,
|
||||
command: 'shutdown'
|
||||
})}>Shutdown</Button>
|
||||
</div>
|
||||
</div>
|
||||
: <div/>
|
||||
}
|
||||
<ConfirmCommand show={this.state.confirmCommand} command={this.state.command} name={this.props.ic.name}
|
||||
onClose={c => this.closeConfirmModal(c)}/>
|
||||
|
||||
</>) : (<div/>)}
|
||||
</>
|
||||
: <div/>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
</Dialog>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
100
src/ic/ics.js
100
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" ?
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
: <></>
|
||||
}
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKeys={['name']}
|
||||
|
@ -438,6 +445,7 @@ class InfrastructureComponents extends Component {
|
|||
{this.state.currentUser.role === "Admin" ?
|
||||
<TableColumn
|
||||
width='150'
|
||||
align='right'
|
||||
editButton
|
||||
showEditButton ={(index) => this.isLocalIC(index, ics)}
|
||||
exportButton
|
||||
|
@ -481,26 +489,23 @@ class InfrastructureComponents extends Component {
|
|||
|
||||
return (
|
||||
<div className='section'>
|
||||
<h1>Infrastructure Components
|
||||
<h1>Infrastructure
|
||||
{this.state.currentUser.role === "Admin" ?
|
||||
(<span className='icon-button'>
|
||||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}> Add Infrastructure Component </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({newModal: true})} style={buttonStyle}><Icon icon="plus" classname='icon-color' style={iconStyle}
|
||||
/></Button>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
key={2}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"import"}`}> Import Infrastructure Component </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({importModal: true})} style={buttonStyle}><Icon icon="upload" classname='icon-color' style={iconStyle}
|
||||
/></Button>
|
||||
</OverlayTrigger>
|
||||
</span>)
|
||||
:
|
||||
(<span> </span>)
|
||||
<span className='icon-button'>
|
||||
<IconButton
|
||||
alt={1}
|
||||
tooltip='Add Infrastructure Component'
|
||||
onClick={() => this.setState({newModal: true})}
|
||||
icon='plus'
|
||||
/>
|
||||
<IconButton
|
||||
alt={1}
|
||||
tooltip='Import Infrastructure Component'
|
||||
onClick={() => this.setState({importModal: true})}
|
||||
icon='upload'
|
||||
/>
|
||||
</span>
|
||||
: <span/>
|
||||
}
|
||||
</h1>
|
||||
|
||||
|
@ -513,20 +518,18 @@ class InfrastructureComponents extends Component {
|
|||
{this.state.currentUser.role === "Admin" && this.state.numberOfExternalICs > 0 ?
|
||||
<div style={{float: 'left'}}>
|
||||
<ICAction
|
||||
hasConfigs = {false}
|
||||
ics={this.state.ics}
|
||||
selectedICs={this.state.selectedICs}
|
||||
token={this.state.sessionToken}
|
||||
actions={[
|
||||
{id: '-1', title: 'Action', data: {action: 'none'}},
|
||||
{id: '0', title: 'Reset', data: {action: 'reset'}},
|
||||
{id: '1', title: 'Shutdown', data: {action: 'shutdown'}},
|
||||
{id: '2', title: 'Delete', data: {action: 'delete'}}
|
||||
{id: '2', title: 'Delete', data: {action: 'delete'}},
|
||||
{id: '3', title: 'Recreate', data: {action: 'create'}},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
:
|
||||
<div/>
|
||||
: <div/>
|
||||
}
|
||||
|
||||
<div style={{ clear: 'both' }} />
|
||||
|
@ -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)}/>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="Import Infrastructure Component" buttonTitle="Add" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup controlId="file">
|
||||
<FormLabel>Infrastructure Component File</FormLabel>
|
||||
<FormControl type="file" onChange={(e) => this.loadFile(e.target.files)} />
|
||||
</FormGroup>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="Import Infrastructure Component"
|
||||
buttonTitle="Add"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={this.valid}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group controlId="file">
|
||||
<Form.Label>Infrastructure Component File</Form.Label>
|
||||
<Form.Control type="file" onChange={(e) => this.loadFile(e.target.files)} />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup controlId="name" valid={this.validateForm('name')}>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="websocketurl">
|
||||
<FormLabel>Websocket URL</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter websocketurl" value={this.state.websocketurl} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="uuid" valid={this.validateForm('uuid')}>
|
||||
<FormLabel>UUID</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter uuid" value={this.state.uuid} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Form.Group controlId="name" valid={this.validateForm('name')}>
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="websocketurl">
|
||||
<Form.Label>Websocket URL</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter websocketurl" value={this.state.websocketurl} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="uuid" valid={this.validateForm('uuid')}>
|
||||
<Form.Label>UUID</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter uuid" value={this.state.uuid} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
198
src/ic/new-ic.js
198
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 (
|
||||
<Dialog show={this.props.show} title="New Infrastructure Component" buttonTitle="Add" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.validateForm()}>
|
||||
<form>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="New Infrastructure Component"
|
||||
buttonTitle="Add"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={this.validateForm()}
|
||||
>
|
||||
<Form>
|
||||
{this.props.managers.length > 0 ?
|
||||
<>
|
||||
<FormGroup controlId="managedexternally">
|
||||
<Form.Group controlId="managedexternally">
|
||||
<OverlayTrigger key="-1" placement={'left'} overlay={<Tooltip id={`tooltip-${"me"}`}>An externally managed component is created and managed by an IC manager via AMQP</Tooltip>} >
|
||||
<FormCheck type={"checkbox"} label={"Managed externally"} defaultChecked={this.state.managedexternally} onChange={e => this.handleChange(e)}>
|
||||
</FormCheck>
|
||||
<Form.Check type={"checkbox"} label={"Managed externally"} defaultChecked={this.state.managedexternally} onChange={e => this.handleChange(e)}>
|
||||
</Form.Check>
|
||||
</OverlayTrigger>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
{this.state.managedexternally === true ?
|
||||
<FormGroup controlId="manager" valid={this.validateForm('manager')}>
|
||||
<Form.Group controlId="manager" valid={this.validateForm('manager')}>
|
||||
<OverlayTrigger key="0" placement={'right'} overlay={<Tooltip id={`tooltip-${"required"}`}> Required field </Tooltip>} >
|
||||
<FormLabel>Manager to create new IC *</FormLabel>
|
||||
<Form.Label>Manager to create new IC *</Form.Label>
|
||||
</OverlayTrigger>
|
||||
<FormControl as="select" value={this.state.manager} onChange={(e) => this.handleChange(e)}>
|
||||
<Form.Control as="select" value={this.state.manager} onChange={(e) => this.handleChange(e)}>
|
||||
{managerOptions}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
: <div/>
|
||||
|
||||
}
|
||||
</>
|
||||
: <div/>
|
||||
}
|
||||
<FormGroup controlId="name" valid={this.validateForm('name')}>
|
||||
<OverlayTrigger key="1" placement={'right'} overlay={<Tooltip id={`tooltip-${"required"}`}> Required field </Tooltip>} >
|
||||
<FormLabel>Name *</FormLabel>
|
||||
</OverlayTrigger>
|
||||
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="category" valid={this.validateForm('category')}>
|
||||
<Form.Group controlId="name" valid={this.validateForm('name')}>
|
||||
<OverlayTrigger key="1" placement={'right'} overlay={<Tooltip id={`tooltip-${"required"}`}> Required field </Tooltip>} >
|
||||
<Form.Label>Name *</Form.Label>
|
||||
</OverlayTrigger>
|
||||
<Form.Control type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
{this.state.managedexternally === false ?
|
||||
<Form.Group controlId="uuid" valid={this.validateForm('uuid')}>
|
||||
<Form.Label>UUID</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter uuid" value={this.state.uuid}
|
||||
onChange={(e) => this.handleChange(e)}/>
|
||||
<Form.Control.Feedback/>
|
||||
</Form.Group>
|
||||
: <div/>
|
||||
}
|
||||
<Form.Group controlId="location">
|
||||
<Form.Label>Location</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter Location" value={this.state.location} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="description">
|
||||
<Form.Label>Description</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter Description" value={this.state.description} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="category" valid={this.validateForm('category')}>
|
||||
<OverlayTrigger key="2" placement={'right'} overlay={<Tooltip id={`tooltip-${"required"}`}> Required field </Tooltip>} >
|
||||
<FormLabel>Category of component *</FormLabel>
|
||||
<Form.Label>Category of component *</Form.Label>
|
||||
</OverlayTrigger>
|
||||
<FormControl as="select" value={this.state.category} onChange={(e) => this.handleChange(e)}>
|
||||
<Form.Control as="select" value={this.state.category} onChange={(e) => this.handleChange(e)}>
|
||||
<option default>Select category</option>
|
||||
<option>simulator</option>
|
||||
<option>service</option>
|
||||
<option>gateway</option>
|
||||
<option>equipment</option>
|
||||
<option>manager</option>
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
<FormGroup controlId="type" valid={this.validateForm('type')}>
|
||||
<option value="simulator">Simulator</option>
|
||||
<option value="service">Service</option>
|
||||
<option value="gateway">Gateway</option>
|
||||
<option value="equipment">Equipment</option>
|
||||
<option value="manager">Manager</option>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="type" valid={this.validateForm('type')}>
|
||||
<OverlayTrigger key="3" placement={'right'} overlay={<Tooltip id={`tooltip-${"required"}`}> Required field </Tooltip>} >
|
||||
<FormLabel>Type of component *</FormLabel>
|
||||
<Form.Label>Type of component *</Form.Label>
|
||||
</OverlayTrigger>
|
||||
<FormControl as="select" value={this.state.type} onChange={(e) => this.handleChange(e)}>
|
||||
<Form.Control as="select" value={this.state.type} onChange={(e) => this.handleChange(e)}>
|
||||
<option default>Select type</option>
|
||||
{typeOptions.map((name,index) => (
|
||||
<option key={index}>{name}</option>
|
||||
))}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
<FormGroup controlId="websocketurl">
|
||||
<FormLabel>Websocket URL</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter Websocket URL" value={this.state.websocketurl} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="apiurl">
|
||||
<FormLabel>API URL</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter API URL" value={this.state.apiurl} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="location">
|
||||
<FormLabel>Location</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter Location" value={this.state.location} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup controlId="description">
|
||||
<FormLabel>Description</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter Description" value={this.state.description} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
{this.state.managedexternally === false ?
|
||||
<FormGroup controlId="uuid" valid={this.validateForm('uuid')}>
|
||||
<FormLabel>UUID</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter uuid" value={this.state.uuid}
|
||||
onChange={(e) => this.handleChange(e)}/>
|
||||
<FormControl.Feedback/>
|
||||
</FormGroup>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="websocketurl">
|
||||
<Form.Label>Websocket URL</Form.Label>
|
||||
<Form.Control type="text" placeholder="https://" value={this.state.websocketurl} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group controlId="apiurl">
|
||||
<Form.Label>API URL</Form.Label>
|
||||
<Form.Control type="text" placeholder="https://" value={this.state.apiurl} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
{this.state.managedexternally === true ?
|
||||
<Form.Group controlId='properties'>
|
||||
<Form.Label> Properties </Form.Label>
|
||||
<ParametersEditor
|
||||
content={this.state.properties}
|
||||
onChange={(data) => this.handlePropertiesChange(data)}
|
||||
/>
|
||||
</Form.Group>
|
||||
: <div/>
|
||||
}
|
||||
</form>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 <Dialog show={this.props.show}
|
||||
return <Dialog
|
||||
show={this.props.show}
|
||||
title={'Edit Result No. ' + this.state.id}
|
||||
buttonTitle='Close'
|
||||
onClose={() => this.onClose()}
|
||||
blendOutCancel={true}
|
||||
valid={true}
|
||||
size='lg'>
|
||||
>
|
||||
<Form.Group as={Col} controlId='description'>
|
||||
<Row style={{ float: 'center' }} >
|
||||
<Col xs lg="2">
|
||||
<Form.Label>Description</Form.Label>
|
||||
</Col>
|
||||
<Col xs lg="4">
|
||||
<Form.Control
|
||||
type='text'
|
||||
placeholder={this.state.description}
|
||||
value={this.state.description}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<Form.Control.Feedback />
|
||||
</Col>
|
||||
<Col xs lg="2">
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={() => this.submitDescription()}>
|
||||
Save
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form.Group>
|
||||
|
||||
<Table data={this.state.files}>
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKey='name'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Size (bytes)'
|
||||
dataKey='size'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Type'
|
||||
dataKey='type'
|
||||
/>
|
||||
<TableColumn
|
||||
title=''
|
||||
deleteButton
|
||||
onDelete={(index) => this.deleteFile(index)}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<div>
|
||||
<FormGroup as={Col} controlId='description'>
|
||||
<Row style={{ float: 'center' }} >
|
||||
<Col xs lg="2">
|
||||
<FormLabel>Description</FormLabel>
|
||||
</Col>
|
||||
<Col xs lg="4">
|
||||
<FormControl type='text' placeholder={this.state.description} value={this.state.description} onChange={this.handleChange} />
|
||||
<FormControl.Feedback />
|
||||
</Col>
|
||||
<Col xs lg="2">
|
||||
<Button
|
||||
type="submit"
|
||||
onClick={() => this.submitDescription()}>
|
||||
Save
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormGroup>
|
||||
|
||||
<Table data={this.state.files}>
|
||||
<TableColumn title='ID' dataKey='id' />
|
||||
<TableColumn title='Name' dataKey='name' />
|
||||
<TableColumn title='Size (bytes)' dataKey='size' />
|
||||
<TableColumn title='Type' dataKey='type' />
|
||||
<TableColumn
|
||||
title=''
|
||||
deleteButton
|
||||
onDelete={(index) => this.deleteFile(index)}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<div style={{ float: 'center' }}>
|
||||
<h5>Add result file</h5>
|
||||
<Row>
|
||||
<Col xs lg="4">
|
||||
<FormControl type='file' onChange={(event) => this.selectUploadFile(event)} />
|
||||
</Col>
|
||||
<Col xs lg="2">
|
||||
<Button
|
||||
disabled={this.state.uploadFile === null}
|
||||
onClick={() => this.startFileUpload()}>
|
||||
Upload
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<br></br>
|
||||
|
||||
<FormGroup as={Col} >
|
||||
<ProgressBar
|
||||
striped={true}
|
||||
animated={true}
|
||||
now={this.state.uploadProgress}
|
||||
label={this.state.uploadProgress + '%'}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<div style={{ float: 'center' }}>
|
||||
<h5>Add result file</h5>
|
||||
<Row>
|
||||
<Col xs lg="4">
|
||||
<Form.Control type='file' onChange={(event) => this.selectUploadFile(event)} />
|
||||
</Col>
|
||||
<Col xs lg="2">
|
||||
<Button
|
||||
disabled={this.state.uploadFile === null}
|
||||
onClick={() => this.startFileUpload()}>
|
||||
Upload
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<Form.Group as={Col} >
|
||||
<ProgressBar
|
||||
striped={true}
|
||||
animated={true}
|
||||
now={this.state.uploadProgress}
|
||||
label={this.state.uploadProgress + '%'}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
||||
export default EditResultDialog;
|
||||
export default EditResultDialog;
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="New Result" buttonTitle="Add" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={true}>
|
||||
<form>
|
||||
<FormGroup controlId="Description">
|
||||
<FormLabel>Description</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter description" value={this.state.Description} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="New Result"
|
||||
buttonTitle="Add"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={true}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group controlId="Description">
|
||||
<Form.Label>Description</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter description" value={this.state.Description} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
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}
|
||||
>
|
||||
<form>
|
||||
<ReactJson
|
||||
src={this.props.configs}
|
||||
name={false}
|
||||
displayDataTypes={false}
|
||||
displayObjectSize={false}
|
||||
enableClipboard={false}
|
||||
collapsed={false}
|
||||
/>
|
||||
</form>
|
||||
<Form>
|
||||
<ReactJson
|
||||
src={this.props.configs}
|
||||
name={false}
|
||||
displayDataTypes={false}
|
||||
displayObjectSize={false}
|
||||
enableClipboard={false}
|
||||
collapsed={false}
|
||||
/>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 <Dialog show={this.props.show} title='Edit Scenario' buttonTitle='Save' onClose={this.onClose} onReset={this.resetState} valid={true}>
|
||||
<form>
|
||||
<FormGroup as={Col} controlId='name'>
|
||||
<FormLabel column={false}>Name</FormLabel>
|
||||
<FormControl type='text' placeholder='Enter name' value={this.state.name} onChange={this.handleChange} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup as={Col} controlId='startParameters'>
|
||||
<FormLabel column={false}>Start Parameters</FormLabel>
|
||||
return <Dialog
|
||||
show={this.props.show}
|
||||
title='Edit Scenario'
|
||||
buttonTitle='Save'
|
||||
onClose={this.onClose}
|
||||
onReset={this.resetState}
|
||||
valid={true}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group as={Col} controlId='name'>
|
||||
<Form.Label column={false}>Name</Form.Label>
|
||||
<Form.Control type='text' placeholder='Enter name' value={this.state.name} onChange={this.handleChange} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group as={Col} controlId='startParameters'>
|
||||
<Form.Label column={false}>Start Parameters</Form.Label>
|
||||
<ParametersEditor content={this.state.startParameters} onChange={this.handleStartParametersChange} />
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <Dialog show={this.props.show} title="Import Scenario" buttonTitle="Import" onClose={this.onClose} onReset={this.resetState} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup as={Col} controlId="file">
|
||||
<FormLabel>Scenario File</FormLabel>
|
||||
<FormControl type="file" onChange={this.loadFile} />
|
||||
</FormGroup>
|
||||
return <Dialog
|
||||
show={this.props.show}
|
||||
title="Import Scenario"
|
||||
buttonTitle="Import"
|
||||
onClose={this.onClose}
|
||||
onReset={this.resetState}
|
||||
valid={this.valid}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group as={Col} controlId="file">
|
||||
<Form.Label>Scenario File</Form.Label>
|
||||
<Form.Control type="file" onChange={this.loadFile} />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col} controlId="name">
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl readOnly={this.imported === false} type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<Form.Group as={Col} controlId="name">
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control readOnly={this.imported === false} type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col}>
|
||||
<FormLabel>Start Parameters</FormLabel>
|
||||
<Form.Group as={Col}>
|
||||
<Form.Label>Start Parameters</Form.Label>
|
||||
|
||||
<ParametersEditor content={this.state.startParameters} onChange={this.handleStartParametersChange} disabled={this.imported === false} />
|
||||
</FormGroup>
|
||||
|
||||
</form>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <Dialog show={this.props.show} title="New Scenario" buttonTitle="Add" onClose={this.onClose} onReset={this.resetState} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup as={Col} controlId="name">
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter name" value={this.state.name} onChange={this.handleChange} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
return <Dialog
|
||||
show={this.props.show}
|
||||
title="New Scenario"
|
||||
buttonTitle="Add"
|
||||
onClose={this.onClose}
|
||||
onReset={this.resetState}
|
||||
valid={this.valid}>
|
||||
<Form>
|
||||
<Form.Group as={Col} controlId="name">
|
||||
<Form.Label>Name</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter name" value={this.state.name} onChange={this.handleChange} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup as={Col}>
|
||||
<FormLabel>Start Parameters</FormLabel>
|
||||
<Form.Group as={Col}>
|
||||
<Form.Label>Start Parameters</Form.Label>
|
||||
|
||||
<ParametersEditor content={this.state.startParameters} onChange={this.handleStartParametersChange} />
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <h1>Loading Scenario...</h1>;
|
||||
}
|
||||
|
||||
let resulttable;
|
||||
if (this.state.results && this.state.results.length > 0) {
|
||||
resulttable = <div>
|
||||
<Table data={this.state.results}>
|
||||
<TableColumn
|
||||
title='Result No.'
|
||||
dataKey='id'
|
||||
modifier={(id, result) => this.modifyResultNoColumn(id, result)}
|
||||
/>
|
||||
<TableColumn title='Description' dataKey='description' />
|
||||
<TableColumn title='Created at' dataKey='createdAt' />
|
||||
<TableColumn title='Last update' dataKey='updatedAt' />
|
||||
<TableColumn
|
||||
title='Files/Data'
|
||||
dataKey='resultFileIDs'
|
||||
linkKey='filebuttons'
|
||||
data={this.state.files}
|
||||
width='300'
|
||||
onDownload={(index) => this.downloadResultData(index)}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Options'
|
||||
width='300'
|
||||
editButton
|
||||
downloadAllButton
|
||||
deleteButton
|
||||
onEdit={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 })}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<EditResultDialog
|
||||
sessionToken={this.state.sessionToken}
|
||||
show={this.state.editResultsModal}
|
||||
files={this.state.files}
|
||||
results={this.state.results}
|
||||
resultId={this.state.modalResultsIndex}
|
||||
scenarioID={this.state.scenario.id}
|
||||
onClose={this.closeEditResultsModal.bind(this)} />
|
||||
<DeleteDialog title="result" name={this.state.modalResultsData.id} show={this.state.deleteResultsModal} onClose={(e) => this.closeDeleteResultsModal(e)} />
|
||||
<ResultConfigDialog
|
||||
show={this.state.resultConfigsModal}
|
||||
configs={this.state.modalResultConfigs}
|
||||
resultNo={this.state.modalResultConfigsIndex}
|
||||
onClose={this.closeResultConfigSnapshots.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
return <div className='section'>
|
||||
<div className='section-buttons-group-right'>
|
||||
<OverlayTrigger key={0} placement={'bottom'} overlay={<Tooltip id={`tooltip-${"file"}`}> Add, edit or delete files of scenario </Tooltip>} >
|
||||
<Button variant='light' key={0} size="lg" onClick={this.onEditFiles.bind(this)}>
|
||||
<Icon icon="file" classname={'icon-color'} style={iconStyle}/>
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
<IconButton
|
||||
key="0"
|
||||
tooltip="Add, edit or delete files of scenario"
|
||||
onClick={this.onEditFiles.bind(this)}
|
||||
icon="file"
|
||||
/>
|
||||
</div>
|
||||
<h1>{this.state.scenario.name}</h1>
|
||||
|
||||
|
@ -810,34 +758,37 @@ class Scenario extends React.Component {
|
|||
{/*Component Configurations table*/}
|
||||
<h2 style={tableHeadingStyle}>Component Configurations
|
||||
<span className='icon-button'>
|
||||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}> Add Component Configuration </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.addConfig()} style={altButtonStyle}><Icon icon="plus" classname={'icon-color'} style={iconStyle} /></Button>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
key={2}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"import"}`}> Import Component Configuration </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({ importConfigModal: true })} style={altButtonStyle}><Icon icon="upload" classname={'icon-color'} style={iconStyle}/></Button>
|
||||
</OverlayTrigger>
|
||||
</span>
|
||||
<IconButton
|
||||
key={0}
|
||||
tooltip='Add Component Configuration'
|
||||
onClick={() => this.addConfig()}
|
||||
icon='plus'
|
||||
/>
|
||||
<IconButton
|
||||
key={1}
|
||||
tooltip='Import Component Configuration'
|
||||
onClick={() => this.setState({ importConfigModal: true })}
|
||||
icon='upload'
|
||||
/>
|
||||
</span>
|
||||
</h2>
|
||||
<Table data={this.state.configs}>
|
||||
<TableColumn
|
||||
checkbox
|
||||
checkboxDisabled={(index) => this.usesExternalIC(index)}
|
||||
checkboxDisabled={(index) => !this.usesExternalIC(index)}
|
||||
onChecked={(index, event) => this.onConfigChecked(index, event)}
|
||||
width='30' />
|
||||
<TableColumn title='Name' dataKey='name' />
|
||||
<TableColumn title='Configuration file(s)' dataKey='fileIDs' modifier={(fileIDs) => this.getListOfFiles(fileIDs, ['json', 'JSON'])} />
|
||||
width='30'
|
||||
/>
|
||||
{this.state.currentUser.role === "Admin" ?
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
: <></>
|
||||
}
|
||||
<TableColumn
|
||||
title='Model file(s)'
|
||||
dataKey='fileIDs'
|
||||
modifier={(fileIDs) => this.getListOfFiles(fileIDs, ['xml'])}
|
||||
editButton
|
||||
onEdit={(index) => this.startPintura(index)}
|
||||
title='Name'
|
||||
dataKey='name'
|
||||
/>
|
||||
<TableColumn
|
||||
title='# Output Signals'
|
||||
|
@ -852,14 +803,19 @@ class Scenario extends React.Component {
|
|||
onEdit={index => this.setState({ editInputSignalsModal: true, modalConfigData: this.state.configs[index], modalConfigIndex: index })}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Signal AutoConf'
|
||||
title='Import Signals'
|
||||
exportButton
|
||||
onExport={(index) => this.signalsAutoConf(index)}
|
||||
/>
|
||||
<TableColumn title='Infrastructure Component' dataKey='icID' modifier={(icID) => this.getICName(icID)} />
|
||||
<TableColumn
|
||||
title='Infrastructure Component'
|
||||
dataKey='icID'
|
||||
modifier={(icID) => this.getICName(icID)}
|
||||
/>
|
||||
<TableColumn
|
||||
title=''
|
||||
width='200'
|
||||
align='right'
|
||||
editButton
|
||||
deleteButton
|
||||
exportButton
|
||||
|
@ -871,27 +827,25 @@ class Scenario extends React.Component {
|
|||
/>
|
||||
</Table>
|
||||
|
||||
{this.state.ExternalICInUse ? (
|
||||
{this.state.ExternalICInUse ?
|
||||
<div style={{ float: 'left' }}>
|
||||
<ICAction
|
||||
hasConfigs={true}
|
||||
ics={this.state.ics}
|
||||
configs={this.state.configs}
|
||||
selectedConfigs = {this.state.selectedConfigs}
|
||||
snapshotConfig = {(index) => 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>
|
||||
) : (<div />)
|
||||
: <div />
|
||||
}
|
||||
|
||||
< div style={{ clear: 'both' }} />
|
||||
<div style={{ clear: 'both' }} />
|
||||
|
||||
<EditConfigDialog
|
||||
show={this.state.editConfigModal}
|
||||
|
@ -901,11 +855,18 @@ class Scenario extends React.Component {
|
|||
files={this.state.files}
|
||||
sessionToken={this.state.sessionToken}
|
||||
/>
|
||||
|
||||
<ImportConfigDialog show={this.state.importConfigModal} onClose={data => this.importConfig(data)} ics={this.state.ics} />
|
||||
<DeleteDialog title="component configuration" name={this.state.modalConfigData.name} show={this.state.deleteConfigModal} onClose={(c) => this.closeDeleteConfigModal(c)} />
|
||||
|
||||
<EditSignalMapping
|
||||
<ImportConfigDialog
|
||||
show={this.state.importConfigModal}
|
||||
onClose={data => this.importConfig(data)}
|
||||
ics={this.state.ics}
|
||||
/>
|
||||
<DeleteDialog
|
||||
title="component configuration"
|
||||
name={this.state.modalConfigData.name}
|
||||
show={this.state.deleteConfigModal}
|
||||
onClose={(c) => this.closeDeleteConfigModal(c)}
|
||||
/>
|
||||
<EditSignalMappingDialog
|
||||
show={this.state.editOutputSignalsModal}
|
||||
onCloseEdit={(direction) => this.closeEditSignalsModal(direction)}
|
||||
direction="Output"
|
||||
|
@ -913,7 +874,7 @@ class Scenario extends React.Component {
|
|||
configID={this.state.modalConfigData.id}
|
||||
sessionToken={this.state.sessionToken}
|
||||
/>
|
||||
<EditSignalMapping
|
||||
<EditSignalMappingDialog
|
||||
show={this.state.editInputSignalsModal}
|
||||
onCloseEdit={(direction) => this.closeEditSignalsModal(direction)}
|
||||
direction="Input"
|
||||
|
@ -925,26 +886,41 @@ class Scenario extends React.Component {
|
|||
{/*Dashboard table*/}
|
||||
<h2 style={tableHeadingStyle}>Dashboards
|
||||
<span className='icon-button'>
|
||||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}> Add Dashboard </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({ newDashboardModal: true })} style={altButtonStyle}><Icon icon="plus" classname={'icon-color'} style={iconStyle} /></Button>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
key={2}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"import"}`}> Import Dashboard </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({ importDashboardModal: true })} style={altButtonStyle}><Icon icon="upload" classname={'icon-color'} style={iconStyle} /></Button>
|
||||
</OverlayTrigger>
|
||||
</span>
|
||||
<IconButton
|
||||
key={0}
|
||||
tooltip='Add Dashboard'
|
||||
onClick={() => this.setState({ newDashboardModal: true })}
|
||||
icon='plus'
|
||||
/>
|
||||
<IconButton
|
||||
key={1}
|
||||
tooltip='Import Dashboard'
|
||||
onClick={() => this.setState({ importDashboardModal: true })}
|
||||
icon='upload'
|
||||
/>
|
||||
</span>
|
||||
</h2>
|
||||
<Table data={this.state.dashboards}>
|
||||
<TableColumn title='Name' dataKey='name' link='/dashboards/' linkKey='id' />
|
||||
<TableColumn title='Grid' dataKey='grid' />
|
||||
{this.state.currentUser.role === "Admin" ?
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
: <></>
|
||||
}
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKey='name'
|
||||
link='/dashboards/'
|
||||
linkKey='id'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Grid'
|
||||
dataKey='grid' />
|
||||
<TableColumn
|
||||
title=''
|
||||
width='200'
|
||||
align='right'
|
||||
editButton
|
||||
deleteButton
|
||||
exportButton
|
||||
|
@ -956,48 +932,145 @@ class Scenario extends React.Component {
|
|||
/>
|
||||
</Table>
|
||||
|
||||
<NewDashboardDialog show={this.state.newDashboardModal} onClose={data => this.closeNewDashboardModal(data)} />
|
||||
<EditDashboardDialog show={this.state.dashboardEditModal} dashboard={this.state.modalDashboardData} onClose={data => this.closeEditDashboardModal(data)} />
|
||||
<ImportDashboardDialog show={this.state.importDashboardModal} onClose={data => this.closeImportDashboardModal(data)} />
|
||||
|
||||
<DeleteDialog title="dashboard" name={this.state.modalDashboardData.name} show={this.state.deleteDashboardModal} onClose={(e) => this.closeDeleteDashboardModal(e)} />
|
||||
<NewDashboardDialog
|
||||
show={this.state.newDashboardModal}
|
||||
onClose={data => this.closeNewDashboardModal(data)}
|
||||
/>
|
||||
<EditDashboardDialog
|
||||
show={this.state.dashboardEditModal}
|
||||
dashboard={this.state.modalDashboardData}
|
||||
onClose={data => this.closeEditDashboardModal(data)}
|
||||
/>
|
||||
<ImportDashboardDialog
|
||||
show={this.state.importDashboardModal}
|
||||
onClose={data => this.closeImportDashboardModal(data)}
|
||||
/>
|
||||
<DeleteDialog
|
||||
title="dashboard"
|
||||
name={this.state.modalDashboardData.name}
|
||||
show={this.state.deleteDashboardModal}
|
||||
onClose={(e) => this.closeDeleteDashboardModal(e)}
|
||||
/>
|
||||
|
||||
{/*Result table*/}
|
||||
<h2 style={tableHeadingStyle}>Results
|
||||
<span className='icon-button'>
|
||||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}> Add Result </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({ newResultModal: true })} style={altButtonStyle}><Icon icon="plus" classname={'icon-color'} style={iconStyle} /></Button>
|
||||
</OverlayTrigger>
|
||||
</span>
|
||||
<IconButton
|
||||
key={1}
|
||||
tooltip='Add Result'
|
||||
onClick={() => this.setState({ newResultModal: true })}
|
||||
icon='plus'
|
||||
/>
|
||||
</span>
|
||||
</h2>
|
||||
{resulttable}
|
||||
<NewResultDialog show={this.state.newResultModal} onClose={data => this.closeNewResultModal(data)} />
|
||||
|
||||
<Table data={this.state.results}>
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
modifier={(id, result) => this.modifyResultNoColumn(id, result)}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Description'
|
||||
dataKey='description'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Created at'
|
||||
dataKey='createdAt'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Last update'
|
||||
dataKey='updatedAt'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Files'
|
||||
dataKey='resultFileIDs'
|
||||
linkKey='filebuttons'
|
||||
data={this.state.files}
|
||||
onDownload={(index) => this.downloadResultData(index)}
|
||||
/>
|
||||
<TableColumn
|
||||
width='200'
|
||||
align='right'
|
||||
editButton
|
||||
downloadAllButton
|
||||
deleteButton
|
||||
onEdit={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 })}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<EditResultDialog
|
||||
sessionToken={this.state.sessionToken}
|
||||
show={this.state.editResultsModal}
|
||||
files={this.state.files}
|
||||
results={this.state.results}
|
||||
resultId={this.state.modalResultsIndex}
|
||||
scenarioID={this.state.scenario.id}
|
||||
onClose={this.closeEditResultsModal.bind(this)}
|
||||
/>
|
||||
<DeleteDialog
|
||||
title="result"
|
||||
name={this.state.modalResultsData.id}
|
||||
show={this.state.deleteResultsModal}
|
||||
onClose={(e) => this.closeDeleteResultsModal(e)}
|
||||
/>
|
||||
<ResultConfigDialog
|
||||
show={this.state.resultConfigsModal}
|
||||
configs={this.state.modalResultConfigs}
|
||||
resultNo={this.state.modalResultConfigsIndex}
|
||||
onClose={this.closeResultConfigSnapshots.bind(this)}
|
||||
/>
|
||||
<NewResultDialog
|
||||
show={this.state.newResultModal}
|
||||
onClose={data => this.closeNewResultModal(data)}
|
||||
/>
|
||||
|
||||
{/*Scenario Users table*/}
|
||||
<h2 style={tableHeadingStyle}>Users sharing this scenario</h2>
|
||||
<div>
|
||||
<Table data={this.state.scenario.users}>
|
||||
<TableColumn title='Name' dataKey='username' />
|
||||
<TableColumn title='Mail' dataKey='mail' />
|
||||
<Table data={this.state.scenario.users}>
|
||||
{this.state.currentUser.role === "Admin" ?
|
||||
<TableColumn
|
||||
title=''
|
||||
width='200'
|
||||
deleteButton
|
||||
onDelete={(index) => this.setState({ deleteUserModal: true, deleteUserName: this.state.scenario.users[index].username, modalUserIndex: index })}
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
</Table>
|
||||
: <></>
|
||||
}
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKey='username'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Role'
|
||||
dataKey='role'
|
||||
/>
|
||||
<TableColumn
|
||||
title=''
|
||||
width='200'
|
||||
align='right'
|
||||
deleteButton
|
||||
onDelete={(index) => this.setState({
|
||||
deleteUserModal: true,
|
||||
deleteUserName: this.state.scenario.users[index].username,
|
||||
modalUserIndex: index
|
||||
})}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<InputGroup style={{ width: 400, float: 'right' }}>
|
||||
<FormControl
|
||||
placeholder="Username"
|
||||
onChange={(e) => this.onUserInputChange(e)}
|
||||
value={this.state.userToAdd}
|
||||
type="text"
|
||||
/>
|
||||
<InputGroup.Append>
|
||||
<InputGroup
|
||||
style={{
|
||||
width: 400,
|
||||
float: 'right'
|
||||
}}
|
||||
>
|
||||
<Form.Control
|
||||
placeholder="Username"
|
||||
onChange={(e) => this.onUserInputChange(e)}
|
||||
value={this.state.userToAdd}
|
||||
type="text"
|
||||
/>
|
||||
<InputGroup.Append>
|
||||
<span className='icon-button'>
|
||||
<Button
|
||||
variant='light'
|
||||
|
@ -1006,14 +1079,18 @@ class Scenario extends React.Component {
|
|||
onClick={() => this.addUser()}>
|
||||
<Icon icon="plus" classname={'icon-color'} style={iconStyle} />
|
||||
</Button>
|
||||
</span>
|
||||
</InputGroup.Append>
|
||||
</InputGroup><br /><br />
|
||||
</div>
|
||||
|
||||
<DeleteDialog title="user from scenario:" name={this.state.deleteUserName} show={this.state.deleteUserModal} onClose={(c) => this.closeDeleteUserModal(c)} />
|
||||
|
||||
</span>
|
||||
</InputGroup.Append>
|
||||
</InputGroup>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<DeleteDialog
|
||||
title="Delete user from scenario"
|
||||
name={this.state.deleteUserName}
|
||||
show={this.state.deleteUserModal}
|
||||
onClose={(c) => this.closeDeleteUserModal(c)}
|
||||
/>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <Icon icon='check' />
|
||||
} else {
|
||||
return <Icon icon='times' />
|
||||
}
|
||||
|
||||
return <Icon icon={ running ? 'check' : 'times' } />
|
||||
}
|
||||
|
||||
render() {
|
||||
const buttonStyle = {
|
||||
marginLeft: '10px',
|
||||
};
|
||||
|
||||
const iconStyle = {
|
||||
height: '30px',
|
||||
width: '30px'
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='section'>
|
||||
return <div className='section'>
|
||||
<h1>Scenarios
|
||||
<span className='icon-button'>
|
||||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}> Add Scenario </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({ newModal: true })} style={buttonStyle}><Icon icon="plus" classname='icon-color' style={iconStyle} /></Button>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
key={2}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"import"}`}> Import Scenario </Tooltip>} >
|
||||
<Button variant='light' onClick={() => this.setState({ importModal: true })} style={buttonStyle}><Icon icon="upload" classname='icon-color' style={iconStyle} /></Button>
|
||||
</OverlayTrigger>
|
||||
</span>
|
||||
<IconButton
|
||||
key={0}
|
||||
tooltip='Add Scenario'
|
||||
onClick={() => this.setState({ newModal: true })}
|
||||
icon='plus'
|
||||
/>
|
||||
<IconButton
|
||||
key={1}
|
||||
tooltip='Import Scenario'
|
||||
onClick={() => this.setState({ importModal: true })}
|
||||
icon='upload'
|
||||
/>
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<Table data={this.state.scenarios}>
|
||||
<TableColumn title='Name' dataKey='name' link='/scenarios/' linkKey='id' />
|
||||
<TableColumn title='ID' dataKey='id' />
|
||||
<TableColumn title='Running' dataKey='running' modifier={(running) => this.modifyRunningColumn(running)}/>
|
||||
{this.state.currentUser.role === "Admin" ?
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
: <></>
|
||||
}
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKey='name'
|
||||
link='/scenarios/'
|
||||
linkKey='id'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Running'
|
||||
dataKey='running'
|
||||
modifier={(running) => this.modifyRunningColumn(running)}
|
||||
/>
|
||||
<TableColumn
|
||||
width='200'
|
||||
align='right'
|
||||
editButton
|
||||
deleteButton
|
||||
exportButton
|
||||
|
@ -285,8 +288,7 @@ class Scenarios extends Component {
|
|||
<ImportScenarioDialog show={this.state.importModal} onClose={data => this.closeImportModal(data)} nodes={this.state.nodes} />
|
||||
|
||||
<DeleteDialog title="scenario" name={this.state.modalScenario.name} show={this.state.deleteModal} onClose={(e) => this.closeDeleteModal(e)} />
|
||||
</div>
|
||||
);
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <Dialog
|
||||
show={this.props.show}
|
||||
title="Edit Signal Mapping"
|
||||
buttonTitle="Save"
|
||||
blendOutCancel = {false}
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={true}
|
||||
>
|
||||
<Form.Group>
|
||||
<Form.Label>{this.props.direction} Mapping</Form.Label>
|
||||
<Form.Text>Click <i>Index</i>, <i>Name</i> or <i>Unit</i> cell to edit</Form.Text>
|
||||
<Table checkbox onChecked={(signal) => this.onSignalChecked(signal)} data={this.state.signals}>
|
||||
<TableColumn
|
||||
checkbox
|
||||
onChecked={(index, event) => this.onSignalChecked(index, event)}
|
||||
checkboxKey='checked'
|
||||
width='30'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Index'
|
||||
dataKey='index'
|
||||
inlineEditable
|
||||
inputType='number'
|
||||
onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Name'
|
||||
dataKey='name'
|
||||
inlineEditable
|
||||
inputType='text'
|
||||
onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Unit'
|
||||
dataKey='unit'
|
||||
inlineEditable
|
||||
inputType='text'
|
||||
onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Scaling Factor'
|
||||
dataKey='scalingFactor'
|
||||
inlineEditable
|
||||
inputType='number'
|
||||
onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)}
|
||||
/>
|
||||
<TableColumn
|
||||
title='Remove'
|
||||
deleteButton
|
||||
onDelete={(index) => this.handleDelete(index)}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="Edit Signal Mapping"
|
||||
buttonTitle="Save"
|
||||
blendOutCancel = {false}
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={true}
|
||||
size='lg'>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{this.props.direction} Mapping</FormLabel>
|
||||
<FormText>Click <i>Index</i>, <i>Name</i> or <i>Unit</i> cell to edit</FormText>
|
||||
<Table checkbox onChecked={(signal) => this.onSignalChecked(signal)} data={this.state.signals}>
|
||||
<TableColumn checkbox onChecked={(index, event) => this.onSignalChecked(index, event)} checkboxKey='checked' width='30' />
|
||||
<TableColumn title='Index' dataKey='index' inlineEditable inputType='number' onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)} />
|
||||
<TableColumn title='Name' dataKey='name' inlineEditable inputType='text' onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)} />
|
||||
<TableColumn title='Unit' dataKey='unit' inlineEditable inputType='text' onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)} />
|
||||
<TableColumn title='Scaling Factor' dataKey='scalingFactor' inlineEditable inputType='number' onInlineChange={(e, row, column) => this.handleMappingChange(e, row, column)} />
|
||||
<TableColumn title='Remove' deleteButton onDelete={(index) => this.handleDelete(index)} />
|
||||
</Table>
|
||||
|
||||
<div className='solid-button' style={{ float: 'right' }}>
|
||||
<OverlayTrigger key={0} placement={'left'} overlay={<Tooltip id={`tooltip-${"check"}`}> Check/Uncheck All </Tooltip>} >
|
||||
<Button variant='secondary' key={50} onClick={() => this.checkAll()} style={buttonStyle}> <Icon icon="check" /> </Button>
|
||||
</OverlayTrigger>
|
||||
<Button variant='secondary' key={51} onClick={() => this.handleRemove()} style={buttonStyle}> Remove </Button>
|
||||
<Button variant='secondary' key={52} onClick={() => this.handleAdd()} style={buttonStyle}><Icon icon="plus" /> Signal </Button>
|
||||
<div className='solid-button' style={{ float: 'right' }}>
|
||||
<OverlayTrigger
|
||||
key={0}
|
||||
placement='left'
|
||||
overlay={<Tooltip id={`tooltip-${"check"}`}> Check/Uncheck All </Tooltip>}
|
||||
>
|
||||
<Button
|
||||
variant='secondary'
|
||||
key={50}
|
||||
onClick={() => this.checkAll()}
|
||||
style={buttonStyle}
|
||||
>
|
||||
<Icon icon="check" />
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
<Button
|
||||
variant='secondary'
|
||||
key={51}
|
||||
onClick={() => this.handleRemove()} style={buttonStyle}>
|
||||
<Icon icon="minus" /> Remove
|
||||
</Button>
|
||||
<Button
|
||||
variant='secondary'
|
||||
key={52}
|
||||
onClick={() => this.handleAdd()} style={buttonStyle}>
|
||||
<Icon icon="plus" /> Signal
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Collapse isOpened={this.state.openCollapse}>
|
||||
<h6>Choose a Component Configuration to add the signal to: </h6>
|
||||
<div className='solid-button'>
|
||||
{typeof this.props.configs !== "undefined" && this.props.configs.map(config => (
|
||||
<Button
|
||||
variant='secondary'
|
||||
key={config.id}
|
||||
onClick={() => this.handleAdd(config.id)}
|
||||
style={buttonStyle}
|
||||
>
|
||||
{config.name}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<Collapse isOpened={this.state.openCollapse}>
|
||||
<h6>Choose a Component Configuration to add the signal to: </h6>
|
||||
<div className='solid-button'>
|
||||
{typeof this.props.configs !== "undefined" && this.props.configs.map(config => (
|
||||
|
||||
<Button variant='secondary' key ={config.id} onClick={() => this.handleAdd(config.id)} style={buttonStyle}>{config.name}</Button>
|
||||
|
||||
))}
|
||||
</div>
|
||||
</Collapse>
|
||||
</div>
|
||||
</FormGroup>
|
||||
</Dialog>
|
||||
);
|
||||
</Collapse>
|
||||
</div>
|
||||
</Form.Group>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -30,37 +30,18 @@ body {
|
|||
hyphens: auto;
|
||||
}
|
||||
|
||||
.app-body {
|
||||
/*height: 100%;*/
|
||||
}
|
||||
|
||||
.app-header {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
padding: 10px 0 0 0;
|
||||
|
||||
color: #527984;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.app-header .menu-icon {
|
||||
color: #818181;
|
||||
right: 5px;
|
||||
|
||||
padding: 6px 0 0 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
|
@ -83,12 +64,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 {
|
||||
|
@ -96,7 +72,7 @@ body {
|
|||
}
|
||||
|
||||
.app-content {
|
||||
padding: 15px 20px;
|
||||
padding: 15px 20px 20px 20px;
|
||||
|
||||
width: auto;
|
||||
min-height: 300px;
|
||||
|
@ -106,10 +82,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 {
|
||||
|
@ -122,10 +96,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;
|
||||
|
@ -133,12 +106,12 @@ body {
|
|||
0 9px 18px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.menu-sidebar a {
|
||||
.menu a {
|
||||
color: #4d4d4d;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.menu-sidebar a:hover, .menu-sidebar a:focus {
|
||||
.menu a:hover, .menu a:focus {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
|
@ -146,13 +119,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);
|
||||
|
@ -229,7 +206,7 @@ body {
|
|||
/**
|
||||
* Login select
|
||||
*/
|
||||
.login-select {
|
||||
.login-select {
|
||||
position: sticky;
|
||||
width: 300px;
|
||||
height: 150px;
|
||||
|
@ -271,6 +248,10 @@ hr {
|
|||
/**
|
||||
* Tables
|
||||
*/
|
||||
.table th,td {
|
||||
padding: 0.5em 0.5em !important;
|
||||
}
|
||||
|
||||
.table th {
|
||||
background-color: #527984;
|
||||
color: #fff;
|
||||
|
@ -279,16 +260,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 {
|
||||
|
@ -485,3 +463,15 @@ hr {
|
|||
.badge-outdated {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Swagger UI
|
||||
*/
|
||||
.swagger-ui .wrapper {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.swagger-ui .info {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="Edit user" buttonTitle="Save" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup as={Col} controlId="username">
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.user.username} value={this.state.username} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="mail">
|
||||
<FormLabel>E-mail</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.user.mail} value={this.state.mail} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="oldPassword">
|
||||
<FormLabel>Old Password</FormLabel>
|
||||
<FormControl type="password" placeholder="Enter current password" value={this.state.oldPassword} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup as={Col} controlId="password">
|
||||
<FormLabel>New Password</FormLabel>
|
||||
<FormControl type="password" placeholder="Enter password" value={this.state.password} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup as={Col} controlId="confirmpassword">
|
||||
<FormLabel>Confirm New Password</FormLabel>
|
||||
<FormControl type="password" placeholder="Enter password" value={this.state.confirmpassword} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
</form>
|
||||
<Form>
|
||||
<Form.Group as={Col} controlId="username">
|
||||
<Form.Label>Username</Form.Label>
|
||||
<Form.Control type="text" value={this.state.username} onChange={(e) => this.handleChange(e)} autocomplete="username" />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="mail">
|
||||
<Form.Label>E-mail</Form.Label>
|
||||
<Form.Control type="text" value={this.state.mail} onChange={(e) => this.handleChange(e)} autocomplete="email" />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="oldPassword">
|
||||
<Form.Label>Old Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Enter current password" value={this.state.oldPassword} onChange={(e) => this.handleChange(e)} autocomplete="current-password" />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="password">
|
||||
<Form.Label>New Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Enter new password" value={this.state.password} onChange={(e) => this.handleChange(e)} autocomplete="new-password" />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="confirmPassword">
|
||||
<Form.Label>Confirm New Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Repeat new password" value={this.state.confirmPassword} onChange={(e) => this.handleChange(e)} autocomplete="new-password" />
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="Edit user" buttonTitle="Save" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup as={Col} controlId="username">
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.user.username} value={this.state.username} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="mail">
|
||||
<FormLabel>E-mail</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.user.mail} value={this.state.mail} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="oldPassword">
|
||||
<FormLabel>Admin Password</FormLabel>
|
||||
<FormControl type="password" placeholder="Enter admin password" value={this.state.oldPassword} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="password">
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl type="password" placeholder="Enter password" value={this.state.password} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="confirmpassword">
|
||||
<FormLabel>Confirm New Password</FormLabel>
|
||||
<FormControl type="password" placeholder="Enter password" value={this.state.confirmpassword} onChange={(e) => this.handleChange(e)} />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="role">
|
||||
<FormLabel>Role</FormLabel>
|
||||
<FormControl as="select" placeholder="Select role" value={this.state.role} onChange={(e) => this.handleChange(e)}>
|
||||
<Form>
|
||||
<Form.Group as={Col} controlId="username">
|
||||
<Form.Label>Username</Form.Label>
|
||||
<Form.Control type="text" value={this.state.username} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="mail">
|
||||
<Form.Label>E-mail</Form.Label>
|
||||
<Form.Control type="text" value={this.state.mail} onChange={(e) => this.handleChange(e)} />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="oldPassword">
|
||||
<Form.Label>Admin Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Enter admin password" value={this.state.oldPassword} onChange={(e) => this.handleChange(e)} />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="password">
|
||||
<Form.Label>Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Enter password" value={this.state.password} onChange={(e) => this.handleChange(e)} />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="confirmPassword">
|
||||
<Form.Label>Confirm New Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Enter password" value={this.state.confirmPassword} onChange={(e) => this.handleChange(e)} />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="role">
|
||||
<Form.Label>Role</Form.Label>
|
||||
<Form.Control as="select" placeholder="Select role" value={this.state.role} onChange={(e) => this.handleChange(e)}>
|
||||
<option key='1' value='Admin'>Administrator</option>
|
||||
<option key='2' value='User'>User</option>
|
||||
<option key='3' value='Guest'>Guest</option>
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup as={Col} controlId="active">
|
||||
<FormLabel>Active</FormLabel>
|
||||
<FormControl as="select" placeholder="Select Active state" value={this.state.active} onChange={(e) => this.handleChange(e)}>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="active">
|
||||
<Form.Label>Active</Form.Label>
|
||||
<Form.Control as="select" placeholder="Select Active state" value={this.state.active} onChange={(e) => this.handleChange(e)}>
|
||||
<option key='1' value='yes'>Yes</option>
|
||||
<option key='2' value='no'>No</option>
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
|
||||
</form>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 (<Redirect to="/login" />);
|
||||
} else {
|
||||
return (<div class="verticalhorizontal">
|
||||
<img style={{height: 300}}src={require('../img/dog-waiting-bw.jpg').default} alt="Waiting Dog" /></div>);
|
||||
return <div class="verticalhorizontal">
|
||||
<img
|
||||
style={{height: 300}}
|
||||
src={require('../img/dog-waiting-bw.jpg').default}
|
||||
alt="Waiting Dog" />
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let fluxContainerConverter = require('../common/FluxContainerConverter');
|
||||
export default Container.create(fluxContainerConverter.convert(LoginComplete));
|
||||
export default Container.create(fluxContainerConverter.convert(LoginComplete));
|
||||
|
|
|
@ -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 (
|
||||
<Form key="login_a">
|
||||
<FormGroup controlId="username">
|
||||
<FormLabel column={true}>Username</FormLabel>
|
||||
<Form.Group controlId="username">
|
||||
<Form.Label column={true}>Username</Form.Label>
|
||||
<Col>
|
||||
<FormControl type="text" placeholder="Username" autoComplete="username" onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control type="text" placeholder="Username" autoComplete="username" onChange={(e) => this.handleChange(e)} />
|
||||
</Col>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
<FormGroup controlId="password">
|
||||
<FormLabel column={true}>Password</FormLabel>
|
||||
<Form.Group controlId="password">
|
||||
<Form.Label column={true}>Password</Form.Label>
|
||||
<Col >
|
||||
<FormControl type="password" placeholder="Password" autoComplete="current-password" onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control type="password" placeholder="Password" autoComplete="current-password" onChange={(e) => this.handleChange(e)} />
|
||||
</Col>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
{this.props.loginMessage &&
|
||||
<div style={{ marginBottom: '20px', color: 'red', fontSize: 'small' }}>
|
||||
|
@ -91,17 +91,16 @@ class LoginForm extends Component {
|
|||
</div>
|
||||
}
|
||||
|
||||
<FormGroup style={{ paddingTop: 15, paddingBottom: 5 }}>
|
||||
<Form.Group style={{ paddingTop: 15, paddingBottom: 5 }}>
|
||||
<Col>
|
||||
<span className='solid-button'>
|
||||
<Button variant='secondary' style={{width: 90}} type="submit" disabled={this.state.disableLogin} onClick={e => this.login(e)}>Login</Button>
|
||||
</span>
|
||||
<Button variant="link" size="sm" style={{marginLeft: 85}} onClick={() => this.openRecoverPassword()}>Forgot your password?</Button>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
<RecoverPassword show={this.state.forgottenPassword} onClose={() => this.closeRecoverPassword()} sessionToken={this.props.sessionToken} />
|
||||
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="New user" buttonTitle="Add" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form>
|
||||
<FormGroup as={Col} controlId="username">
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter username" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
<FormText>Min 3 characters.</FormText>
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="mail">
|
||||
<FormLabel>E-mail</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter e-mail" value={this.state.mail} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="password">
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl type="text" placeholder="Enter password" value={this.state.password} onChange={(e) => this.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} controlId="role">
|
||||
<FormLabel>Role</FormLabel>
|
||||
<FormControl as="select" placeholder="Select role" value={this.state.role} onChange={(e) => this.handleChange(e)}>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="New User"
|
||||
buttonTitle="Add"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={this.valid}
|
||||
>
|
||||
<Form>
|
||||
<Form.Group as={Col} controlId="username">
|
||||
<Form.Label>Username</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter username" value={this.state.name} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
<Form.Text>Min 3 characters.</Form.Text>
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="mail">
|
||||
<Form.Label>E-mail</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter e-mail" value={this.state.mail} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="password">
|
||||
<Form.Label>Password</Form.Label>
|
||||
<Form.Control type="text" placeholder="Enter password" value={this.state.password} onChange={(e) => this.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
<Form.Group as={Col} controlId="role">
|
||||
<Form.Label>Role</Form.Label>
|
||||
<Form.Control as="select" placeholder="Select role" value={this.state.role} onChange={(e) => this.handleChange(e)}>
|
||||
<option key='1' value='Admin'>Administrator</option>
|
||||
<option key='2' value='User'>User</option>
|
||||
<option key='3' value='Guest'>Guest</option>
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
</form>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -35,13 +35,20 @@ class RecoverPassword extends React.Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<Dialog show={this.props.show} title="Recover password" buttonTitle="Close" onClose={(c) => this.onClose(c)} blendOutCancel = {true} valid={true} size = 'lg'>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="Recover password"
|
||||
buttonTitle="Close"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
blendOutCancel={true}
|
||||
valid={true}
|
||||
>
|
||||
<div>
|
||||
<div>Please contact:</div>
|
||||
<div>{this.state.admin.name}</div>
|
||||
<div>E-Mail:</div>
|
||||
<a href={`mailto:${this.state.admin.mail}`}>{this.state.admin.mail}</a>
|
||||
</div>
|
||||
<div>Please contact:</div>
|
||||
<div>{this.state.admin.name}</div>
|
||||
<div>E-Mail:</div>
|
||||
<a href={`mailto:${this.state.admin.mail}`}>{this.state.admin.mail}</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
144
src/user/user.js
144
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 (
|
||||
<div>
|
||||
<h1>Your User Account</h1>
|
||||
<h1>Account</h1>
|
||||
|
||||
{this.state.currentUser !== undefined && this.state.currentUser !== null ?
|
||||
{user ?
|
||||
<>
|
||||
<Form>
|
||||
<Form.Group as={Row} controlId="username">
|
||||
<Form.Label column sm={2}>Username</Form.Label>
|
||||
<Col sm={10}>
|
||||
<Form.Control plaintext readOnly defaultValue={user.username} />
|
||||
</Col>
|
||||
</Form.Group>
|
||||
<Form.Group as={Row} controlId="mail">
|
||||
<Form.Label column sm={2}>E-mail</Form.Label>
|
||||
<Col sm={10}>
|
||||
<Form.Control plaintext readOnly defaultValue={user.mail} type="email" />
|
||||
</Col>
|
||||
</Form.Group>
|
||||
<Form.Group as={Row} controlId="role">
|
||||
<Form.Label column sm={2}>Role</Form.Label>
|
||||
<Col sm={10}>
|
||||
<Form.Control plaintext readOnly defaultValue={user.role} />
|
||||
</Col>
|
||||
</Form.Group>
|
||||
<Form.Group as={Row} controlId="formBasicEmail">
|
||||
<Form.Label column sm={2}>Created at</Form.Label>
|
||||
<Col sm={10}>
|
||||
<Form.Control plaintext readOnly defaultValue={user.createdAt} />
|
||||
</Col>
|
||||
</Form.Group>
|
||||
<Button variant="primary" onClick={() => this.setState({ editModal: true })}>
|
||||
<Icon icon='edit' /> Edit
|
||||
</Button>
|
||||
</Form>
|
||||
|
||||
<form>
|
||||
|
||||
<Row>
|
||||
<FormGroup as={Col} sm={2} controlId="details">
|
||||
<div style={{ alignItems: 'right' }}>Username:</div>
|
||||
<div style={{ alignItems: 'right' }}>E-mail:</div>
|
||||
<div style={{ alignItems: 'right' }}>Role:</div>
|
||||
</FormGroup>
|
||||
<FormGroup as={Col} sm={3} controlId="information" >
|
||||
<div> {this.state.currentUser.username}</div>
|
||||
<div>{this.state.currentUser.mail}</div>
|
||||
<div>{this.state.currentUser.role}</div>
|
||||
<span className='icon-button'>
|
||||
<Button variant='light' size='lg' variant='light' style={{margin: '10px'}} onClick={() => this.setState({ editModal: true })}><Icon size='lg' classname='icon-color' icon='edit' /> </Button>
|
||||
</span>
|
||||
</FormGroup>
|
||||
</Row>
|
||||
|
||||
<EditOwnUserDialog show={this.state.editModal} onClose={(data) => this.closeEditModal(data)}
|
||||
user={this.state.currentUser} />
|
||||
|
||||
</form> : "Loading user data..."
|
||||
<EditOwnUserDialog
|
||||
show={this.state.editModal}
|
||||
onClose={(data) => this.closeEditModal(data)}
|
||||
user={user}
|
||||
/>
|
||||
</>
|
||||
: <div/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -50,7 +50,6 @@ class UsersStore extends ArrayStore {
|
|||
return super.reduce(state, action);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new UsersStore();
|
||||
|
|
|
@ -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 <Icon icon='check' />
|
||||
} else {
|
||||
return <Icon icon='times' />
|
||||
}
|
||||
|
||||
modifyActiveColumn(active) {
|
||||
return <Icon icon={active ? 'check' : 'times'} />
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const buttonStyle = {
|
||||
marginLeft: '10px',
|
||||
};
|
||||
|
||||
const iconStyle = {
|
||||
height: '30px',
|
||||
width: '30px'
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
return <div>
|
||||
<h1>Users
|
||||
<span className='icon-button'>
|
||||
<OverlayTrigger
|
||||
key={1}
|
||||
placement={'top'}
|
||||
overlay={<Tooltip id={`tooltip-${"add"}`}> Add User </Tooltip>} >
|
||||
<Button variant='light' style={buttonStyle} onClick={() => this.setState({ newModal: true })}><Icon icon='plus' classname='icon-color' style={iconStyle} /> </Button>
|
||||
</OverlayTrigger>
|
||||
</span>
|
||||
<IconButton
|
||||
key={0}
|
||||
tooltip='Add User'
|
||||
onClick={() => this.setState({ newModal: true })}
|
||||
icon='plus'
|
||||
/>
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<Table data={this.state.users}>
|
||||
<TableColumn title='Username' width='150' dataKey='username' />
|
||||
<TableColumn title='ID' width='150' dataKey='id' />
|
||||
<TableColumn title='E-mail' dataKey='mail' />
|
||||
<TableColumn title='Role' dataKey='role' modifier={(role) => this.getHumanRoleName(role)} />
|
||||
<TableColumn title='Active' dataKey='active' modifier={(active) => this.modifyActiveColumn(active)} />
|
||||
<TableColumn width='200' editButton deleteButton onEdit={index => 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" ?
|
||||
<TableColumn
|
||||
title='ID'
|
||||
dataKey='id'
|
||||
/>
|
||||
: <></>
|
||||
}
|
||||
<TableColumn
|
||||
title='Username'
|
||||
width='150'
|
||||
dataKey='username'
|
||||
/>
|
||||
<TableColumn
|
||||
title='E-mail'
|
||||
dataKey='mail'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Role'
|
||||
dataKey='role'
|
||||
/>
|
||||
<TableColumn
|
||||
title='Active'
|
||||
dataKey='active'
|
||||
modifier={(active) => this.modifyActiveColumn(active)}
|
||||
/>
|
||||
<TableColumn
|
||||
width='200'
|
||||
align='right'
|
||||
editButton
|
||||
deleteButton
|
||||
onEdit={index => this.setState({
|
||||
editModal: true,
|
||||
modalData: this.state.users[index]
|
||||
})}
|
||||
onDelete={index => this.setState({
|
||||
deleteModal: true,
|
||||
modalData: this.state.users[index]
|
||||
})}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
<NewUserDialog show={this.state.newModal} onClose={(data) => this.closeNewModal(data)} />
|
||||
<EditUserDialog show={this.state.editModal} onClose={(data) => this.closeEditModal(data)} user={this.state.modalData} />
|
||||
|
||||
<DeleteDialog title="user" name={this.state.modalData.username} show={this.state.deleteModal} onClose={(e) => this.closeDeleteModal(e)} />
|
||||
</div>
|
||||
);
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <Dialog show={this.props.show} title='Color Picker' buttonTitle='Save' onClose={(c) => this.onClose(c)} valid={true}>
|
||||
<form>
|
||||
return <Dialog
|
||||
show={this.props.show}
|
||||
title='Color Picker'
|
||||
buttonTitle='Save'
|
||||
onClose={(c) => this.onClose(c)}
|
||||
valid={true}
|
||||
>
|
||||
<Form>
|
||||
<SketchPicker
|
||||
color={rgbColor}
|
||||
disableAlpha={this.props.disableOpacity}
|
||||
disableAlpha={this.props.disableOpacity}
|
||||
onChangeComplete={ this.handleChangeComplete }
|
||||
width={"300"}
|
||||
width={300}
|
||||
/>
|
||||
|
||||
</form>
|
||||
</Form>
|
||||
</Dialog>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup>
|
||||
<FormCheck
|
||||
<Form.Group>
|
||||
<Form.Check
|
||||
type='checkbox'
|
||||
id={this.props.controlId}
|
||||
checked={isCustomProperty ? this.state.widget[parts[0]][parts[1]] : this.state.widget[this.props.controlId]}
|
||||
label={"Lock Aspect Ratio"}
|
||||
onChange={e => this.props.handleChange(e)}>
|
||||
</FormCheck>
|
||||
</FormGroup>
|
||||
onChange={e => this.props.handleChange(e)}
|
||||
/>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <FormGroup>
|
||||
<FormCheck
|
||||
return <Form.Group>
|
||||
<Form.Check
|
||||
type={"checkbox"}
|
||||
id={this.props.controlId}
|
||||
label={this.props.text}
|
||||
defaultChecked={this.state.isChecked}
|
||||
onChange={e => this.handleCheckboxChange(e)}>
|
||||
|
||||
</FormCheck>
|
||||
</FormGroup>;
|
||||
onChange={e => this.handleCheckboxChange(e)}
|
||||
/>
|
||||
</Form.Group>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup>
|
||||
<FormLabel>{this.props.label}</FormLabel>
|
||||
|
||||
<div className='section-buttons-group-right'>
|
||||
return <Form.Group>
|
||||
<Form.Label>{this.props.label}</Form.Label>
|
||||
|
||||
<div className='section-buttons-group-right'>
|
||||
<OverlayTrigger key={0} placement={'right'} overlay={<Tooltip id={`tooltip-${"color"}`}> {tooltipText} </Tooltip>} >
|
||||
<Button key={2} style={style} onClick={this.openColorPicker.bind(this)} >
|
||||
<Icon icon="paint-brush"/>
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ColorPicker show={this.state.showColorPicker} onClose={(data) => this.closeEditModal(data)} widget={this.state.widget} controlId={this.props.controlId} disableOpacity={this.props.disableOpacity}/>
|
||||
</FormGroup>
|
||||
|
||||
)
|
||||
<ColorPicker show={this.state.showColorPicker} onClose={(data) => this.closeEditModal(data)} widget={this.state.widget} controlId={this.props.controlId} disableOpacity={this.props.disableOpacity}/>
|
||||
</Form.Group>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <FormGroup>
|
||||
<FormLabel>Color zones</FormLabel>
|
||||
|
||||
return <Form.Group>
|
||||
<Form.Label>Color Zones</Form.Label>
|
||||
<span className='icon-button'>
|
||||
<Button variant='light' onClick={this.addZone} style={buttonStyle} disabled={!this.props.widget.customProperties.colorZones}><Icon icon="plus" className='icon-color' style={iconStyle} /></Button>
|
||||
<Button
|
||||
variant='light'
|
||||
onClick={this.addZone}
|
||||
style={buttonStyle}
|
||||
disabled={!this.props.widget.customProperties.colorZones}
|
||||
>
|
||||
<Icon icon="plus" className='icon-color' style={iconStyle} />
|
||||
</Button>
|
||||
</span>
|
||||
<div>
|
||||
{
|
||||
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 (<Button
|
||||
style={style} key={idx} onClick={i => this.editColorZone(idx)} disabled={!this.props.widget.customProperties.colorZones}><Icon icon="pen" /></Button>
|
||||
)
|
||||
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 (<Button
|
||||
style={style} key={idx} onClick={i => this.editColorZone(idx)} disabled={!this.props.widget.customProperties.colorZones}><Icon icon="pen" /></Button>
|
||||
)
|
||||
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<Collapse isOpened={collapse} >
|
||||
<OverlayTrigger key={0} placement={'right'} overlay={<Tooltip id={`tooltip-${"color"}`}>Change color</Tooltip>} >
|
||||
<Button key={0} style={pickerStyle} onClick={this.openColorPicker.bind(this)} >
|
||||
<Icon icon="paint-brush"/>
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Min:
|
||||
<FormControl
|
||||
type="number"
|
||||
step="any"
|
||||
placeholder="Min"
|
||||
value={this.state.minValue}
|
||||
onChange={e => this.handleMinChange(e)} />
|
||||
</td>
|
||||
<td>
|
||||
Max:
|
||||
<FormControl
|
||||
type="number"
|
||||
step="any"
|
||||
placeholder="Max"
|
||||
value={ this.state.maxValue}
|
||||
onChange={e => this.handleMaxChange(e)} />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<span className='icon-button'>
|
||||
<Button variant='light' onClick={this.removeZones} ><Icon style={iconStyle} classname='icon-color' icon="trash-alt" /></Button>
|
||||
</span>
|
||||
</div>
|
||||
<Collapse isOpened={collapse}>
|
||||
<OverlayTrigger key={0} placement={'right'} overlay={<Tooltip id={`tooltip-${"color"}`}>Change color</Tooltip>} >
|
||||
<Button key={0} style={pickerStyle} onClick={this.openColorPicker.bind(this)} >
|
||||
<Icon icon="paint-brush"/>
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Min:
|
||||
<Form.Control
|
||||
type="number"
|
||||
step="any"
|
||||
placeholder="Min"
|
||||
value={this.state.minValue}
|
||||
onChange={e => this.handleMinChange(e)} />
|
||||
</td>
|
||||
<td>
|
||||
Max:
|
||||
<Form.Control
|
||||
type="number"
|
||||
step="any"
|
||||
placeholder="Max"
|
||||
value={ this.state.maxValue}
|
||||
onChange={e => this.handleMaxChange(e)} />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
<span className='icon-button'>
|
||||
<Button variant='light' onClick={this.removeZones} ><Icon style={iconStyle} classname='icon-color' icon="trash-alt" /></Button>
|
||||
</span>
|
||||
</Collapse>
|
||||
|
||||
<ColorPicker show={this.state.showColorPicker} onClose={(data) => this.closeEditModal(data)} widget={this.state.widget} zoneIndex={this.state.selectedIndex} controlId={'strokeStyle'} />
|
||||
</FormGroup>;
|
||||
</Form.Group>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <div>
|
||||
<FormGroup controlId="file">
|
||||
<FormLabel>File</FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId="file">
|
||||
<Form.Label>File</Form.Label>
|
||||
<Form.Control
|
||||
as="select"
|
||||
value={isCustomProperty ? this.props.widget[parts[0]][parts[1]] : this.props.widget[this.props.controlId]}
|
||||
onChange={(e) => this.handleFileChange(e)}>{fileOptions} </FormControl>
|
||||
</FormGroup>
|
||||
onChange={(e) => this.handleFileChange(e)}>{fileOptions} </Form.Control>
|
||||
</Form.Group>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId={this.props.controlId}>
|
||||
<FormLabel>HTML Content</FormLabel>
|
||||
<FormControl onKeyDown={this.handleKeyIgnore} componentclass="textarea" style={{ height: 200 }} placeholder={this.props.placeholder} value={this.state.value} onChange={e => this.props.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<Form.Group controlId={this.props.controlId}>
|
||||
<Form.Label>HTML Content</Form.Label>
|
||||
<Form.Control
|
||||
onKeyDown={this.handleKeyIgnore}
|
||||
componentclass="textarea"
|
||||
style={{ height: 200 }}
|
||||
placeholder={this.props.placeholder}
|
||||
value={this.state.value}
|
||||
onChange={e => this.props.handleChange(e)}
|
||||
/>
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default EditWidgetHTMLContent;
|
||||
|
|
|
@ -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 <div>
|
||||
<FormGroup controlId="ic">
|
||||
<FormLabel>IC</FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId="ic">
|
||||
<Form.Label>IC</Form.Label>
|
||||
<Form.Control
|
||||
as="select"
|
||||
value={isCustomProperty ? this.props.widget[parts[0]][parts[1]] : this.props.widget[this.props.controlId]}
|
||||
onChange={(e) => this.handleICChange(e)}>{icOptions} </FormControl>
|
||||
</FormGroup>
|
||||
onChange={(e) => this.handleICChange(e)}>{icOptions} </Form.Control>
|
||||
</Form.Group>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <FormGroup>
|
||||
<FormLabel>{this.props.label}</FormLabel>
|
||||
<FormCheck
|
||||
return <Form.Group>
|
||||
<Form.Label>{this.props.label}</Form.Label>
|
||||
<Form.Check
|
||||
label= {"UseMinMax"}
|
||||
defaultChecked={this.state.useMinMax}
|
||||
onChange={e => this.handleCheckboxChange(e)}>
|
||||
</FormCheck>
|
||||
</Form.Check>
|
||||
|
||||
<Table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Min:
|
||||
<FormControl
|
||||
<Form.Control
|
||||
type="number"
|
||||
step="any"
|
||||
disabled={!this.state.useMinMax}
|
||||
|
@ -98,7 +98,7 @@ class EditWidgetMinMaxControl extends React.Component {
|
|||
</td>
|
||||
<td>
|
||||
Max:
|
||||
<FormControl
|
||||
<Form.Control
|
||||
type="number"
|
||||
step="any"
|
||||
disabled={!this.state.useMinMax}
|
||||
|
@ -109,7 +109,7 @@ class EditWidgetMinMaxControl extends React.Component {
|
|||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
</FormGroup>;
|
||||
</Form.Group>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId={this.props.controlId}>
|
||||
<FormLabel>{this.props.label}</FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId={this.props.controlId}>
|
||||
<Form.Label>{this.props.label}</Form.Label>
|
||||
<Form.Control
|
||||
type="number"
|
||||
step={step}
|
||||
value={isCustomProperty ? this.state.widget[parts[0]][parts[1]] : this.state.widget[this.props.controlId]}
|
||||
onChange={e => this.props.handleChange(e)} />
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <Row> tag shouldn't be necessary, but it gives height to the row while combining horizontal and vertical forms
|
||||
return (
|
||||
<FormGroup controlId="orientation">
|
||||
<Form.Group controlId="orientation">
|
||||
<Row>
|
||||
<Col className={FormLabel} sm={3}>
|
||||
<Col className={Form.Label} sm={3}>
|
||||
Orientation
|
||||
</Col>
|
||||
<Col sm={10}>
|
||||
|
@ -64,14 +63,20 @@ class EditWidgetOrientation extends Component {
|
|||
let value = WidgetSlider.OrientationTypes[type].value;
|
||||
let name = WidgetSlider.OrientationTypes[type].name;
|
||||
|
||||
return (
|
||||
<FormCheck inline label={name} key={value} id={value} type='radio' title='orientation' checked={ value === this.state.widget.customProperties.orientation } onChange={(e) => this.handleOrientationChange(value)}>
|
||||
</FormCheck>)
|
||||
return <Form.Check
|
||||
inline label={name}
|
||||
key={value}
|
||||
id={value}
|
||||
type='radio'
|
||||
title='orientation'
|
||||
checked={ value === this.state.widget.customProperties.orientation }
|
||||
onChange={(e) => this.handleOrientationChange(value)}
|
||||
/>
|
||||
})
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId={this.props.controlId}>
|
||||
<FormLabel>{this.props.label}</FormLabel>
|
||||
<ParametersEditor content={this.state.widget[this.props.controlId] || {}} onChange={(v)=> this.handleChange(v)} />
|
||||
</FormGroup>
|
||||
<Form.Group controlId={this.props.controlId}>
|
||||
<Form.Label>{this.props.label}</Form.Label>
|
||||
<ParametersEditor
|
||||
content={this.state.widget[this.props.controlId] || {}}
|
||||
onChange={(v)=> this.handleChange(v)}
|
||||
/>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup>
|
||||
<FormLabel>Line Colors</FormLabel>
|
||||
<Form.Group>
|
||||
<Form.Label>Line Colors</Form.Label>
|
||||
<div>
|
||||
{
|
||||
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'
|
||||
}
|
||||
|
||||
<div>
|
||||
{
|
||||
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 (<OverlayTrigger key={idx} placement={'bottom'} overlay={<Tooltip id={'tooltip-${"signal name"}'}>{signal.name}</Tooltip>}>
|
||||
<Button
|
||||
style={style} key={idx} onClick={i => this.editLineColor(signalID)} ><Icon icon="pen" /></Button>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
})
|
||||
}
|
||||
return <OverlayTrigger
|
||||
key={idx}
|
||||
placement={'bottom'}
|
||||
overlay={<Tooltip id={'tooltip-${"signal name"}'}>{signal.name}</Tooltip>}
|
||||
>
|
||||
<Button
|
||||
style={style}
|
||||
key={idx}
|
||||
onClick={i => this.editLineColor(signalID)}
|
||||
>
|
||||
<Icon icon="pen" />
|
||||
</Button>
|
||||
</OverlayTrigger>;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<ColorPicker show={this.state.showColorPicker} onClose={(data) => this.closeEditModal(data)} widget={this.state.widget} lineIndex={this.state.selectedIndex} controlId={'lineColor'} disableOpacity={true}/>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId="signal">
|
||||
<FormLabel>Select signal</FormLabel>
|
||||
<FormControl as="select" value={this.props.widget.signalIDs[0] || ""} onChange={(e) => this.handleSignalChange(e)}>
|
||||
<Form.Group controlId="signal">
|
||||
<Form.Label>Select signal</Form.Label>
|
||||
<Form.Control as="select" value={this.props.widget.signalIDs[0] || ""} onChange={(e) => this.handleSignalChange(e)}>
|
||||
<option default>Select signal</option>
|
||||
{
|
||||
this.state.signals.length === 0 ? (
|
||||
|
@ -61,8 +61,8 @@ class EditWidgetSignalControl extends Component {
|
|||
))
|
||||
)
|
||||
}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup>
|
||||
<FormLabel>Signals</FormLabel>
|
||||
<Form.Group>
|
||||
<Form.Label>Signals</Form.Label>
|
||||
{
|
||||
this.state.signals === 0 || !this.state.widget.hasOwnProperty(this.props.controlId)? (
|
||||
<FormLabel>No signals available</FormLabel>
|
||||
<Form.Label>No signals available</Form.Label>
|
||||
) : (
|
||||
this.state.signals.map((signal, index) => (
|
||||
<FormCheck
|
||||
<Form.Check
|
||||
type={'checkbox'}
|
||||
label={signal.name}
|
||||
id={signal.id}
|
||||
key={signal.id}
|
||||
checked={this.state.checkedSignals.find(id => id === signal.id) !== undefined}
|
||||
onChange={(e) => this.handleSignalChange(e.target.checked, signal.id)}>
|
||||
</FormCheck>
|
||||
</Form.Check>
|
||||
))
|
||||
)
|
||||
}
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId={this.props.controlId}>
|
||||
<FormLabel>{this.props.label}</FormLabel>
|
||||
<FormControl type="text" placeholder={this.props.placeholder} value={this.state.value} onChange={e => this.props.handleChange(e)} />
|
||||
<FormControl.Feedback />
|
||||
</FormGroup>
|
||||
<Form.Group controlId={this.props.controlId}>
|
||||
<Form.Label>{this.props.label}</Form.Label>
|
||||
<Form.Control type="text" placeholder={this.props.placeholder} value={this.state.value} onChange={e => this.props.handleChange(e)} />
|
||||
<Form.Control.Feedback />
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId="customProperties.textSize">
|
||||
<FormLabel>Text size</FormLabel>
|
||||
<FormControl as="select" value={this.props.widget.customProperties.textSize} onChange={e => this.props.handleChange(e)}>
|
||||
<Form.Group controlId="customProperties.textSize">
|
||||
<Form.Label>Text size</Form.Label>
|
||||
<Form.Control as="select" value={this.props.widget.customProperties.textSize} onChange={e => this.props.handleChange(e)}>
|
||||
{sizes.map((size, index) => (
|
||||
<option key={index} value={size}>{size}</option>
|
||||
))}
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<FormGroup controlId= {this.props.controlId}>
|
||||
<FormLabel>Time</FormLabel>
|
||||
<FormControl
|
||||
<Form.Group controlId= {this.props.controlId}>
|
||||
<Form.Label>Time</Form.Label>
|
||||
<Form.Control
|
||||
type="number"
|
||||
min="1"
|
||||
max="300"
|
||||
|
@ -53,8 +53,8 @@ class EditWidgetTimeControl extends Component {
|
|||
value={isCustomProperty ? this.state.widget[parts[0]][parts[1]] : this.state.widget[this.props.controlId]}
|
||||
onChange={(e) => this.props.handleChange(e)}
|
||||
/>
|
||||
<FormText>Time in seconds</FormText>
|
||||
</FormGroup>
|
||||
<Form.Text>Time in seconds</Form.Text>
|
||||
</Form.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<Dialog show={this.props.show} title="Edit Widget" buttonTitle="Save" onClose={(c) => this.onClose(c)} onReset={() => this.resetState()} valid={this.valid}>
|
||||
<form encType='multipart/form-data'>
|
||||
<Dialog
|
||||
show={this.props.show}
|
||||
title="Edit Widget"
|
||||
buttonTitle="Save"
|
||||
onClose={(c) => this.onClose(c)}
|
||||
onReset={() => this.resetState()}
|
||||
valid={this.valid}
|
||||
>
|
||||
<Form encType='multipart/form-data'>
|
||||
{ controls || '' }
|
||||
</form>
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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){
|
|||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PlotLegend extends React.Component {
|
||||
|
@ -60,7 +59,6 @@ class PlotLegend extends React.Component {
|
|||
<Legend key={signal.id} sig={signal} lineColor={"undefined"}/>
|
||||
))
|
||||
}
|
||||
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
|||
<canvas ref={node => this.gaugeCanvas = node} />
|
||||
<div className="gauge-unit">{this.state.unit + scaleText}</div>
|
||||
<div className="gauge-value">{this.state.value}</div>
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<div className="number-input-widget full">
|
||||
<Form componentclass="fieldset" horizontal="true">
|
||||
<FormGroup>
|
||||
<Col as={FormLabel}>
|
||||
<Form.Group>
|
||||
<Col as={Form.Label}>
|
||||
{this.props.widget.name}
|
||||
</Col>
|
||||
<Col>
|
||||
<InputGroup>
|
||||
<FormControl
|
||||
<Form.Control
|
||||
type="number"
|
||||
step="any"
|
||||
disabled={ this.props.editing }
|
||||
|
@ -112,7 +112,7 @@ class WidgetInput extends Component {
|
|||
)}
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -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 (
|
||||
<div className="time-offset">
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
(<span></span>) : (<span>no IC</span>)
|
||||
}
|
||||
{this.props.widget.customProperties.icID !== -1 && this.props.widget.customProperties.showName ?
|
||||
{this.props.widget.customProperties.icID !== -1 && this.props.widget.customProperties.showName ?
|
||||
(<span>{this.state.icName}</span>) : (<span></span>)
|
||||
}
|
||||
}
|
||||
<OverlayTrigger key={0} placement={'left'} overlay={<Tooltip id={`tooltip-${"traffic-light"}`}>
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
(<span>{this.state.icName}<br></br>Offset: {this.state.timeOffset + "s"}</span>)
|
||||
:
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
(<span>{this.state.icName}<br></br>Offset: {this.state.timeOffset + "s"}</span>)
|
||||
:
|
||||
(<span>Please select Infrastructure Component</span>)}
|
||||
</Tooltip>}>
|
||||
</Tooltip>}>
|
||||
<TrafficLight Horizontal={this.props.widget.customProperties.horizontal} width={this.props.widget.width - 40} height={this.props.widget.height - 40}
|
||||
RedOn={(this.props.widget.customProperties.threshold_red <= this.state.timeOffset) || !this.state.websocketOpen}
|
||||
YellowOn={(this.props.widget.customProperties.threshold_yellow <= this.state.timeOffset) && (this.state.timeOffset < this.props.widget.customProperties.threshold_red) && this.state.websocketOpen}
|
||||
GreenOn={(this.state.timeOffset < this.props.widget.customProperties.threshold_yellow) && this.state.websocketOpen}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
(
|
||||
<span>{icSelected}</span>)
|
||||
:
|
||||
|
|
|
@ -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<P>, prevState: Readonly<S>, 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);
|
||||
|
|
Loading…
Add table
Reference in a new issue