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

Merge branch 'master' into feature-whitelabel

This commit is contained in:
irismarie 2021-04-30 13:39:57 +02:00
commit ec04fdc81b
7 changed files with 293 additions and 216 deletions

View file

@ -18,49 +18,47 @@
import React from 'react';
import { Form } from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
class NewDashboardDialog extends React.Component {
valid: false;
import Dialog from './dialog';
class NewDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
name: ''
value: ''
}
}
onClose(canceled) {
if (canceled === false) {
if (this.valid) {
this.props.onClose(this.state);
}
this.props.onClose(this.state);
} else {
this.props.onClose();
}
}
handleChange(e) {
console.log(e)
this.setState({ [e.target.id]: e.target.value });
}
resetState() {
this.setState({ name: '' });
this.setState({ value: '' });
}
validateForm(target) {
// check all controls
var name = true;
var inputGiven = true;
if (this.state.name === '') {
name = false;
if (this.state.value === '') {
inputGiven = false;
}
this.valid = name;
this.valid = inputGiven;
// return state to control
if (target === 'name') return name ? "success" : "error";
if (target === 'value') return inputGiven ? "success" : "error";
return "success";
}
@ -68,17 +66,18 @@ class NewDashboardDialog extends React.Component {
render() {
return (
<Dialog
size="md"
show={this.props.show}
title="New Dashboard"
title={this.props.title}
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.Group controlId="value" valid={this.validateForm('value')}>
<Form.Label>{this.props.inputLabel}</Form.Label>
<Form.Control type="text" placeholder={this.props.placeholder} value={this.state.value} onChange={(e) => this.handleChange(e)} />
<Form.Control.Feedback />
</Form.Group>
</Form>
@ -87,4 +86,4 @@ class NewDashboardDialog extends React.Component {
}
}
export default NewDashboardDialog;
export default NewDialog;

View file

@ -15,11 +15,12 @@
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React, {Component} from "react";
import React, { Component } from "react";
import FileSaver from 'file-saver';
import IconButton from "../common/icon-button";
import Table from "../common/table";
import TableColumn from "../common/table-column";
import NewDialog from "../common/dialogs/new-dialog";
import DeleteDialog from "../common/dialogs/delete-dialog";
import AppDispatcher from "../common/app-dispatcher";
import NotificationsDataManager from "../common/data-managers/notifications-data-manager";
@ -37,21 +38,21 @@ class ConfigTable extends Component {
editConfigModal: false,
modalConfigData: {},
modalConfigIndex: 0,
newConfigModal: false,
deleteConfigModal: false,
importConfigModal: false,
newConfig: false,
selectedConfigs: [],
ExternalICInUse: false,
editOutputSignalsModal: false,
editInputSignalsModal: false,
editOutputSignalsModal: false,
editInputSignalsModal: false,
}
}
static getDerivedStateFromProps(props, state){
static getDerivedStateFromProps(props, state) {
let ExternalICInUse = false
for (let config of props.configs){
for (let config of props.configs) {
for (let component of props.ics) {
if ((config.icID === component.id) && (component.managedexternally === true)) {
ExternalICInUse = true;
@ -65,26 +66,27 @@ class ConfigTable extends Component {
};
}
addConfig() {
const config = {
scenarioID: this.props.scenario.id,
name: 'New Component Configuration',
icID: this.props.ics.length > 0 ? this.props.ics[0].id : null,
startParameters: {},
};
closeNewConfigModal(data) {
this.setState({ newConfigModal: false });
AppDispatcher.dispatch({
type: 'configs/start-add',
data: config,
token: this.props.sessionToken
});
this.setState({ newConfig: true });
if (data) {
const config = {
scenarioID: this.props.scenario.id,
name: data.value,
icID: this.props.ics.length > 0 ? this.props.ics[0].id : null,
startParameters: {},
};
AppDispatcher.dispatch({
type: 'configs/start-add',
data: config,
token: this.props.sessionToken
});
}
}
closeEditConfigModal(data) {
this.setState({ editConfigModal: false, newConfig: false });
this.setState({ editConfigModal: false });
if (data) {
AppDispatcher.dispatch({
@ -312,27 +314,27 @@ class ConfigTable extends Component {
{/*Component Configurations table*/}
<h2 style={this.props.tableHeadingStyle}>Component Configurations
<span className='icon-button'>
<IconButton
childKey={0}
tooltip='Add Component Configuration'
onClick={() => this.addConfig()}
icon='plus'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
<IconButton
childKey={1}
tooltip='Import Component Configuration'
onClick={() => this.setState({ importConfigModal: true })}
icon='upload'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
<IconButton
childKey={0}
tooltip='Add Component Configuration'
onClick={() => this.setState({ newConfigModal: true })}
icon='plus'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
<IconButton
childKey={1}
tooltip='Import Component Configuration'
onClick={() => this.setState({ importConfigModal: true })}
icon='upload'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
</h2>
<Table data={this.props.configs}>
<TableColumn
@ -404,9 +406,9 @@ class ConfigTable extends Component {
<ICAction
ics={this.props.ics}
configs={this.props.configs}
selectedConfigs = {this.state.selectedConfigs}
snapshotConfig = {(index) => this.copyConfig(index)}
token = {this.props.sessionToken}
selectedConfigs={this.state.selectedConfigs}
snapshotConfig={(index) => this.copyConfig(index)}
token={this.props.sessionToken}
actions={[
{ id: '0', title: 'Start', data: { action: 'start' } },
{ id: '1', title: 'Stop', data: { action: 'stop' } },
@ -432,6 +434,13 @@ class ConfigTable extends Component {
onClose={data => this.importConfig(data)}
ics={this.props.ics}
/>
<NewDialog
show={this.state.newConfigModal}
title="New Component Configuration"
inputLabel="Name"
placeholder="Enter name"
onClose={data => this.closeNewConfigModal(data)}
/>
<DeleteDialog
title="component configuration"
name={this.state.modalConfigData.name}

View file

@ -20,11 +20,11 @@ import FileSaver from 'file-saver';
import IconButton from "../common/icon-button";
import Table from "../common/table";
import TableColumn from "../common/table-column";
import NewDashboardDialog from "./new-dashboard";
import EditDashboardDialog from "./edit-dashboard";
import ImportDashboardDialog from "./import-dashboard";
import DeleteDialog from "../common/dialogs/delete-dialog";
import AppDispatcher from "../common/app-dispatcher";
import NewDialog from "../common/dialogs/new-dialog";
class DashboardTable extends Component {
@ -43,15 +43,15 @@ class DashboardTable extends Component {
closeNewDashboardModal(data) {
this.setState({ newDashboardModal: false });
if (data) {
// TODO: 'newDashboard' not used, check this
let newDashboard = data;
let newDashboard = {};
newDashboard["name"] = data.value;
// add default grid value and scenarioID
newDashboard["grid"] = 15;
newDashboard["scenarioID"] = this.props.scenario.id;
AppDispatcher.dispatch({
type: 'dashboards/start-add',
data,
data: newDashboard,
token: this.props.sessionToken,
});
}
@ -218,10 +218,14 @@ class DashboardTable extends Component {
/>
</Table>
<NewDashboardDialog
<NewDialog
show={this.state.newDashboardModal}
title="New Dashboard"
inputLabel="Name"
placeholder="Enter name"
onClose={data => this.closeNewDashboardModal(data)}
/>
<EditDashboardDialog
show={this.state.dashboardEditModal}
dashboard={this.state.modalDashboardData}

View file

@ -1,77 +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 { Form } from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
class NewResultDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
ConfigSnapshots: '',
Description: '',
ResultFileIDs: [],
}
}
onClose(canceled) {
if (canceled === false) {
this.props.onClose(this.state);
} else {
this.props.onClose();
}
}
handleChange(e) {
this.setState({ [e.target.id]: e.target.value });
}
resetState() {
this.setState({
ConfigSnapshots: '',
Description: '',
ResultFileIDs: [],
});
}
render() {
return (
<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>
);
}
}
export default NewResultDialog;

View file

@ -26,7 +26,7 @@ import TableColumn from "../common/table-column";
import DeleteDialog from "../common/dialogs/delete-dialog";
import EditResultDialog from "./edit-result";
import ResultConfigDialog from "./result-configs-dialog";
import NewResultDialog from "./new-result";
import NewDialog from "../common/dialogs/new-dialog";
class ResultTable extends Component {
@ -79,10 +79,13 @@ class ResultTable extends Component {
closeNewResultModal(data) {
this.setState({ newResultModal: false });
if (data) {
data["scenarioID"] = this.props.scenario.id;
let newResult = { ConfigSnapshots: '', ResultFileIDs: [] };
newResult["scenarioID"] = this.props.scenario.id;
newResult["Description"] = data.value;
AppDispatcher.dispatch({
type: 'results/start-add',
data,
data: newResult,
token: this.props.sessionToken,
});
}
@ -245,8 +248,11 @@ class ResultTable extends Component {
resultNo={this.state.modalResultConfigsIndex}
onClose={this.closeResultConfigSnapshots.bind(this)}
/>
<NewResultDialog
<NewDialog
show={this.state.newResultModal}
title="New Result"
inputLabel="Description"
placeholder="Enter description"
onClose={data => this.closeNewResultModal(data)}
/>
</div>

View file

@ -0,0 +1,71 @@
/**
* 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 { Table } from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
class UsersToScenarioDialog extends React.Component {
valid = true;
onClose() {
if (this.props.onClose != null) {
this.props.onClose();
}
};
renderRow(value, key) {
return ( <tr>
<td>{key}</td>
<td>{value}</td>
</tr> );
}
renderData() {
let arr = [];
this.props.users.forEach((value, key) => {
arr.push(this.renderRow(value,key))
})
return arr;
}
render() {
return <Dialog
size='md'
show={this.props.show}
title={'Add to \'' + this.props.scenario + '\'?'}
buttonTitle='Confirm'
onClose={() => this.onClose()}
valid={true}
>
<Table size='sm' striped>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{ this.renderData() }
</tbody>
</Table>
</Dialog>;
}
}
export default UsersToScenarioDialog;

View file

@ -20,13 +20,16 @@ import { Container } from 'flux/utils';
import AppDispatcher from '../common/app-dispatcher';
import UsersStore from './users-store';
import ScenarioStore from '../scenario/scenario-store';
import Icon from '../common/icon';
import IconButton from '../common/icon-button';
import { Dropdown, DropdownButton } from 'react-bootstrap';
import Table from '../common/table';
import TableColumn from '../common/table-column';
import NewUserDialog from './new-user';
import EditUserDialog from './edit-user';
import UsersToScenarioDialog from './users-to-scenario';
import DeleteDialog from '../common/dialogs/delete-dialog';
import NotificationsDataManager from "../common/data-managers/notifications-data-manager";
@ -34,25 +37,25 @@ import NotificationsFactory from "../common/data-managers/notifications-factory"
class Users extends Component {
static getStores() {
return [ UsersStore ];
return [UsersStore, ScenarioStore];
}
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
if (!prevState && token) {
AppDispatcher.dispatch({
type: 'users/start-load',
token: token
});
if (prevState == null) {
prevState = {};
}
return {
token: token,
token: localStorage.getItem("token"),
users: UsersStore.getState(),
scenarios: ScenarioStore.getState(),
usersToAdd: prevState.usersToAdd || new Map(),
selectedScenarioID: prevState.selectedScenarioID || null,
selectedScenario: prevState.selectedScenario || '',
newModal: false,
addUsersModal: false,
editModal: false,
deleteModal: false,
modalData: {},
@ -60,6 +63,19 @@ class Users extends Component {
};
}
componentDidMount() {
AppDispatcher.dispatch({
type: 'scenarios/start-load',
token: this.state.token
});
AppDispatcher.dispatch({
type: 'users/start-load',
token: this.state.token
});
}
closeNewModal(data) {
this.setState({ newModal: false });
@ -102,14 +118,37 @@ class Users extends Component {
}
}
onModalKeyPress = (event) => {
if (event.key === 'Enter') {
event.preventDefault();
this.confirmDeleteModal();
onUserChecked(user) {
let temp = this.state.usersToAdd;
const found = temp.get(user.id);
if (!found) {
temp.set(user.id, user.username);
} else {
temp.delete(user.id)
}
this.setState({ usersToAdd: temp });
}
setScenario(ID) {
let scenarioID = parseInt(ID, 10)
let scenario = this.state.scenarios.find(s => s.id === scenarioID);
this.setState({ selectedScenarioID: scenario.id, selectedScenario: scenario.name, addUsersModal: true })
};
closeAddUsersModal() {
this.state.usersToAdd.forEach((value, key) => {
AppDispatcher.dispatch({
type: 'scenarios/add-user',
data: this.state.selectedScenarioID,
username: value,
token: this.state.token
});
})
this.setState({ addUsersModal: false, selectedScenarioID: null })
}
modifyActiveColumn(active) {
return <Icon icon={active ? 'check' : 'times'} />
}
@ -125,65 +164,91 @@ class Users extends Component {
}
return <div>
<h1>Users
<h1>Users
<span className='icon-button'>
<IconButton
childKey={0}
tooltip='Add User'
onClick={() => this.setState({ newModal: true })}
icon='plus'
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
</h1>
<IconButton
childKey={0}
tooltip='Add User'
onClick={() => this.setState({ newModal: true })}
icon='plus'
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
</h1>
<Table data={this.state.users}>
{this.state.currentUser.role === "Admin" ?
<TableColumn
title='ID'
dataKey='id'
/>
: <></>
}
<Table data={this.state.users}>
{this.state.currentUser.role === "Admin" ?
<TableColumn
title='Username'
width='150'
dataKey='username'
title='ID'
dataKey='id'
/>
: <></>
}
{this.state.currentUser.role === "Admin" ?
<TableColumn
title='E-mail'
dataKey='mail'
title='Add'
checkbox
onChecked={(index, event) => this.onUserChecked(index, event)}
checkboxKey='checked'
width='30'
/>
<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>
: <></>
}
<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>
<span className='solid-button'>
<DropdownButton
title='Add to Scenario'
onSelect={(id) => this.setScenario(id)}
>
{this.state.scenarios.map(scenario => (
<Dropdown.Item key={scenario.id} eventKey={scenario.id}>{scenario.name}</Dropdown.Item>
))}
</DropdownButton>
</span>
<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>;
<UsersToScenarioDialog
show={this.state.addUsersModal}
users={this.state.usersToAdd}
scenario={this.state.selectedScenario}
onClose={() => this.closeAddUsersModal()}
/>
<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>;
}
}