aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/components/LineChart.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DataVizBox/components/LineChart.tsx')
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx153
1 files changed, 77 insertions, 76 deletions
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index e093ec648..bc35ab8c8 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -3,18 +3,19 @@ import * as d3 from 'd3';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCast, NumListCast, StrListCast } from '../../../../../fields/Doc';
+import { Doc, DocListCast, NumListCast } from '../../../../../fields/Doc';
import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
-import { DocumentManager } from '../../../../util/DocumentManager';
import { undoable } from '../../../../util/UndoManager';
+import {} from '../../../DocComponent';
import { ObservableReactComponent } from '../../../ObservableReactComponent';
-import { PinProps, PresBox } from '../../trails';
+import { PinProps, PinDocView } from '../../../PinFuncs';
import { DataVizBox } from '../DataVizBox';
import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils';
import './Chart.scss';
+import { DocumentView } from '../../DocumentView';
export interface DataPoint {
x: number;
@@ -62,7 +63,6 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
}
@computed get _lineChartData() {
- var guids = StrListCast(this._props.layoutDoc.dataViz_rowIds);
if (this._props.axes.length <= 1) return [];
return this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[1]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
}
@@ -71,7 +71,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
}
@computed get parentViz() {
return DocCast(this._props.Document.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+ // return LinkManager.Links(this._props.Document) // out of all links
// .filter(link => {
// return link.link_anchor_1 == this._props.Document.dataViz_parentViz;
// }) // get links where this chart doc is the target of the link
@@ -80,7 +80,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
@computed get incomingHighlited() {
// return selected x and y axes
// otherwise, use the selection of whatever is linked to us
- const incomingVizBox = DocumentManager.Instance.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox;
+ const incomingVizBox = DocumentView.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox;
const highlitedRowIds = NumListCast(incomingVizBox?.layoutDoc?.dataViz_highlitedRows);
return this._tableData.filter((record, i) => highlitedRowIds.includes(this._tableDataIds[i])); // get all the datapoints they have selected field set by incoming anchor
}
@@ -102,7 +102,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
);
this._disposers.annos = reaction(
() => DocListCast(this._props.dataDoc[this._props.fieldKey + '_annotations']),
- annotations => {
+ (/* annotations */) => {
// modify how d3 renders so that anything in this annotations list would be potentially highlighted in some way
// could be blue colored to make it look like anchor
// this.drawAnnotations()
@@ -175,9 +175,9 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
getAnchor = (pinProps?: PinProps) => {
const anchor = Docs.Create.ConfigDocument({
//
- title: 'line doc selection' + this._currSelected?.x,
+ title: 'line doc selection' + (this._currSelected?.x ?? ''),
});
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
+ PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
anchor.config_dataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined;
return anchor;
};
@@ -191,11 +191,12 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
}
@computed get defaultGraphTitle() {
- var ax0 = this._props.axes[0];
- var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+ const ax0 = this._props.axes[0];
+ const 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 + ' Line Chart';
- } else return ax1 + ' by ' + ax0 + ' Line Chart';
+ }
+ return ax1 + ' by ' + ax0 + ' Line Chart';
}
setupTooltip() {
@@ -215,9 +216,11 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
@action
setCurrSelected(x?: number, y?: number) {
// TODO: nda - get rid of svg element in the list?
- if (this._currSelected && this._currSelected.x == x && this._currSelected.y == y) this._currSelected = undefined;
+ if (this._currSelected && this._currSelected.x === x && this._currSelected.y === y) this._currSelected = undefined;
else this._currSelected = x !== undefined && y !== undefined ? { x, y } : undefined;
- this._props.records.forEach(record => record[this._props.axes[0]] === x && record[this._props.axes[1]] === y && (record.selected = true));
+ this._props.records.forEach(record => {
+ record[this._props.axes[0]] === x && record[this._props.axes[1]] === y && (record.selected = true);
+ });
}
drawDataPoints(data: DataPoint[], idx: number, xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>) {
@@ -241,13 +244,13 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
d3.select(this._lineChartRef.current).select('svg').remove();
d3.select(this._lineChartRef.current).select('.tooltip').remove();
- var { xMin, xMax, yMin, yMax } = rangeVals;
+ let { xMin, xMax, yMin, yMax } = rangeVals;
if (xMin === undefined || xMax === undefined || yMin === undefined || yMax === undefined) {
return;
}
// adding svg
- const margin = this._props.margin;
+ const { margin } = this._props;
const svg = (this._lineChartSvg = d3
.select(this._lineChartRef.current)
.append('svg')
@@ -257,18 +260,19 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`));
- var validSecondData;
- if (this._props.axes.length>2){ // for when there are 2 lines on the chart
- var next = this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[2]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
+ let validSecondData;
+ if (this._props.axes.length > 2) {
+ // for when there are 2 lines on the chart
+ const next = this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[2]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
validSecondData = next.filter(d => {
- if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) return false;
+ if (!d.x || isNaN(d.x) || !d.y || isNaN(d.y)) return false;
return true;
});
- var secondDataRange = minMaxRange([validSecondData]);
- if (secondDataRange.xMax!>xMax) xMax = secondDataRange.xMax;
- if (secondDataRange.yMax!>yMax) yMax = secondDataRange.yMax;
- if (secondDataRange.xMin!<xMin) xMin = secondDataRange.xMin;
- if (secondDataRange.yMin!<yMin) yMin = secondDataRange.yMin;
+ const secondDataRange = minMaxRange([validSecondData]);
+ if (secondDataRange.xMax! > xMax) xMax = secondDataRange.xMax;
+ if (secondDataRange.yMax! > yMax) yMax = secondDataRange.yMax;
+ if (secondDataRange.xMin! < xMin) xMin = secondDataRange.xMin;
+ if (secondDataRange.yMin! < yMin) yMin = secondDataRange.yMin;
}
// creating the x and y scales
@@ -285,40 +289,34 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
if (validSecondData) {
drawLine(svg.append('path'), validSecondData, lineGen, true);
this.drawDataPoints(validSecondData, 0, xScale, yScale);
- svg.append('path').attr("stroke", "red");
+ svg.append('path').attr('stroke', 'red');
// legend
- var color = d3.scaleOrdinal()
- .range(["black", "blue"])
- .domain([this._props.axes[1], this._props.axes[2]])
- svg.selectAll("mydots")
+ const color: any = d3.scaleOrdinal().range(['black', 'blue']).domain([this._props.axes[1], this._props.axes[2]]);
+ svg.selectAll('mydots')
.data([this._props.axes[1], this._props.axes[2]])
.enter()
- .append("circle")
- .attr("cx", 5)
- .attr("cy", function(d,i){ return -30 + i*15})
- .attr("r", 7)
- .style("fill", function(d){ return color(d)})
- svg.selectAll("mylabels")
+ .append('circle')
+ .attr('cx', 5)
+ .attr('cy', (d, i) => -30 + i * 15)
+ .attr('r', 7)
+ .style('fill', d => color(d));
+ svg.selectAll('mylabels')
.data([this._props.axes[1], this._props.axes[2]])
.enter()
- .append("text")
- .attr("x", 25)
- .attr("y", function(d,i){ return -30 + i*15})
- .style("fill", function(d){ return color(d)})
- .text(function(d){ return d})
- .attr("text-anchor", "left")
- .style("alignment-baseline", "middle")
+ .append('text')
+ .attr('x', 25)
+ .attr('y', (d, i) => -30 + i * 15)
+ .style('fill', d => color(d))
+ .text(d => d)
+ .attr('text-anchor', 'left')
+ .style('alignment-baseline', 'middle');
}
// get valid data points
const data = dataSet[0];
- var validData = data.filter(d => {
- Object.keys(data[0]).map(key => {
- if (!d[key] || Number.isNaN(d[key])) return false;
- });
- return true;
- });
+ const keys = Object.keys(data[0]);
+ const validData = data.filter(d => !keys.some(key => isNaN(d[key])));
// draw the plot line
drawLine(svg.append('path'), validData, lineGen, false);
@@ -345,7 +343,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
const x0 = bisect(data, xScale.invert(xPos - 5)); // shift x by -5 so that you can reach points on the left-side axis
const d0 = data[x0];
// find .circle-d1 with data-x = d0.x and data-y = d0.y
- const selected = svg.selectAll('.datapoint').filter((d: any) => d['data-x'] === d0.x && d['data-y'] === d0.y);
+ svg.selectAll('.datapoint').filter((d: any) => d['data-x'] === d0.x && d['data-y'] === d0.y);
this.setCurrSelected(d0.x, d0.y);
this.updateTooltip(higlightFocusPt, xScale, d0, yScale, tooltip);
});
@@ -368,7 +366,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
.style('text-anchor', 'middle')
.text(this._props.axes[0]);
svg.append('text')
- .attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')')
+ .attr('transform', 'rotate(-90) translate(0, -10)')
.attr('x', -(height / 2))
.attr('y', -30)
.attr('height', 20)
@@ -394,57 +392,60 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
}
render() {
- var titleAccessor: any = 'dataViz_lineChart_title';
- if (this._props.axes.length == 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1];
- else if (this._props.axes.length > 0) titleAccessor = titleAccessor + this._props.axes[0];
+ let titleAccessor: any = 'dataViz_lineChart_title';
+ if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1];
+ else if (this._props.axes.length > 0) titleAccessor += this._props.axes[0];
if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
const selectedPt = this._currSelected ? `{ ${this._props.axes[0]}: ${this._currSelected.x} ${this._props.axes[1]}: ${this._currSelected.y} }` : 'none';
- var selectedTitle = "";
- if (this._currSelected && this._props.titleCol){
- selectedTitle+= "\n" + this._props.titleCol + ": "
+ let selectedTitle = '';
+ if (this._currSelected && this._props.titleCol) {
+ selectedTitle += '\n' + this._props.titleCol + ': ';
this._tableData.forEach(each => {
- var mapThisEntry = false;
- if (this._currSelected.x==each[this._props.axes[0]] && this._currSelected.y==each[this._props.axes[1]]) mapThisEntry = true;
- else if (this._currSelected.y==each[this._props.axes[0]] && this._currSelected.x==each[this._props.axes[1]]) mapThisEntry = true;
- if (mapThisEntry) selectedTitle += each[this._props.titleCol] + ", ";
- })
- selectedTitle = selectedTitle.slice(0,-1).slice(0,-1);
+ let mapThisEntry = false;
+ if (this._currSelected.x === each[this._props.axes[0]] && this._currSelected.y === each[this._props.axes[1]]) mapThisEntry = true;
+ else if (this._currSelected.y === each[this._props.axes[0]] && this._currSelected.x === each[this._props.axes[1]]) mapThisEntry = true;
+ if (mapThisEntry) selectedTitle += each[this._props.titleCol] + ', ';
+ });
+ selectedTitle = selectedTitle.slice(0, -1).slice(0, -1);
}
- if (this._lineChartData.length > 0 || !this.parentViz || this.parentViz.length == 0) {
+ if (this._lineChartData.length > 0 || !this.parentViz || this.parentViz.length === 0) {
return this._props.axes.length >= 2 && /\d/.test(this._props.records[0][this._props.axes[0]]) && /\d/.test(this._props.records[0][this._props.axes[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])}
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'}
+ color="black"
size={Size.LARGE}
fillWidth
/>
</div>
<div ref={this._lineChartRef} />
- {selectedPt != 'none' ? (
- <div className={'selected-data'}>
+ {selectedPt !== 'none' ? (
+ <div className="selected-data">
{`Selected: ${selectedPt}`}
{`${selectedTitle}`}
<Button
- onClick={e => {
+ onClick={() => {
this._props.vizBox.sidebarBtnDown;
this._props.vizBox.sidebarAddDocument;
- }}></Button>
+ }}
+ />
</div>
) : null}
</div>
) : (
- <span className="chart-container"> {'first use table view to select two numerical axes to plot'}</span>
- );
- } else
- return (
- // when it is a brushed table and the incoming table doesn't have any rows selected
- <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>
+ <span className="chart-container"> first use table view to select two numerical axes to plot</span>
);
+ }
+ return (
+ // when it is a brushed table and the incoming table doesn't have any rows selected
+ <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>
+ );
}
}