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

Plot Widget: make line colors editable #275

This commit is contained in:
Laura Fuentes Grau 2021-01-03 15:40:37 +01:00
parent f5ad08e888
commit 09c75c4f18
8 changed files with 135 additions and 13 deletions

View file

@ -55,6 +55,9 @@ class ColorPicker extends React.Component {
if(this.props.controlId === 'strokeStyle'){
temp.customProperties.zones[this.props.zoneIndex]['strokeStyle'] = color.hex;
}
else if(this.props.controlId === 'lineColor'){
temp.customProperties.lineColors[this.props.lineIndex] = color.hex;
}
else{
let parts = this.props.controlId.split('.');
let isCustomProperty = true;
@ -96,7 +99,12 @@ class ColorPicker extends React.Component {
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'];
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'){
hexColor = this.state.widget.customProperties.lineColors[this.props.lineIndex];
}
}
else{

View file

@ -191,7 +191,7 @@ class EditWidgetColorZonesControl extends React.Component {
}
return <FormGroup>
<FormLabel>Color zones</FormLabel>
<FormLabel>Color Zones</FormLabel>
<Button onClick={this.addZone} style={{marginBottom: '10px', marginLeft: '120px'}} disabled={!this.props.widget.customProperties.colorZones}><Icon size='xs' icon="plus" /></Button>
<div>
@ -205,8 +205,6 @@ class EditWidgetColorZonesControl extends React.Component {
height: '40px'
}
return (<Button
style={style} key={idx} onClick={i => this.editColorZone(idx)} disabled={!this.props.widget.customProperties.colorZones}><Icon icon="pen" /></Button>
)

View file

@ -31,6 +31,7 @@ import EditWidgetCheckboxControl from './edit-widget-checkbox-control';
import EditWidgetColorZonesControl from './edit-widget-color-zones-control';
import EditWidgetMinMaxControl from './edit-widget-min-max-control';
import EditWidgetParametersControl from './edit-widget-parameters-control';
import EditWidgetPlotColorsControl from './edit-widget-plot-colors-control';
//import EditWidgetHTMLContent from './edit-widget-html-content';
export default function CreateControls(widgetType = null, widget = null, sessionToken = null, files = null, signals, handleChange) {
@ -70,8 +71,9 @@ export default function CreateControls(widgetType = null, widget = null, session
DialogControls.push(
<EditWidgetTimeControl key={0} widget={widget} controlId={'customProperties.time'} handleChange={(e) => handleChange(e)} />,
<EditWidgetSignalsControl key={1} widget={widget} controlId={'signalIDs'} signals={signals} handleChange={(e) => handleChange(e)} direction={'out'}/>,
<EditWidgetTextControl key={2} widget={widget} controlId={'customProperties.ylabel'} label={'Y-Axis name'} placeholder={'Enter a name for the y-axis'} handleChange={(e) => handleChange(e)} />,
<EditWidgetMinMaxControl key={3} widget={widget} controlId="customProperties.y" handleChange={e => handleChange(e)} />
<EditWidgetPlotColorsControl key={2} widget={widget} controlId={'customProperties.lineColors'} signals={signals} handleChange={(e) => handleChange(e)} />,
<EditWidgetTextControl key={3} widget={widget} controlId={'customProperties.ylabel'} label={'Y-Axis name'} placeholder={'Enter a name for the y-axis'} handleChange={(e) => handleChange(e)} />,
<EditWidgetMinMaxControl key={4} widget={widget} controlId="customProperties.y" handleChange={e => handleChange(e)} />
);
break;
case 'Table':

View file

@ -0,0 +1,101 @@
/**
* 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 { FormGroup, OverlayTrigger, Tooltip , FormLabel, Button } from 'react-bootstrap';
import ColorPicker from './color-picker'
import Icon from "../../common/icon";
// schemeCategory20 no longer available in d3
class EditWidgetPlotColorsControl extends Component {
constructor(props) {
super(props);
this.state = {
widget: {},
showColorPicker: false,
originalColor: null,
selectedIndex: null
};
}
static getDerivedStateFromProps(props, state){
return {
widget: props.widget
};
}
//same here
closeEditModal = (data) => {
this.setState({showColorPicker: false})
if(typeof data === 'undefined'){
let temp = this.state.widget;
temp.customProperties.lineColors[this.state.selectedIndex] = this.state.originalColor;
this.setState({ widget: temp });
}
}
editLineColor = (index) => {
if(this.state.selectedIndex !== index){
let color = this.state.widget.customProperties.lineColors[index];
this.setState({selectedIndex: index, showColorPicker: true, originalColor: color});
}
else{
this.setState({selectedIndex: null});
}
}
render() {
return (
<FormGroup>
<FormLabel>Line Colors</FormLabel>
<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);
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>
)
}
}
export default EditWidgetPlotColorsControl;

View file

@ -89,6 +89,7 @@ class WidgetFactory {
widget.customProperties.yMin = 0;
widget.customProperties.yMax = 10;
widget.customProperties.yUseMinMax = false;
widget.customProperties.lineColors = [];
break;
case 'Table':
widget.minWidth = 200;

View file

@ -20,13 +20,17 @@ import { scaleOrdinal} from 'd3-scale';
import {schemeCategory10} from 'd3-scale-chromatic'
function Legend(props){
const signal = props.sig;
const hasScalingFactor = (signal.scalingFactor !== 1);
const newLineColor = scaleOrdinal(schemeCategory10);
let color = typeof props.lineColor === "undefined" ? newLineColor(signal.id) : props.lineColor;
if(hasScalingFactor){
return (
<li key={signal.id} className="signal-legend" style={{ color: props.colorScale(signal.id) }}>
<li key={signal.id} className="signal-legend" style={{ color: color }}>
<span className="signal-legend-name">{signal.name}</span>
<span style={{ marginLeft: '0.3em' }} className="signal-unit">{signal.unit}</span>
<span style={{ marginLeft: '0.3em' }} className="signal-scale">{signal.scalingFactor}</span>
@ -34,7 +38,7 @@ function Legend(props){
)
} else {
return (
<li key={signal.id} className="signal-legend" style={{ color: props.colorScale(signal.id) }}>
<li key={signal.id} className="signal-legend" style={{ color: color }}>
<span className="signal-legend-name">{signal.name}</span>
<span style={{ marginLeft: '0.3em' }} className="signal-unit">{signal.unit}</span>
</li>
@ -45,13 +49,12 @@ function Legend(props){
class PlotLegend extends React.Component {
render() {
const colorScale = scaleOrdinal(schemeCategory10);
return <div className="plot-legend">
<ul>
{
this.props.signals.map( signal =>
<Legend key={signal.id} sig={signal} colorScale={colorScale}/>
<Legend key={signal.id} sig={signal} lineColor={this.props.lineColors[signal.id]}/>
)}
</ul>
</div>;

View file

@ -203,14 +203,21 @@ class Plot extends React.Component {
// generate paths from data
const sparkLine = line().x(p => xScale(p.x)).y(p => yScale(p.y));
const lineColor = scaleOrdinal(schemeCategory10);
const newLineColor = scaleOrdinal(schemeCategory10);
const lines = this.state.data.map((values, index) => <path d={sparkLine(values)} key={index} style={{ fill: 'none', stroke: lineColor(index) }} />);
const lines = this.state.data.map((values, index) => {
let signalID = this.props.signalIDs[index];
if (typeof this.props.lineColors[signalID] === "undefined") {
this.props.lineColors[signalID] = newLineColor(signalID);
}
return <path d={sparkLine(values)} key={index} style={{ fill: 'none', stroke: this.props.lineColors[signalID] }} />
});
this.setState({ lines, xAxis, yAxis });
}
render() {
const yLabelPos = {
x: 12,
y: this.props.height / 2

View file

@ -103,9 +103,11 @@ class WidgetPlot extends React.Component {
yUseMinMax={this.props.widget.customProperties.yUseMinMax}
paused={this.props.paused}
yLabel={this.props.widget.customProperties.ylabel}
lineColors={this.props.widget.customProperties.lineColors}
signalIDs={this.props.widget.signalIDs}
/>
</div>
<PlotLegend signals={this.state.signals} />
<PlotLegend signals={this.state.signals} lineColors={this.props.widget.customProperties.lineColors} />
</div>;
}
}