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

modularize scenario.js file #270

This commit is contained in:
Sonja Happ 2021-03-19 16:40:54 +01:00
parent a4ca694b47
commit eaefeeb310
5 changed files with 1142 additions and 995 deletions

View file

@ -0,0 +1,434 @@
/**
* 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, {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 DeleteDialog from "../common/dialogs/delete-dialog";
import AppDispatcher from "../common/app-dispatcher";
import NotificationsDataManager from "../common/data-managers/notifications-data-manager";
import ICAction from "../ic/ic-action";
import EditConfigDialog from "./edit-config";
import ImportConfigDialog from "./import-config";
import EditSignalMappingDialog from "../signal/edit-signal-mapping";
class ConfigTable extends Component {
constructor() {
super();
this.state = {
editConfigModal: false,
modalConfigData: {},
modalConfigIndex: 0,
deleteConfigModal: false,
importConfigModal: false,
newConfig: false,
selectedConfigs: [],
ExternalICInUse: false,
editOutputSignalsModal: false,
editInputSignalsModal: false,
}
}
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: {},
};
AppDispatcher.dispatch({
type: 'configs/start-add',
data: config,
token: this.props.sessionToken
});
this.setState({ newConfig: true });
}
closeEditConfigModal(data) {
this.setState({ editConfigModal: false, newConfig: false });
if (data) {
AppDispatcher.dispatch({
type: 'configs/start-edit',
data: data,
token: this.props.sessionToken,
});
}
}
closeDeleteConfigModal(confirmDelete) {
this.setState({ deleteConfigModal: false });
if (confirmDelete === false) {
return;
}
AppDispatcher.dispatch({
type: 'configs/start-remove',
data: this.state.modalConfigData,
token: this.props.sessionToken
});
}
importConfig(data) {
this.setState({ importConfigModal: false });
if (data == null) {
return;
}
let newConfig = JSON.parse(JSON.stringify(data.config))
newConfig["scenarioID"] = this.props.scenario.id;
newConfig.name = data.name;
AppDispatcher.dispatch({
type: 'configs/start-add',
data: newConfig,
token: this.props.sessionToken
});
}
copyConfig(index) {
let config = JSON.parse(JSON.stringify(this.props.configs[index]));
let signals = JSON.parse(JSON.stringify(this.props.signals.filter(s => s.configID === parseInt(config.id, 10))));
signals.forEach((signal) => {
delete signal.configID;
delete signal.id;
})
// two separate lists for inputMapping and outputMapping
let inputSignals = signals.filter(s => s.direction === 'in');
let outputSignals = signals.filter(s => s.direction === 'out');
// add signal mappings to config
config["inputMapping"] = inputSignals;
config["outputMapping"] = outputSignals;
delete config.id;
delete config.scenarioID;
delete config.inputLength;
delete config.outputLength;
return config;
}
exportConfig(index) {
let config = this.copyConfig(index);
// show save dialog
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
FileSaver.saveAs(blob, 'config-' + config.name + '.json');
}
duplicateConfig(index) {
let newConfig = this.copyConfig(index);
newConfig["scenarioID"] = this.props.scenario.id;
newConfig.name = newConfig.name + '_copy';
AppDispatcher.dispatch({
type: 'configs/start-add',
data: newConfig,
token: this.props.sessionToken
});
}
onConfigChecked(index, event) {
const selectedConfigs = Object.assign([], this.state.selectedConfigs);
for (let key in selectedConfigs) {
if (selectedConfigs[key] === index) {
// update existing entry
if (event.target.checked) {
return;
}
selectedConfigs.splice(key, 1);
this.setState({ selectedConfigs: selectedConfigs });
return;
}
}
// add new entry
if (event.target.checked === false) {
return;
}
selectedConfigs.push(index);
this.setState({ selectedConfigs: selectedConfigs });
}
usesExternalIC(index) {
let icID = this.props.configs[index].icID;
let ic = null;
for (let component of this.props.ics) {
if (component.id === icID) {
ic = component;
}
}
if (ic == null) {
return false;
}
if (ic.managedexternally === true) {
this.setState({ ExternalICInUse: true })
return true
}
return false
}
getICName(icID) {
for (let ic of this.props.ics) {
if (ic.id === icID) {
return ic.name || ic.uuid;
}
}
}
/* ##############################################
* Signal modification methods
############################################## */
closeEditSignalsModal(direction) {
// reload the config
AppDispatcher.dispatch({
type: 'configs/start-load',
data: this.state.modalConfigData.id,
token: this.props.sessionToken
});
if (direction === "in") {
this.setState({ editInputSignalsModal: false });
} else if (direction === "out") {
this.setState({ editOutputSignalsModal: false });
}
}
signalsAutoConf(index) {
let componentConfig = this.props.configs[index];
// determine apiurl of infrastructure component
let ic = this.props.ics.find(ic => ic.id === componentConfig.icID)
if (!ic.type.includes("villas-node")) {
let message = "Cannot autoconfigure signals for IC type " + ic.type + " of category " + ic.category + ". This is only possible for gateway ICs of type 'VILLASnode'."
console.warn(message);
const SIGNAL_AUTOCONF_WARN_NOTIFICATION = {
title: 'Failed to load signal config for IC ' + ic.name,
message: message,
level: 'warning'
};
NotificationsDataManager.addNotification(SIGNAL_AUTOCONF_WARN_NOTIFICATION);
return;
}
let splitWebsocketURL = ic.websocketurl.split("/")
AppDispatcher.dispatch({
type: 'signals/start-autoconfig',
url: ic.apiurl + "/nodes",
socketname: splitWebsocketURL[splitWebsocketURL.length - 1],
token: this.props.sessionToken,
configID: componentConfig.id
});
}
startPintura(configIndex) {
let config = this.props.configs[configIndex];
// get xml / CIM file
let files = []
for (let id of config.fileIDs) {
for (let file of this.props.files) {
if (file.id === id && ['xml'].some(e => file.type.includes(e))) {
files.push(file);
}
}
}
if (files.length > 1) {
// more than one CIM file...
console.warn("There is more than one CIM file selected in this component configuration. I will open them all in a separate tab.")
}
let baseURL = 'aaa.bbb.ccc.ddd/api/v2/files/'
for (let file of files) {
// endpoint param serves for download and upload of CIM file, token is required for authentication
let params = {
token: this.props.sessionToken,
endpoint: baseURL + String(file.id),
}
// TODO start Pintura for editing CIM/ XML file from here
console.warn("Starting Pintura... and nothing happens so far :-) ", params)
}
}
render() {
return (
<div>
{/*Component Configurations table*/}
<h2 style={this.props.tableHeadingStyle}>Component Configurations
<span className='icon-button'>
<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.props.configs}>
<TableColumn
checkbox
checkboxDisabled={(index) => !this.usesExternalIC(index)}
onChecked={(index, event) => this.onConfigChecked(index, event)}
width={20}
/>
{this.props.currentUser.role === "Admin" ?
<TableColumn
title='ID'
dataKey='id'
width={70}
/>
: <></>
}
<TableColumn
title='Name'
dataKey='name'
width={250}
/>
<TableColumn
title='# Output Signals'
dataKey='outputLength'
editButton
onEdit={index => this.setState({ editOutputSignalsModal: true, modalConfigData: this.props.configs[index], modalConfigIndex: index })}
width={150}
/>
<TableColumn
title='# Input Signals'
dataKey='inputLength'
editButton
onEdit={index => this.setState({ editInputSignalsModal: true, modalConfigData: this.props.configs[index], modalConfigIndex: index })}
width={150}
/>
<TableColumn
title='Import Signals'
exportButton
onExport={(index) => this.signalsAutoConf(index)}
width={150}
/>
<TableColumn
title='Infrastructure Component'
dataKey='icID'
modifier={(icID) => this.getICName(icID)}
width={200}
/>
<TableColumn
title=''
width={200}
align='right'
editButton
deleteButton
exportButton
duplicateButton
onEdit={index => this.setState({ editConfigModal: true, modalConfigData: this.props.configs[index], modalConfigIndex: index })}
onDelete={(index) => this.setState({ deleteConfigModal: true, modalConfigData: this.props.configs[index], modalConfigIndex: index })}
onExport={index => this.exportConfig(index)}
onDuplicate={index => this.duplicateConfig(index)}
/>
</Table>
{this.state.ExternalICInUse ?
<div style={{ float: 'left' }}>
<ICAction
ics={this.props.ics}
configs={this.props.configs}
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' } },
{ id: '2', title: 'Pause', data: { action: 'pause' } },
{ id: '3', title: 'Resume', data: { action: 'resume' } }
]} />
</div>
: <div />
}
<div style={{ clear: 'both' }} />
<EditConfigDialog
show={this.state.editConfigModal}
onClose={data => this.closeEditConfigModal(data)}
config={this.state.modalConfigData}
ics={this.props.ics}
files={this.props.files}
sessionToken={this.props.sessionToken}
/>
<ImportConfigDialog
show={this.state.importConfigModal}
onClose={data => this.importConfig(data)}
ics={this.props.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"
signals={this.props.signals}
configID={this.state.modalConfigData.id}
sessionToken={this.props.sessionToken}
/>
<EditSignalMappingDialog
show={this.state.editInputSignalsModal}
onCloseEdit={(direction) => this.closeEditSignalsModal(direction)}
direction="Input"
signals={this.props.signals}
configID={this.state.modalConfigData.id}
sessionToken={this.props.sessionToken}
/>
</div>
)
}
}
export default ConfigTable;

View file

@ -0,0 +1,229 @@
/**
* 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, {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 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";
class DashboardTable extends Component {
constructor() {
super();
this.state = {
newDashboardModal: false,
deleteDashboardModal: false,
importDashboardModal: false,
modalDashboardData: {},
dashboardEditModal: false,
}
}
closeNewDashboardModal(data) {
this.setState({ newDashboardModal: false });
if (data) {
// TODO: 'newDashboard' not used, check this
let newDashboard = data;
// add default grid value and scenarioID
newDashboard["grid"] = 15;
newDashboard["scenarioID"] = this.props.scenario.id;
AppDispatcher.dispatch({
type: 'dashboards/start-add',
data,
token: this.props.sessionToken,
});
}
}
closeEditDashboardModal(data) {
this.setState({ dashboardEditModal: false });
let editDashboard = this.state.modalDashboardData;
if (data != null) {
editDashboard.name = data.name;
AppDispatcher.dispatch({
type: 'dashboards/start-edit',
data: editDashboard,
token: this.props.sessionToken
});
}
}
closeDeleteDashboardModal(confirmDelete) {
this.setState({ deleteDashboardModal: false });
if (confirmDelete === false) {
return;
}
AppDispatcher.dispatch({
type: 'dashboards/start-remove',
data: this.state.modalDashboardData,
token: this.props.sessionToken,
});
}
closeImportDashboardModal(data) {
this.setState({ importDashboardModal: false });
if (data) {
let newDashboard = JSON.parse(JSON.stringify(data));
newDashboard["scenarioID"] = this.props.scenario.id;
AppDispatcher.dispatch({
type: 'dashboards/start-add',
data: newDashboard,
token: this.props.sessionToken,
});
}
}
copyDashboard(index) {
let dashboard = JSON.parse(JSON.stringify(this.props.dashboards[index]));
let widgets = JSON.parse(JSON.stringify(this.props.widgets.filter(w => w.dashboardID === parseInt(dashboard.id, 10))));
widgets.forEach((widget) => {
delete widget.dashboardID;
delete widget.id;
})
dashboard["widgets"] = widgets;
delete dashboard.scenarioID;
delete dashboard.id;
return dashboard;
}
exportDashboard(index) {
let dashboard = this.copyDashboard(index);
// show save dialog
const blob = new Blob([JSON.stringify(dashboard, null, 2)], { type: 'application/json' });
FileSaver.saveAs(blob, 'dashboard - ' + dashboard.name + '.json');
}
duplicateDashboard(index) {
let newDashboard = this.copyDashboard(index);
newDashboard.scenarioID = this.props.scenario.id;
newDashboard.name = newDashboard.name + '_copy';
AppDispatcher.dispatch({
type: 'dashboards/start-add',
data: newDashboard,
token: this.props.sessionToken,
});
}
render() {
return (
<div>
{/*Dashboard table*/}
<h2 style={this.props.tableHeadingStyle}>Dashboards
<span className='icon-button'>
<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.props.dashboards}>
{this.props.currentUser.role === "Admin" ?
<TableColumn
title='ID'
dataKey='id'
width={70}
/>
: <></>
}
<TableColumn
title='Name'
dataKey='name'
link='/dashboards/'
linkKey='id'
width={300}
/>
<TableColumn
title='Grid'
dataKey='grid'
width={100}
/>
<TableColumn
title=''
width={200}
align='right'
editButton
deleteButton
exportButton
duplicateButton
onEdit={index => this.setState({
dashboardEditModal: true,
modalDashboardData: this.props.dashboards[index]
})}
onDelete={(index) => this.setState({
deleteDashboardModal: true,
modalDashboardData: this.props.dashboards[index],
modalDashboardIndex: index
})}
onExport={index => this.exportDashboard(index)}
onDuplicate={index => this.duplicateDashboard(index)}
/>
</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)}
/>
</div>
)
}
}
export default DashboardTable;

244
src/result/result-table.js Normal file
View file

@ -0,0 +1,244 @@
/**
* 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, {Component} from "react";
import JSZip from 'jszip';
import {Button} from "react-bootstrap";
import FileSaver from 'file-saver';
import AppDispatcher from "../common/app-dispatcher";
import IconButton from "../common/icon-button";
import Table from "../common/table";
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";
class ResultTable extends Component {
constructor() {
super();
this.state = {
editResultsModal: false,
modalResultsData: {},
modalResultsIndex: 0,
newResultModal: false,
filesToDownload: [],
zipfiles: false,
resultNodl: 0,
resultConfigsModal: false,
modalResultConfigs: {},
modalResultConfigsIndex: 0,
}
}
componentDidUpdate(prevProps, prevState) {
// check whether file data has been loaded
if (this.state.filesToDownload && this.state.filesToDownload.length > 0) {
if (this.props.files !== prevProps.files) {
if (!this.state.zipfiles) {
let fileToDownload = this.props.files.filter(file => file.id === this.state.filesToDownload[0])
if (fileToDownload.length === 1 && fileToDownload[0].data) {
const blob = new Blob([fileToDownload[0].data], { type: fileToDownload[0].type });
FileSaver.saveAs(blob, fileToDownload[0].name);
this.setState({ filesToDownload: [] });
}
} else { // zip and save one or more files (download all button)
let filesToDownload = this.props.files.filter(file => this.state.filesToDownload.includes(file.id) && file.data);
if (filesToDownload.length === this.state.filesToDownload.length) { // all requested files have been loaded
var zip = new JSZip();
filesToDownload.forEach(file => {
zip.file(file.name, file.data);
});
let zipname = "result_" + this.state.resultNodl + "_" + (new Date()).toISOString();
zip.generateAsync({ type: "blob" }).then(function (content) {
saveAs(content, zipname);
});
this.setState({ filesToDownload: [] });
}
}
}
}
}
closeNewResultModal(data) {
this.setState({ newResultModal: false });
if (data) {
data["scenarioID"] = this.props.scenario.id;
AppDispatcher.dispatch({
type: 'results/start-add',
data,
token: this.props.sessionToken,
});
}
}
closeEditResultsModal() {
this.setState({ editResultsModal: false });
}
downloadResultData(param) {
let toDownload = [];
let zip = false;
if (typeof (param) === 'object') { // download all files
toDownload = param.resultFileIDs;
zip = true;
this.setState({ filesToDownload: toDownload, zipfiles: zip, resultNodl: param.id });
} else { // download one file
toDownload.push(param);
this.setState({ filesToDownload: toDownload, zipfiles: zip });
}
toDownload.forEach(fileid => {
AppDispatcher.dispatch({
type: 'files/start-download',
data: fileid,
token: this.props.sessionToken
});
});
}
closeDeleteResultsModal(confirmDelete) {
this.setState({ deleteResultsModal: false });
if (confirmDelete === false) {
return;
}
AppDispatcher.dispatch({
type: 'results/start-remove',
data: this.state.modalResultsData,
token: this.props.sessionToken,
});
}
openResultConfigSnapshots(result) {
if (result.configSnapshots === null || result.configSnapshots === undefined) {
this.setState({
modalResultConfigs: {"configs": []},
modalResultConfigsIndex: result.id,
resultConfigsModal: true
});
} else {
this.setState({
modalResultConfigs: result.configSnapshots,
modalResultConfigsIndex: result.id,
resultConfigsModal: true
});
}
}
closeResultConfigSnapshots() {
this.setState({ resultConfigsModal: false });
}
modifyResultNoColumn(id, result) {
return <Button variant="link" style={{ color: '#047cab' }} onClick={() => this.openResultConfigSnapshots(result)}>{id}</Button>
}
render() {
return (
<div>
{/*Result table*/}
<h2 style={this.props.tableHeadingStyle}>Results
<span className='icon-button'>
<IconButton
key={1}
tooltip='Add Result'
onClick={() => this.setState({ newResultModal: true })}
icon='plus'
/>
</span>
</h2>
<Table data={this.props.results}>
<TableColumn
title='ID'
dataKey='id'
modifier={(id, result) => this.modifyResultNoColumn(id, result)}
width={70}
/>
<TableColumn
title='Description'
dataKey='description'
width={300}
/>
<TableColumn
title='Created at'
dataKey='createdAt'
width={200}
/>
<TableColumn
title='Last update'
dataKey='updatedAt'
width={200}
/>
<TableColumn
title='Files'
dataKey='resultFileIDs'
linkKey='filebuttons'
data={this.props.files}
onDownload={(index) => this.downloadResultData(index)}
width={300}
/>
<TableColumn
width={200}
align='right'
editButton
downloadAllButton
deleteButton
onEdit={index => this.setState({ editResultsModal: true, modalResultsIndex: index })}
onDownloadAll={(index) => this.downloadResultData(this.props.results[index])}
onDelete={(index) => this.setState({ deleteResultsModal: true, modalResultsData: this.props.results[index], modalResultsIndex: index })}
/>
</Table>
<EditResultDialog
sessionToken={this.props.sessionToken}
show={this.state.editResultsModal}
files={this.props.files}
results={this.props.results}
resultId={this.state.modalResultsIndex}
scenarioID={this.props.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)}
/>
</div>
)
}
}
export default ResultTable;

View file

@ -0,0 +1,169 @@
/**
* 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, {Component} from "react";
import {Button, Form, InputGroup} from "react-bootstrap";
import {Redirect} from "react-router-dom";
import Table from "../common/table";
import TableColumn from "../common/table-column";
import Icon from "../common/icon";
import DeleteDialog from "../common/dialogs/delete-dialog";
import AppDispatcher from "../common/app-dispatcher";
class ScenarioUsersTable extends Component {
constructor(props) {
super(props);
this.state = {
userToAdd: '',
deleteUserName: '',
deleteUserModal: false,
goToScenarios: false
}
}
onUserInputChange(e) {
this.setState({ userToAdd: e.target.value });
}
addUser() {
AppDispatcher.dispatch({
type: 'scenarios/add-user',
data: this.props.scenario.id,
username: this.state.userToAdd,
token: this.props.sessionToken
});
this.setState({ userToAdd: '' });
}
closeDeleteUserModal() {
let scenarioID = this.props.scenario.id;
if (this.state.deleteUserName === this.props.currentUser.username) {
AppDispatcher.dispatch({
type: 'scenarios/remove-user',
data: scenarioID,
username: this.state.deleteUserName,
token: this.props.sessionToken,
ownuser: true
});
this.setState({ goToScenarios: true });
} else {
AppDispatcher.dispatch({
type: 'scenarios/remove-user',
data: scenarioID,
username: this.state.deleteUserName,
token: this.props.sessionToken,
ownuser: false
});
}
this.setState({ deleteUserModal: false });
}
render() {
if (this.state.goToScenarios) {
console.log("redirect to scenario overview")
return (<Redirect to="/scenarios" />);
}
const altButtonStyle = {
marginLeft: '10px',
}
const iconStyle = {
height: '30px',
width: '30px'
}
return (
<div>
{/*Scenario Users table*/}
<h2 style={this.props.tableHeadingStyle}>Users sharing this scenario</h2>
<Table data={this.props.scenario.users}>
{this.props.currentUser.role === "Admin" ?
<TableColumn
title='ID'
dataKey='id'
width={70}
/>
: <></>
}
<TableColumn
title='Name'
dataKey='username'
width={300}
/>
<TableColumn
title='Role'
dataKey='role'
width={100}
/>
<TableColumn
title=''
width={30}
align='right'
deleteButton
onDelete={(index) => this.setState({
deleteUserModal: true,
deleteUserName: this.props.scenario.users[index].username,
modalUserIndex: index
})}
/>
</Table>
<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'
type="submit"
style={altButtonStyle}
onClick={() => this.addUser()}>
<Icon icon="plus" classname={'icon-color'} style={iconStyle} />
</Button>
</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>
)
}
}
export default ScenarioUsersTable;

File diff suppressed because it is too large Load diff