diff options
author | srichman333 <sarah_n_richman@brown.edu> | 2023-07-28 14:36:30 -0400 |
---|---|---|
committer | srichman333 <sarah_n_richman@brown.edu> | 2023-07-28 14:36:30 -0400 |
commit | b236882faef4e5434158e7a8dfb82daa47031ca5 (patch) | |
tree | b9d2f54a8bf804a88b0459af6b7fc1c2f8ff34fa /src | |
parent | 6984267d0f70f080bc1e1e6397b2377145e3cae2 (diff) |
graph colorPickers
Diffstat (limited to 'src')
4 files changed, 102 insertions, 12 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index d5e21ce0e..70fed91ef 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -97,17 +97,38 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } selectAxes = (axes: string[]) => (this.layoutDoc.data_vizAxes = new List<string>(axes)); - @computed get selectView() { + @computed get table(){ + if (!this.pairs) return 'no data'; + return <TableBox pairs={this.pairs} axes={this.axes} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes}/>; + } + @computed get lineChart(){ + const width = this.props.PanelWidth() * 0.9; + const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9; + const margin = { top: 10, right: 25, bottom: 50, left: 25 }; + if (!this.pairs) return 'no data'; + return <LineChart ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />; + } + @computed get histogram(){ const width = this.props.PanelWidth() * 0.9; const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9; const margin = { top: 10, right: 25, bottom: 50, left: 25 }; if (!this.pairs) return 'no data'; - // prettier-ignore + return <Histogram height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />; + } + @computed get pieChart(){ + const width = this.props.PanelWidth() * 0.9; + const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9; + const margin = { top: 10, right: 25, bottom: 50, left: 25 }; + if (!this.pairs) return 'no data'; + console.log('new pie') + return <PieChart height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />; + } + @computed get selectView() { switch (this.dataVizView) { - case DataVizView.TABLE: return <TableBox pairs={this.pairs} axes={this.axes} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes}/>; - case DataVizView.LINECHART: return <LineChart ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />; - case DataVizView.HISTOGRAM: return <Histogram height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />; - case DataVizView.PIECHART: return <PieChart height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />; + case DataVizView.TABLE: return this.table; + case DataVizView.LINECHART: return this.lineChart; + case DataVizView.HISTOGRAM: return this.histogram; + case DataVizView.PIECHART: return this.pieChart; } } @computed get dataUrl() { diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss index 5945840b5..da5a274a5 100644 --- a/src/client/views/nodes/DataVizBox/components/Chart.scss +++ b/src/client/views/nodes/DataVizBox/components/Chart.scss @@ -23,9 +23,8 @@ .histogram-bar{ outline: thin solid black; - fill: #69b3a2; &.hover{ - fill: grey; + outline: 5px solid black; } } diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index fdde29c81..998636a42 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -14,6 +14,8 @@ import { PinProps, PresBox } from "../../trails"; import { Docs } from "../../../../documents/Documents"; import { List } from "../../../../../fields/List"; import './Chart.scss'; +import { ColorPicker, Size, Type } from "browndash-components"; +import { FaFillDrip } from "react-icons/fa"; export interface HistogramProps { rootDoc: Doc; @@ -41,6 +43,9 @@ export class Histogram extends React.Component<HistogramProps> { private numericalYData: boolean = false; // whether the y axis is controlled by provided data rather than frequency private maxBins = 15; // maximum number of bins that is readable on a normal sized doc @observable _currSelected: any | undefined = undefined; + private curBarSelected: any = undefined; + private barColors: any = {}; + private defaultBarColor: string = '#69b3a2'; // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates @computed get _histogramData() { @@ -381,6 +386,11 @@ export class Histogram extends React.Component<HistogramProps> { elements[i].classList.remove('hover'); } if (!sameAsCurrent!) selected.attr('class', 'histogram-bar hover'); + if (sameAsCurrent!) this.curBarSelected = undefined; + else { + selected.attr('class', 'histogram-bar hover') + this.curBarSelected = selected; + } }); svg.on('click', onPointClick); @@ -415,6 +425,20 @@ export class Histogram extends React.Component<HistogramProps> { return height - y(d.length)}) .attr("width", eachRectWidth) .attr("class", 'histogram-bar') + .attr("fill", (d)=>{ return this.barColors[d[0]]? this.barColors[d[0]] : this.defaultBarColor}) + }; + + @action changeSelectedColor = (color: string) => { + this.curBarSelected.attr("fill", color); + this.barColors[this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')] = color; + }; + @action changeDefaultColor = (color: string) => { + const defaultColorBars = this._histogramSvg!.selectAll('.histogram-bar').filter((d: any) => { + if (this.barColors[d[0]]) return false; + else return true; + }) + defaultColorBars.attr("fill", color); + this.defaultBarColor = color; }; render() { @@ -433,7 +457,27 @@ export class Histogram extends React.Component<HistogramProps> { this.props.axes.length >= 1 ? ( <div className="chart-container" > <div className="graph-title"> {this.graphTitle} </div> - <div className={'selected-data'}> {`Selected: ${selected}`}</div> + <ColorPicker + tooltip={'Change Default Slice Color'} + type={Type.SEC} + icon={<FaFillDrip/>} + selectedColor={this.defaultBarColor} + setSelectedColor={color => this.changeDefaultColor(color)} + size={Size.XSMALL} + /> + {selected != 'none' ? + <div className={'selected-data'}> + Selected: {selected} + <ColorPicker + tooltip={'Change Slice Color'} + type={Type.SEC} + icon={<FaFillDrip/>} + selectedColor={this.curBarSelected.attr("fill")} + setSelectedColor={color => this.changeSelectedColor(color)} + size={Size.XSMALL} + /> + </div> + : null} <div ref={this._histogramRef} /> </div> ) : <span className="chart-container"> {'first use table view to select a column to graph'}</span> diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index 27653b847..872bf9af1 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -14,6 +14,8 @@ import { PinProps, PresBox } from "../../trails"; import { Docs } from "../../../../documents/Documents"; import { List } from "../../../../../fields/List"; import './Chart.scss'; +import { ColorPicker, Size, Type } from "browndash-components"; +import { FaFillDrip } from "react-icons/fa"; export interface PieChartProps { rootDoc: Doc; @@ -39,6 +41,8 @@ export class PieChart extends React.Component<PieChartProps> { private _piechartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined; private byCategory: boolean = true; // whether the data is organized by category or by specified number percentages/ratios @observable _currSelected: any | undefined = undefined; + private curSliceSelected: any = undefined; + private sliceColors: any = {}; // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates @computed get _piechartData() { @@ -332,7 +336,11 @@ export class PieChart extends React.Component<PieChartProps> { for (let i = 0; i < elements.length; i++) { elements[i].classList.remove('hover'); } - if (!sameAsCurrent!) selected.attr('class', 'slice hover'); + if (sameAsCurrent!) this.curSliceSelected = undefined; + else { + selected.attr('class', 'slice hover') + this.curSliceSelected = selected; + } }); var arcs = g.selectAll("arc") @@ -340,7 +348,7 @@ export class PieChart extends React.Component<PieChartProps> { .enter() .append("g") arcs.append("path") - .attr("fill", (data, i)=>{ return d3.schemeSet3[i]? d3.schemeSet3[i]: d3.schemeSet3[i%12] }) + .attr("fill", (data, i)=>{ return this.sliceColors[data.data.valueOf()]? this.sliceColors[data.data.valueOf()] : d3.schemeSet3[i]? d3.schemeSet3[i]: d3.schemeSet3[i%12] }) .attr("class", 'slice') .attr("d", arc) .on('click', onPointClick) @@ -368,7 +376,13 @@ export class PieChart extends React.Component<PieChartProps> { }; + @action changeSelectedColor = (color: string) => { + this.curSliceSelected.attr("fill", color); + this.sliceColors[this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')] = color; + }; + render() { + console.log(this.sliceColors) var selected: string; if (this._currSelected){ selected = '{ '; @@ -383,7 +397,19 @@ export class PieChart extends React.Component<PieChartProps> { this.props.axes.length >= 1 ? ( <div className="chart-container"> <div className="graph-title"> {this.graphTitle} </div> - <div className={'selected-data'}> {`Selected: ${selected}`}</div> + {selected != 'none' ? + <div className={'selected-data'}> + Selected: {selected} + <ColorPicker + tooltip={'Change Slice Color'} + type={Type.SEC} + icon={<FaFillDrip/>} + selectedColor={this.curSliceSelected.attr("fill")} + setSelectedColor={color => this.changeSelectedColor(color)} + size={Size.XSMALL} + /> + </div> + : null} <div ref={this._piechartRef} /> </div> ) : <span className="chart-container"> {'first use table view to select a column to graph'}</span> |