mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Add plot-table widget
Bug: Width of plot in new widget is not correct resized
This commit is contained in:
parent
5bf9ad9f8d
commit
73a576ab88
5 changed files with 205 additions and 62 deletions
|
@ -19,7 +19,8 @@ class TableColumn extends Component {
|
|||
link: '/',
|
||||
linkKey: '',
|
||||
dataIndex: false,
|
||||
inlineEditable: false
|
||||
inlineEditable: false,
|
||||
clickable: false
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -11,13 +11,14 @@ import React, { Component } from 'react';
|
|||
import { Table, Button, Glyphicon, FormControl } from 'react-bootstrap';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import TableColumn from './table-column';
|
||||
//import TableColumn from './table-column';
|
||||
|
||||
class CustomTable extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
rows: [],
|
||||
editCell: [ -1, -1 ]
|
||||
};
|
||||
}
|
||||
|
@ -30,78 +31,97 @@ class CustomTable extends Component {
|
|||
this.setState({ editCell: [ column, row ]}); // x, y
|
||||
}
|
||||
|
||||
addCell(data, index, child) {
|
||||
// add data to cell
|
||||
const dataKey = child.props.dataKey;
|
||||
var cell = [];
|
||||
|
||||
if (dataKey && data[dataKey] != null) {
|
||||
// get content
|
||||
var content;
|
||||
const modifier = child.props.modifier;
|
||||
|
||||
if (modifier) {
|
||||
content = modifier(data[dataKey]);
|
||||
} else {
|
||||
content = data[dataKey].toString();
|
||||
}
|
||||
|
||||
// check if cell should be a link
|
||||
const linkKey = child.props.linkKey;
|
||||
if (linkKey && data[linkKey] != null) {
|
||||
cell.push(<Link to={child.props.link + data[linkKey]}>{content}</Link>);
|
||||
} else if (child.props.clickable) {
|
||||
cell.push(<a onClick={() => child.props.onClick(index)}>{content}</a>);
|
||||
} else {
|
||||
cell.push(content);
|
||||
}
|
||||
}
|
||||
|
||||
if (child.props.dataIndex) {
|
||||
cell.push(index);
|
||||
}
|
||||
|
||||
// add buttons
|
||||
if (child.props.editButton) {
|
||||
cell.push(<Button bsClass='table-control-button' onClick={() => child.props.onEdit(index)}><Glyphicon glyph='pencil' /></Button>);
|
||||
}
|
||||
|
||||
if (child.props.deleteButton) {
|
||||
cell.push(<Button bsClass='table-control-button' onClick={() => child.props.onDelete(index)}><Glyphicon glyph='remove' /></Button>);
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// check if data exists
|
||||
if (nextProps.data == null) {
|
||||
this.setState({ rows: [] });
|
||||
return;
|
||||
}
|
||||
|
||||
// create row data
|
||||
var rows = nextProps.data.map((data, index) => {
|
||||
// check if multiple columns
|
||||
if (Array.isArray(nextProps.children)) {
|
||||
var row = [];
|
||||
|
||||
nextProps.children.forEach(child => {
|
||||
row.push(this.addCell(data, index, child));
|
||||
});
|
||||
|
||||
return row;
|
||||
} else {
|
||||
// table only has a single column
|
||||
return [ this.addCell(data, index, nextProps.children) ];
|
||||
}
|
||||
});
|
||||
|
||||
this.setState({ rows: rows });
|
||||
}
|
||||
|
||||
render() {
|
||||
// create sorted data for rows
|
||||
var rows = [];
|
||||
if (this.props.data) {
|
||||
rows = this.props.data.map((row, index) => {
|
||||
var array = [];
|
||||
|
||||
for (var i = 0; i < this.props.children.length; i++) {
|
||||
// only handle table-column children
|
||||
if (this.props.children[i].type === TableColumn) {
|
||||
// add content to cell
|
||||
var cell = [];
|
||||
|
||||
// add data to cell
|
||||
const dataKey = this.props.children[i].props.dataKey;
|
||||
if (dataKey && row[dataKey] != null) {
|
||||
// get content
|
||||
var content;
|
||||
const modifier = this.props.children[i].props.modifier;
|
||||
|
||||
if (modifier) {
|
||||
content = modifier(row[dataKey]);
|
||||
} else {
|
||||
content = row[dataKey].toString();
|
||||
}
|
||||
|
||||
// check if cell should be a link
|
||||
const linkKey = this.props.children[i].props.linkKey;
|
||||
if (linkKey && row[linkKey] != null) {
|
||||
cell.push(<Link to={this.props.children[i].props.link + row[linkKey]}>{content}</Link>);
|
||||
} else {
|
||||
cell.push(content);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.props.children[i].props.dataIndex) {
|
||||
cell.push(index);
|
||||
}
|
||||
|
||||
// add buttons
|
||||
if (this.props.children[i].props.editButton) {
|
||||
const onEdit = this.props.children[i].props.onEdit;
|
||||
cell.push(<Button bsClass='table-control-button' onClick={() => onEdit(index)}><Glyphicon glyph='pencil' /></Button>);
|
||||
}
|
||||
|
||||
if (this.props.children[i].props.deleteButton) {
|
||||
const onDelete = this.props.children[i].props.onDelete;
|
||||
cell.push(<Button bsClass='table-control-button' onClick={() => onDelete(index)}><Glyphicon glyph='remove' /></Button>);
|
||||
}
|
||||
|
||||
array.push(cell);
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
});
|
||||
// get children
|
||||
var children = this.props.children;
|
||||
if (Array.isArray(this.props.children) === false) {
|
||||
children = [ children ];
|
||||
}
|
||||
|
||||
return (
|
||||
<Table width={this.props.width} striped hover>
|
||||
<Table style={{ width: this.props.width}} striped hover bordered>
|
||||
<thead>
|
||||
<tr>
|
||||
{this.props.children}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((row, rowIndex) => (
|
||||
{this.state.rows.map((row, rowIndex) => (
|
||||
<tr key={rowIndex}>
|
||||
{row.map((cell, cellIndex) => (
|
||||
<td key={cellIndex} onClick={this.props.children[cellIndex].props.inlineEditable === true ? (event) => this.onClick(event, rowIndex, cellIndex) : () => {}}>
|
||||
<td key={cellIndex} onClick={children[cellIndex].props.inlineEditable === true ? (event) => this.onClick(event, rowIndex, cellIndex) : () => {}}>
|
||||
{(this.state.editCell[0] === cellIndex && this.state.editCell[1] === rowIndex ) ? (
|
||||
<FormControl type="text" value={cell} onChange={(event) => this.props.children[cellIndex].props.onInlineChange(event, rowIndex, cellIndex)} />
|
||||
<FormControl type="text" value={cell} onChange={(event) => children[cellIndex].props.onInlineChange(event, rowIndex, cellIndex)} />
|
||||
) : (
|
||||
<span>
|
||||
{cell.map((element, elementIndex) => (
|
||||
|
|
112
src/components/widget-plot-table.js
Normal file
112
src/components/widget-plot-table.js
Normal file
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* File: widget-plot-table.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* Date: 15.03.2017
|
||||
* Copyright: 2017, Institute for Automation of Complex Power Systems, EONERC
|
||||
* This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential.
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
**********************************************************************************/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { LineChart } from 'rd3';
|
||||
import { Col } from 'react-bootstrap';
|
||||
|
||||
import Table from './table';
|
||||
import TableColumn from './table-column';
|
||||
|
||||
class WidgetPlotTable extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
signal: 0,
|
||||
firstTimestamp: 0,
|
||||
latestTimestamp: 0,
|
||||
sequence: null,
|
||||
rows: [],
|
||||
values: []
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// check data
|
||||
const simulator = nextProps.widget.simulator;
|
||||
|
||||
if (nextProps.simulation == null || nextProps.data == null || nextProps.data[simulator] == null || nextProps.data[simulator].length === 0 || nextProps.data[simulator].values[0].length === 0) {
|
||||
// clear values
|
||||
this.setState({ values: [], sequence: null, rows: [] });
|
||||
return;
|
||||
}
|
||||
|
||||
// check if new data, otherwise skip
|
||||
if (this.state.sequence >= nextProps.data[simulator].sequence) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get simulation model
|
||||
const simulationModel = nextProps.simulation.models.find((model) => {
|
||||
return (model.simulator === simulator);
|
||||
});
|
||||
|
||||
// get rows
|
||||
var rows = [];
|
||||
|
||||
simulationModel.mapping.forEach((signal) => {
|
||||
rows.push({ name: signal.name })
|
||||
});
|
||||
|
||||
// get timestamps
|
||||
var latestTimestamp = nextProps.data[simulator].values[0][nextProps.data[simulator].values[0].length - 1].x;
|
||||
var firstTimestamp = latestTimestamp - nextProps.widget.time * 1000;
|
||||
var firstIndex;
|
||||
|
||||
if (nextProps.data[simulator].values[0][0].x < firstTimestamp) {
|
||||
// find element index representing firstTimestamp
|
||||
firstIndex = nextProps.data[simulator].values[0].findIndex((value) => {
|
||||
return value.x >= firstTimestamp;
|
||||
});
|
||||
} else {
|
||||
firstIndex = 0;
|
||||
firstTimestamp = nextProps.data[simulator].values[0][0].x;
|
||||
latestTimestamp = firstTimestamp + nextProps.widget.time * 1000;
|
||||
}
|
||||
|
||||
// copy all values for each signal in time region
|
||||
var values = [{
|
||||
values: nextProps.data[simulator].values[this.state.signal].slice(firstIndex, nextProps.data[simulator].values[this.state.signal].length - 1)
|
||||
}];
|
||||
|
||||
this.setState({ values: values, firstTimestamp: firstTimestamp, latestTimestamp: latestTimestamp, sequence: nextProps.data[simulator].sequence, rows: rows });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ width: '100%', height: '100%' }} ref="wrapper">
|
||||
<h4>{this.props.widget.name}</h4>
|
||||
|
||||
<Col xs={3}>
|
||||
<Table data={this.state.rows}>
|
||||
<TableColumn title="Signal" dataKey="name" clickable onClick={(index) => this.setState({ signal: index }) } />
|
||||
</Table>
|
||||
</Col>
|
||||
|
||||
<Col xs={4}>
|
||||
{this.state.sequence &&
|
||||
<LineChart
|
||||
width={400}
|
||||
height={this.props.widget.height - 20}
|
||||
data={this.state.values}
|
||||
gridHorizontal={true}
|
||||
xAccessor={(d) => { if (d != null) { return new Date(d.x); } }}
|
||||
hoverAnimation={false}
|
||||
circleRadius={0}
|
||||
domain={{ x: [this.state.firstTimestamp, this.state.latestTimestamp] }}
|
||||
/>
|
||||
}
|
||||
</Col>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default WidgetPlotTable;
|
|
@ -118,7 +118,7 @@ class Visualization extends Component {
|
|||
} else if (item.name === 'Plot') {
|
||||
widget.simulator = this.state.simulation.models[0].simulator;
|
||||
widget.signals = [ 0 ];
|
||||
widget.time = 300;
|
||||
widget.time = 60;
|
||||
widget.width = 400;
|
||||
widget.height = 200;
|
||||
} else if (item.name === 'Table') {
|
||||
|
@ -127,6 +127,11 @@ class Visualization extends Component {
|
|||
widget.height = 200;
|
||||
} else if (item.name === 'Label') {
|
||||
|
||||
} else if (item.name === 'PlotTable') {
|
||||
widget.simulator = this.state.simulation.models[0].simulator;
|
||||
widget.width = 500;
|
||||
widget.height = 400;
|
||||
widget.time = 60
|
||||
}
|
||||
|
||||
var visualization = this.state.visualization;
|
||||
|
@ -276,6 +281,7 @@ class Visualization extends Component {
|
|||
<ToolboxItem name="Table" type="widget" />
|
||||
<ToolboxItem name="Label" type="widget" />
|
||||
<ToolboxItem name="Image" type="widget" disabled />
|
||||
<ToolboxItem name="PlotTable" type="widget" />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import WidgetValue from '../components/widget-value';
|
|||
import WidgetPlot from '../components/widget-plot';
|
||||
import WidgetTable from '../components/widget-table';
|
||||
import WidgetLabel from '../components/widget-label';
|
||||
import WidgetPlotTable from '../components/widget-plot-table';
|
||||
|
||||
import '../styles/widgets.css';
|
||||
|
||||
|
@ -83,6 +84,7 @@ class Widget extends Component {
|
|||
const widget = this.props.data;
|
||||
var element = null;
|
||||
|
||||
// dummy is passed to widgets to keep updating them while in edit mode
|
||||
if (widget.type === 'Value') {
|
||||
element = <WidgetValue widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulation={this.props.simulation} />
|
||||
} else if (widget.type === 'Plot') {
|
||||
|
@ -91,6 +93,8 @@ class Widget extends Component {
|
|||
element = <WidgetTable widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulation={this.props.simulation} />
|
||||
} else if (widget.type === 'Label') {
|
||||
element = <WidgetLabel widget={widget} />
|
||||
} else if (widget.type === 'PlotTable') {
|
||||
element = <WidgetPlotTable widget={widget} data={this.state.simulatorData} dummy={this.state.sequence} simulation={this.props.simulation} />
|
||||
}
|
||||
|
||||
if (this.props.editing) {
|
||||
|
|
Loading…
Add table
Reference in a new issue