diff options
Diffstat (limited to 'src/client/views/nodes/DataVizBox/components/Histogram.tsx')
-rw-r--r-- | src/client/views/nodes/DataVizBox/components/Histogram.tsx | 107 |
1 files changed, 56 insertions, 51 deletions
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index eca77f0f3..227c993c7 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -1,7 +1,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ColorPicker, EditableText, IconButton, Size, Type } from 'browndash-components'; import * as d3 from 'd3'; -import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { FaFillDrip } from 'react-icons/fa'; @@ -10,14 +10,14 @@ import { List } from '../../../../../fields/List'; import { listSpec } from '../../../../../fields/Schema'; import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; import { Docs } from '../../../../documents/Documents'; -import { LinkManager } from '../../../../util/LinkManager'; import { undoable } from '../../../../util/UndoManager'; import { PinProps, PresBox } from '../../trails'; import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils'; import './Chart.scss'; +import { ObservableReactComponent } from '../../../ObservableReactComponent'; export interface HistogramProps { - rootDoc: Doc; + Document: Doc; layoutDoc: Doc; axes: string[]; records: { [key: string]: any }[]; @@ -34,7 +34,7 @@ export interface HistogramProps { } @observer -export class Histogram extends React.Component<HistogramProps> { +export class Histogram extends ObservableReactComponent<HistogramProps> { private _disposers: { [key: string]: IReactionDisposer } = {}; private _histogramRef: React.RefObject<HTMLDivElement> = React.createRef(); private _histogramSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined; @@ -46,46 +46,51 @@ export class Histogram extends React.Component<HistogramProps> { private selectedData: any = undefined; // Selection of selected bar private hoverOverData: any = undefined; // Selection of bar being hovered over + constructor(props: any) { + super(props); + makeObservable(this); + } + @computed get _tableDataIds() { - return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows); + return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows); } // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent) @computed get _tableData() { - return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]); + return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]); } // filters all data to just display selected data if brushed (created from an incoming link) @computed get _histogramData() { - if (this.props.axes.length < 1) return []; - if (this.props.axes.length < 2) { - var ax0 = this.props.axes[0]; - if (/\d/.test(this.props.records[0][ax0])) { + if (this._props.axes.length < 1) return []; + if (this._props.axes.length < 2) { + var ax0 = this._props.axes[0]; + if (/\d/.test(this._props.records[0][ax0])) { this.numericalXData = true; } - return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]] })); + return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] })); } - var ax0 = this.props.axes[0]; - var ax1 = this.props.axes[1]; - if (/\d/.test(this.props.records[0][ax0])) { + var ax0 = this._props.axes[0]; + var ax1 = this._props.axes[1]; + if (/\d/.test(this._props.records[0][ax0])) { this.numericalXData = true; } - if (/\d/.test(this.props.records[0][ax1])) { + if (/\d/.test(this._props.records[0][ax1])) { this.numericalYData = true; } - return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]], [ax1]: record[this.props.axes[1]] })); + return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]], [ax1]: record[this._props.axes[1]] })); } @computed get defaultGraphTitle() { - var ax0 = this.props.axes[0]; - var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined; - if (this.props.axes.length < 2 || !ax1 || !/\d/.test(this.props.records[0][ax1]) || !this.numericalYData) { + var ax0 = this._props.axes[0]; + var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined; + if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1]) || !this.numericalYData) { return ax0 + ' Histogram'; } else return ax0 + ' by ' + ax1 + ' Histogram'; } @computed get parentViz() { - return DocCast(this.props.rootDoc.dataViz_parentViz); - // return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links - // .filter(link => link.link_anchor_1 == this.props.rootDoc.dataViz_parentViz) // get links where this chart doc is the target of the link + return DocCast(this._props.Document.dataViz_parentViz); + // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links + // .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link // .map(link => DocCast(link.link_anchor_1)); // then return the source of the link } @@ -115,16 +120,16 @@ export class Histogram extends React.Component<HistogramProps> { const anchor = Docs.Create.ConfigDocument({ title: 'histogram doc selection' + this._currSelected, }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc); + PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); return anchor; }; @computed get height() { - return this.props.height - this.props.margin.top - this.props.margin.bottom; + return this._props.height - this._props.margin.top - this._props.margin.bottom; } @computed get width() { - return this.props.width - this.props.margin.left - this.props.margin.right; + return this._props.width - this._props.margin.left - this._props.margin.right; } // cleans data by converting numerical data to numbers and taking out empty cells @@ -212,10 +217,10 @@ export class Histogram extends React.Component<HistogramProps> { .select(this._histogramRef.current) .append('svg') .attr('class', 'graph') - .attr('width', width + this.props.margin.right + this.props.margin.left) - .attr('height', height + this.props.margin.top + this.props.margin.bottom) + .attr('width', width + this._props.margin.right + this._props.margin.left) + .attr('height', height + this._props.margin.top + this._props.margin.bottom) .append('g') - .attr('transform', 'translate(' + this.props.margin.left + ',' + this.props.margin.top + ')')); + .attr('transform', 'translate(' + this._props.margin.left + ',' + this._props.margin.top + ')')); var x = d3 .scaleLinear() .domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins]) @@ -383,7 +388,7 @@ export class Histogram extends React.Component<HistogramProps> { ) .attr('fill', d => { var barColor; - const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); + const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); barColors.forEach(each => { if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; else { @@ -391,24 +396,24 @@ export class Histogram extends React.Component<HistogramProps> { if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1]; } }); - return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor); + return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor); }); }; @action changeSelectedColor = (color: string) => { this.curBarSelected.attr('fill', color); - const barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')); + const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')); - const barColors = Cast(this.props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); + const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); barColors.push(StrCast(barName + '::' + color)); }; @action eraseSelectedColor = () => { - this.curBarSelected.attr('fill', this.props.layoutDoc.dataViz_histogram_defaultColor); - const barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')); + this.curBarSelected.attr('fill', this._props.layoutDoc.dataViz_histogram_defaultColor); + const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')); - const barColors = Cast(this.props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); + const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); }; @@ -417,7 +422,7 @@ export class Histogram extends React.Component<HistogramProps> { if (svg) svg.selectAll('rect').attr('fill', (d: any) => { var barColor; - const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); + const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); barColors.forEach(each => { if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; else { @@ -425,7 +430,7 @@ export class Histogram extends React.Component<HistogramProps> { if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1]; } }); - return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor); + return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor); }); }; @@ -434,14 +439,14 @@ export class Histogram extends React.Component<HistogramProps> { this._histogramData; var curSelectedBarName = ''; var titleAccessor: any = ''; - if (this.props.axes.length == 2) titleAccessor = 'dataViz_histogram_title' + this.props.axes[0] + '-' + this.props.axes[1]; - else if (this.props.axes.length > 0) titleAccessor = 'dataViz_histogram_title' + this.props.axes[0]; - if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle; - if (!this.props.layoutDoc.dataViz_histogram_defaultColor) this.props.layoutDoc.dataViz_histogram_defaultColor = '#69b3a2'; - if (!this.props.layoutDoc.dataViz_histogram_barColors) this.props.layoutDoc.dataViz_histogram_barColors = new List<string>(); + if (this._props.axes.length == 2) titleAccessor = 'dataViz_histogram_title' + this._props.axes[0] + '-' + this._props.axes[1]; + else if (this._props.axes.length > 0) titleAccessor = 'dataViz_histogram_title' + this._props.axes[0]; + if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle; + if (!this._props.layoutDoc.dataViz_histogram_defaultColor) this._props.layoutDoc.dataViz_histogram_defaultColor = '#69b3a2'; + if (!this._props.layoutDoc.dataViz_histogram_barColors) this._props.layoutDoc.dataViz_histogram_barColors = new List<string>(); var selected = 'none'; if (this._currSelected) { - curSelectedBarName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')); + curSelectedBarName = StrCast(this._currSelected![this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')); selected = '{ '; Object.keys(this._currSelected).forEach(key => key // @@ -451,17 +456,17 @@ export class Histogram extends React.Component<HistogramProps> { selected = selected.substring(0, selected.length - 2) + ' }'; } var selectedBarColor; - var barColors = StrListCast(this.props.layoutDoc.histogramBarColors).map(each => each.split('::')); + var barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::')); barColors.forEach(each => each[0] === curSelectedBarName && (selectedBarColor = each[1])); if (this._histogramData.length > 0 || !this.parentViz) { - return this.props.axes.length >= 1 ? ( - <div className="chart-container" style={{width: this.props.width+this.props.margin.right}}> + return this._props.axes.length >= 1 ? ( + <div className="chart-container" style={{width: this._props.width+this._props.margin.right}}> <div className="graph-title"> <EditableText - val={StrCast(this.props.layoutDoc[titleAccessor])} + val={StrCast(this._props.layoutDoc[titleAccessor])} setVal={undoable( - action(val => (this.props.layoutDoc[titleAccessor] = val as string)), + action(val => (this._props.layoutDoc[titleAccessor] = val as string)), 'Change Graph Title' )} color={'black'} @@ -473,9 +478,9 @@ export class Histogram extends React.Component<HistogramProps> { tooltip={'Change Default Bar Color'} type={Type.SEC} icon={<FaFillDrip />} - selectedColor={StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor)} - setFinalColor={undoable(color => (this.props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')} - setSelectedColor={undoable(color => (this.props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')} + selectedColor={StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor)} + setFinalColor={undoable(color => (this._props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')} + setSelectedColor={undoable(color => (this._props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')} size={Size.XSMALL} /> </div> |