Aufgrund einer Wartung wird GitLab am 17.08. zwischen 8:30 und 9:00 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to maintenance, GitLab will be temporarily unavailable on 17.08. between 8:30 and 9:00 am.

Commit a7ca4d45 authored by Sonja Happ's avatar Sonja Happ

display signals with PlotTable widget #218

parent c1b513cd
...@@ -80,7 +80,7 @@ class Plot extends React.Component { ...@@ -80,7 +80,7 @@ class Plot extends React.Component {
} }
// check if data is invalid // check if data is invalid
if (props.data == null || props.data.length === 0 || props.data[0].length === 0) { if (props.data == null || props.data.length === 0) {
// create empty plot axes // create empty plot axes
let xScale; let xScale;
let yScale; let yScale;
...@@ -116,11 +116,14 @@ class Plot extends React.Component { ...@@ -116,11 +116,14 @@ class Plot extends React.Component {
// only show data in requested time // only show data in requested time
let data = props.data; let data = props.data;
let icDataset = data.find(function(element) {
return element !== undefined;
})
const firstTimestamp = data[0][data[0].length - 1].x - (props.time + 1) * 1000; const firstTimestamp = icDataset[icDataset.length - 1].x - (props.time + 1) * 1000;
if (data[0][0].x < firstTimestamp) { if (icDataset[0].x < firstTimestamp) {
// only show data in range (+100 ms) // only show data in range (+100 ms)
const index = data[0].findIndex(value => value.x >= firstTimestamp - 100); const index = icDataset.findIndex(value => value.x >= firstTimestamp - 100);
data = data.map(values => values.slice(index)); data = data.map(values => values.slice(index));
} }
...@@ -177,7 +180,11 @@ class Plot extends React.Component { ...@@ -177,7 +180,11 @@ class Plot extends React.Component {
if (this.props.yUseMinMax) { if (this.props.yUseMinMax) {
yRange = [this.props.yMin, this.props.yMax]; yRange = [this.props.yMin, this.props.yMax];
} else if (this.props.data.length > 0) { } else if (this.props.data.length > 0) {
yRange = [this.props.data[0][0].y, this.props.data[0][0].y]; let icDataset = this.props.data.find(function(element) {
return element !== undefined;
})
yRange = [icDataset[0].y, icDataset[0].y];
this.props.data.forEach(values => { this.props.data.forEach(values => {
const range = extent(values, p => p.y); const range = extent(values, p => p.y);
......
...@@ -69,14 +69,12 @@ class Widget extends React.Component { ...@@ -69,14 +69,12 @@ class Widget extends React.Component {
// TODO make sure that the signals are only the signals that belong to the scenario at hand // TODO make sure that the signals are only the signals that belong to the scenario at hand
let signals = SignalStore.getState(); let signals = SignalStore.getState();
let icIDs = []; let icIDs = [];
if ( props.data.signalIDs.length > 0){
for (let i in props.data.signalIDs.length){
let signal = signals.find(s => s.id === props.data.signalIDs[i]);
let config = configs.find(m => m.id === signal.configID);
icIDs[i] = config.icID;
}
}
for (let id of props.data.signalIDs){
let signal = signals.find(s => s.id === id);
let config = configs.find(m => m.id === signal.configID);
icIDs[signal.id] = config.icID;
}
return { return {
icData: icData, icData: icData,
...@@ -138,7 +136,7 @@ class Widget extends React.Component { ...@@ -138,7 +136,7 @@ class Widget extends React.Component {
} else if (widget.type === 'Label') { } else if (widget.type === 'Label') {
return <WidgetLabel widget={widget} /> return <WidgetLabel widget={widget} />
} else if (widget.type === 'PlotTable') { } else if (widget.type === 'PlotTable') {
return <WidgetPlotTable widget={widget} data={this.state.icData} dummy={this.state.sequence} editing={this.props.editing} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index)} paused={this.props.paused} /> return <WidgetPlotTable widget={widget} data={this.state.icData} dummy={this.state.sequence} signals={this.state.signals} icIDs={this.state.icIDs} editing={this.props.editing} onWidgetChange={(w) => this.props.onWidgetStatusChange(w, this.props.index)} paused={this.props.paused} />
} else if (widget.type === 'Image') { } else if (widget.type === 'Image') {
return <WidgetImage widget={widget} files={this.state.files} token={this.state.sessionToken} /> return <WidgetImage widget={widget} files={this.state.files} token={this.state.sessionToken} />
} else if (widget.type === 'Button') { } else if (widget.type === 'Button') {
......
...@@ -27,124 +27,85 @@ class WidgetPlotTable extends Component { ...@@ -27,124 +27,85 @@ class WidgetPlotTable extends Component {
super(props); super(props);
this.state = { this.state = {
preselectedSignals: [],
signals: [] signals: []
}; };
} }
componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void { componentDidUpdate(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot: SS): void {
if (this.props.config == null) { // Identify if there was a change in the selected signals
return; if (JSON.stringify(prevProps.widget.signalIDs) !== JSON.stringify(this.props.widget.signalIDs)
} || this.state.signals.length === 0) {
// Update the currently selected signals
// Update internal selected signals state with props (different array objects) let intersection = []
if (prevProps.widget.customProperties.signals !== this.props.widget.customProperties.signals) { let signalID, sig;
this.setState( {signals: this.props.widget.customProperties.signals}); for (signalID of this.props.widget.signalIDs) {
} for (sig of this.props.signals) {
if (signalID === sig.id) {
// Identify if there was a change in the preselected signals intersection.push(sig);
if (JSON.stringify(prevProps.widget.customProperties.preselectedSignals) !== JSON.stringify(this.props.widget.customProperties.preselectedSignals)
|| this.state.preselectedSignals.length === 0) {
// Update the currently selected signals by intersecting with the preselected signalsWidget
// Do the same with the plot values
var intersection = this.computeIntersection(this.props.widget.customProperties.preselectedSignals, this.props.widget.customProperties.signals);
this.setState({ signals: intersection });
this.updatePreselectedSignalsState(this.props);
}
}
// Perform the intersection of the lists, alternatively could be done with Sets ensuring unique values
computeIntersection(preselectedSignals, selectedSignals) {
return preselectedSignals.filter( s => selectedSignals.includes(s));
}
updatePreselectedSignalsState(props) {
// Create checkboxes using the signal indices from component config
if(props.config.outputMapping){
const preselectedSignals = props.config.outputMapping.reduce(
// Loop through component config signals
(accum, signal, signal_index) => {
// Append them if they belong to the current selected type
if (props.widget.customProperties.preselectedSignals.indexOf(signal_index) > -1) {
accum.push(
{
index: signal_index,
name: signal.name,
type: signal.type
}
)
} }
return accum; }
}, []);
this.setState({ preselectedSignals });
} }
this.setState({signals: intersection});
}
} }
updateSignalSelection(signal_index, checked) { updateSignalSelection(signal_index, checked) {
// Update the selected signals and propagate to parent component // Update the selected signals and propagate to parent component
var new_widget = Object.assign({}, this.props.widget, { var new_widget = Object.assign({}, this.props.widget, {
signals: checked? this.state.signals.concat(signal_index) : this.state.signals.filter( (idx) => idx !== signal_index ) signals: checked ? this.state.signals.concat(signal_index) : this.state.signals.filter((idx) => idx !== signal_index)
}); });
this.props.onWidgetChange(new_widget); this.props.onWidgetChange(new_widget);
} }
render() { render() {
let checkBoxes = []; let checkBoxes = [];
let icData = []; let icData = [];
let legendSignals = []; let legendSignals = [];
// Data passed to plot let showLegend = false;
if (this.props.config) {
const ic = this.props.config.icID; if (this.state.signals.length > 0) {
if (this.props.data[ic] != null && this.props.data[ic].output != null && this.props.data[ic].output.values != null) { showLegend = true;
icData = this.props.data[ic].output.values.filter((values, index) => (
this.props.widget.customProperties.signals.findIndex(value => value === index) !== -1 // get data of preselected signals
)); let signal;
} for (signal of this.state.signals) {
// determine ID of infrastructure component related to signal (via config)
let icID = this.props.icIDs[signal.id]
if (this.props.data[icID] != null && this.props.data[icID].output != null && this.props.data[icID].output.values != null) {
if (this.props.data[icID].output.values[signal.index] !== undefined){
icData.push(this.props.data[icID].output.values[signal.index]);
}
}
}
if (this.state.preselectedSignals && this.state.preselectedSignals.length > 0) {
// Create checkboxes using the signal indices from component config // Create checkboxes using the signal indices from component config
checkBoxes = this.state.preselectedSignals.map( (signal) => { checkBoxes = this.state.signals.map((signal) => {
var checked = this.state.signals.indexOf(signal.index) > -1; let checked = this.state.signals.indexOf(signal.index) > -1;
var chkBxClasses = classNames({ let chkBxClasses = classNames({
'btn': true, 'btn': true,
'btn-default': true, 'btn-default': true,
'active': checked 'active': checked
}); });
return <FormCheck key={signal.index} className={chkBxClasses} checked={checked} disabled={ this.props.editing } onChange={(e) => this.updateSignalSelection(signal.index, e.target.checked) } > { signal.name } </FormCheck> return <FormCheck key={signal.index} className={chkBxClasses} checked={checked} disabled={this.props.editing}
onChange={(e) => this.updateSignalSelection(signal.index, e.target.checked)}> {signal.name} </FormCheck>
}); });
} }
// Prepare an array with the signals to show in the legend
legendSignals = this.state.preselectedSignals.reduce( (accum, signal, i) => {
if (this.state.signals.includes(signal.index)) {
accum.push({
index: signal.index,
name: signal.name,
type: signal.type
});
}
return accum;
}, []);}
let showLegend = false;
if(legendSignals !== []){
showLegend = true;
}
return ( return (
<div className="plot-table-widget" ref="wrapper"> <div className="plot-table-widget" ref="wrapper">
<div className="content"> <div className="content">
<div className="table-plot-row"> <div className="table-plot-row">
<div className="widget-table"> <div className="widget-table">
{ checkBoxes.length > 0 ? ( {checkBoxes.length > 0 ? (
<FormGroup className="btn-group-vertical"> <FormGroup className="btn-group-vertical">
{ checkBoxes } {checkBoxes}
</FormGroup> </FormGroup>
) : ( <small>No signal has been pre-selected.</small> ) ) : (<small>No signal has been pre-selected.</small>)
} }
</div> </div>
...@@ -162,13 +123,12 @@ class WidgetPlotTable extends Component { ...@@ -162,13 +123,12 @@ class WidgetPlotTable extends Component {
/> />
</div> </div>
</div> </div>
{showLegend? ( {showLegend ? (
<PlotLegend signals={legendSignals} /> ) : (<div></div>) <PlotLegend signals={this.state.signals}/>) : (<div></div>)
} }
</div> </div>
</div> </div>
); );
} }
} }
export default WidgetPlotTable; export default WidgetPlotTable;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment