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:
parent
f5ad08e888
commit
09c75c4f18
8 changed files with 135 additions and 13 deletions
|
@ -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{
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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':
|
||||
|
|
101
src/widget/edit-widget/edit-widget-plot-colors-control.js
Normal file
101
src/widget/edit-widget/edit-widget-plot-colors-control.js
Normal 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;
|
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue