diff options
Diffstat (limited to 'src/client/views/nodes/DataVizBox/components/PieChart.tsx')
-rw-r--r-- | src/client/views/nodes/DataVizBox/components/PieChart.tsx | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index 4622b470a..e644870da 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -1,6 +1,7 @@ +import { Checkbox } from '@mui/material'; import { ColorPicker, EditableText, 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'; @@ -12,10 +13,10 @@ import { Docs } from '../../../../documents/Documents'; import { undoable } from '../../../../util/UndoManager'; import { PinProps, PresBox } from '../../trails'; import './Chart.scss'; -import { Checkbox } from '@material-ui/core'; +import { ObservableReactComponent } from '../../../ObservableReactComponent'; export interface PieChartProps { - rootDoc: Doc; + Document: Doc; layoutDoc: Doc; axes: string[]; records: { [key: string]: any }[]; @@ -32,7 +33,7 @@ export interface PieChartProps { } @observer -export class PieChart extends React.Component<PieChartProps> { +export class PieChart extends ObservableReactComponent<PieChartProps> { private _disposers: { [key: string]: IReactionDisposer } = {}; private _piechartRef: React.RefObject<HTMLDivElement> = React.createRef(); private _piechartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined; @@ -41,44 +42,49 @@ export class PieChart extends React.Component<PieChartProps> { private hoverOverData: any = undefined; // Selection of slice being hovered over @observable _currSelected: any | undefined = undefined; // Object of selected slice + 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]); } // organized by specified number percentages/ratios if one column is selected and it contains numbers // otherwise, assume data is organized by categories @computed get byCategory() { - return !/\d/.test(this.props.records[0][this.props.axes[0]]) || this.props.layoutDoc.dataViz_pie_asHistogram; + return !/\d/.test(this._props.records[0][this._props.axes[0]]) || this._props.layoutDoc.dataViz_pie_asHistogram; } // filters all data to just display selected data if brushed (created from an incoming link) @computed get _pieChartData() { - if (this.props.axes.length < 1) return []; + if (this._props.axes.length < 1) return []; - const ax0 = this.props.axes[0]; - if (this.props.axes.length < 2) { - return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]] })); + const ax0 = this._props.axes[0]; + if (this._props.axes.length < 2) { + return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] })); } - const ax1 = this.props.axes[1]; - return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]], [ax1]: record[this.props.axes[1]] })); + const ax1 = 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 || !/\d/.test(this.props.records[0][ax0]) || !ax1) { + var ax0 = this._props.axes[0]; + var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined; + if (this._props.axes.length < 2 || !/\d/.test(this._props.records[0][ax0]) || !ax1) { return ax0 + ' Pie Chart'; } return ax1 + ' by ' + ax0 + ' Pie Chart'; } @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 } @@ -101,16 +107,16 @@ export class PieChart extends React.Component<PieChartProps> { // title: 'piechart 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 @@ -181,7 +187,7 @@ export class PieChart extends React.Component<PieChartProps> { var percentField = Object.keys(dataSet[0])[0]; var descriptionField = Object.keys(dataSet[0])[1]!; - var radius = Math.min(width, height - this.props.margin.top - this.props.margin.bottom) / 2; + var radius = Math.min(width, height - this._props.margin.top - this._props.margin.bottom) / 2; // converts data into Objects var data = this.data(dataSet); @@ -209,10 +215,10 @@ export class PieChart extends React.Component<PieChartProps> { .select(this._piechartRef.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')); - let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this.props.margin.left) + ',' + height / 2 + ')'); + let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this._props.margin.left) + ',' + height / 2 + ')'); var pie = d3.pie(); var arc = d3.arc().innerRadius(0).outerRadius(radius); @@ -249,7 +255,7 @@ export class PieChart extends React.Component<PieChartProps> { } catch (error) {} possibleDataPointVals.push(dataPointVal); }); - const sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); + const sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); arcs.append('path') .attr('fill', (d, i) => { var dataPoint; @@ -261,7 +267,7 @@ export class PieChart extends React.Component<PieChartProps> { } var sliceColor; if (dataPoint) { - const sliceTitle = dataPoint[this.props.axes[0]]; + const sliceTitle = dataPoint[this._props.axes[0]]; const accessByName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle; sliceColors.forEach(each => each[0] == accessByName && (sliceColor = each[1])); } @@ -277,6 +283,7 @@ export class PieChart extends React.Component<PieChartProps> { return 'slice'; } ) + // @ts-ignore .attr('d', arc) .on('click', onPointClick) .on('mouseover', onHover) @@ -308,10 +315,10 @@ export class PieChart extends React.Component<PieChartProps> { @action changeSelectedColor = (color: string) => { this.curSliceSelected.attr('fill', color); - const sliceTitle = this._currSelected[this.props.axes[0]]; + const sliceTitle = this._currSelected[this._props.axes[0]]; const sliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle; - const sliceColors = Cast(this.props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null); + const sliceColors = Cast(this._props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null); sliceColors.map(each => { if (each.split('::')[0] == sliceName) sliceColors.splice(sliceColors.indexOf(each), 1); }); @@ -319,20 +326,20 @@ export class PieChart extends React.Component<PieChartProps> { }; @action changeHistogramCheckBox = () => { - this.props.layoutDoc.dataViz_pie_asHistogram = !this.props.layoutDoc.dataViz_pie_asHistogram; + this._props.layoutDoc.dataViz_pie_asHistogram = !this._props.layoutDoc.dataViz_pie_asHistogram; this.drawChart(this._pieChartData, this.width, this.height); }; render() { var titleAccessor: any = ''; - if (this.props.axes.length == 2) titleAccessor = 'dataViz_pie_title' + this.props.axes[0] + '-' + this.props.axes[1]; - else if (this.props.axes.length > 0) titleAccessor = 'dataViz_pie_title' + this.props.axes[0]; - if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle; - if (!this.props.layoutDoc.dataViz_pie_sliceColors) this.props.layoutDoc.dataViz_pie_sliceColors = new List<string>(); + if (this._props.axes.length == 2) titleAccessor = 'dataViz_pie_title' + this._props.axes[0] + '-' + this._props.axes[1]; + else if (this._props.axes.length > 0) titleAccessor = 'dataViz_pie_title' + this._props.axes[0]; + if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle; + if (!this._props.layoutDoc.dataViz_pie_sliceColors) this._props.layoutDoc.dataViz_pie_sliceColors = new List<string>(); var selected: string; var curSelectedSliceName = ''; if (this._currSelected) { - const sliceTitle = this._currSelected[this.props.axes[0]]; + const sliceTitle = this._currSelected[this._props.axes[0]]; curSelectedSliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle; selected = '{ '; Object.keys(this._currSelected).map(key => { @@ -342,19 +349,19 @@ export class PieChart extends React.Component<PieChartProps> { selected += ' }'; } else selected = 'none'; var selectedSliceColor; - var sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); + var sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); sliceColors.forEach(each => { if (each[0] == curSelectedSliceName!) selectedSliceColor = each[1]; }); if (this._pieChartData.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'} @@ -362,9 +369,9 @@ export class PieChart extends React.Component<PieChartProps> { fillWidth /> </div> - {this.props.axes.length === 1 && /\d/.test(this.props.records[0][this.props.axes[0]]) ? ( - <div className={'asHistogram-checkBox'} style={{ width: this.props.width }}> - <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this.props.layoutDoc.dataViz_pie_asHistogram as boolean} /> + {this._props.axes.length === 1 && /\d/.test(this._props.records[0][this._props.axes[0]]) ? ( + <div className={'asHistogram-checkBox'} style={{ width: this._props.width }}> + <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this._props.layoutDoc.dataViz_pie_asHistogram as boolean} /> Organize data as histogram </div> ) : null} |