From aa3c70399ac2b6a337a9c85fb30f57f82ee44063 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Tue, 23 Jan 2024 13:22:13 -0500 Subject: data has a title column --- src/client/views/nodes/DataVizBox/components/LineChart.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/nodes/DataVizBox/components/LineChart.tsx') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 2a9a8b354..f23ab94a2 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -28,6 +28,7 @@ export interface LineChartProps { Document: Doc; layoutDoc: Doc; axes: string[]; + titleCol: string; records: { [key: string]: any }[]; width: number; height: number; -- cgit v1.2.3-70-g09d2 From 16c4a0ad4f9c33e6e52241bef8e6b250237226ae Mon Sep 17 00:00:00 2001 From: srichman333 Date: Mon, 29 Jan 2024 13:00:31 -0500 Subject: show selected names for pie charts + line charts --- .../views/nodes/DataVizBox/components/LineChart.tsx | 15 +++++++++++++-- .../views/nodes/DataVizBox/components/PieChart.tsx | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components/LineChart.tsx') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index f23ab94a2..47ac751cd 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -47,7 +47,7 @@ export class LineChart extends ObservableReactComponent { private _disposers: { [key: string]: IReactionDisposer } = {}; private _lineChartRef: React.RefObject = React.createRef(); private _lineChartSvg: d3.Selection | undefined; - @observable _currSelected: SelectedDataPoint | undefined = undefined; + @observable _currSelected: any | undefined = undefined; // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates constructor(props: any) { super(props); @@ -357,6 +357,17 @@ export class LineChart extends ObservableReactComponent { else if (this._props.axes.length > 0) titleAccessor = 'dataViz_lineChart_title' + 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 + ": " + 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); + } 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]]) ? (
@@ -376,9 +387,9 @@ export class LineChart extends ObservableReactComponent { {selectedPt != 'none' ? (
{`Selected: ${selectedPt}`} + {`${selectedTitle}`} diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index 55c2208a3..f98d51123 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -340,14 +340,28 @@ export class PieChart extends ObservableReactComponent { var selected: string; var curSelectedSliceName = ''; if (this._currSelected) { + selected = '{ '; const sliceTitle = this._currSelected[this._props.axes[0]]; curSelectedSliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\ { key != '' ? (selected += key + ': ' + this._currSelected[key] + ', ') : ''; }); selected = selected.substring(0, selected.length - 2); selected += ' }'; + if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10) && this._pieChartData){ + var percentField = Object.keys(this._pieChartData[0])[0]; + var descriptionField = Object.keys(this._pieChartData[0])[1]!; + selected+= "\n" + this._props.titleCol + ": " + this._tableData.forEach(each => { + if (this._currSelected[percentField]==each[percentField]) { + if (descriptionField){ + if (this._currSelected[descriptionField]==each[descriptionField]) selected+= each[this._props.titleCol] + ", "; + } + else selected+= each[this._props.titleCol] + ", "; + } + }) + selected = selected.slice(0,-1).slice(0,-1); + } } else selected = 'none'; var selectedSliceColor; var sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); -- cgit v1.2.3-70-g09d2 From 6d5a43b114b54820e3578862a5429eb096c71058 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Wed, 31 Jan 2024 17:36:41 -0500 Subject: can select 3 columns (+ beginning of basic 2 columns displayed on y axis in linechart) --- .../views/nodes/DataVizBox/components/LineChart.tsx | 19 ++++++++++++++++--- .../views/nodes/DataVizBox/components/TableBox.tsx | 18 ++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components/LineChart.tsx') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 47ac751cd..8d6671e65 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -272,12 +272,25 @@ export class LineChart extends ObservableReactComponent { const data = dataSet[0]; const lineGen = createLineGenerator(xScale, yScale); var validData = data.filter(d => { - var valid = true; Object.keys(data[0]).map(key => { - if (!d[key] || Number.isNaN(d[key])) valid = false; + if (!d[key] || Number.isNaN(d[key])) return false; }); - return valid; + return true; }); + + if (this._props.axes.length>2){ + 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)); + var validNext = next.filter(d => { + // Object.keys(next[0]).map(key => { + // if (!d[key] || Number.isNaN(d[key])) return false; + // }); + if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) valid = false; + return true; + }); + drawLine(svg.append('path'), validNext, lineGen); + this.drawDataPoints(validNext, 0, xScale, yScale); + } + // draw the plot line drawLine(svg.append('path'), validData, lineGen); // draw the datapoint circle diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index c20509029..1b239b5e5 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -163,7 +163,7 @@ export class TableBox extends ObservableReactComponent { else{ const newAxes = this._props.axes; if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1); - else if (newAxes.length > 1) newAxes[1] = col; + else if (newAxes.length > 2) newAxes[newAxes.length-1] = col; else newAxes.push(col); this._props.selectAxes(newAxes); } @@ -220,8 +220,15 @@ export class TableBox extends ObservableReactComponent { 2 && this._props.axes.lastElement() === col) ? 'darkred' + : (this._props.axes.lastElement()===col || (this._props.axes.length>2 && this._props.axes[1]==col))? 'darkblue' : undefined, + background: this._props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' + : (this._props.axes.length>2 && this._props.axes.lastElement() === col) ? '#Fbdbdb' + : (this._props.axes.lastElement()===col || (this._props.axes.length>2 && this._props.axes[1]==col))? '#c6ebf7' : undefined, + // blue: #ADD8E6 + // green: #E3fbdb + // red: #Fbdbdb fontWeight: 'bolder', border: '3px solid black', }} @@ -243,7 +250,10 @@ export class TableBox extends ObservableReactComponent { background: NumListCast(this._props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '', }}> {this.columns.map(col => { - var colSelected = this._props.axes.length > 1 ? this._props.axes[0] == col || this._props.axes[1] == col : this._props.axes.length > 0 ? this._props.axes[0] == col : false; + var colSelected = false; + if (this._props.axes.length>2) colSelected = this._props.axes[0]==col || this._props.axes[1]==col || this._props.axes[2]==col; + else if (this._props.axes.length>1) colSelected = this._props.axes[0]==col || this._props.axes[1]==col; + else if (this._props.axes.length>0) colSelected = this._props.axes[0]==col; if (this._props.titleCol==col) colSelected = true; return ( -- cgit v1.2.3-70-g09d2 From 4a0f77ae19934273a34e3a57541e7e8c4172b469 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Wed, 31 Jan 2024 17:56:11 -0500 Subject: 2 lines on line charts --- .../nodes/DataVizBox/components/LineChart.tsx | 47 +++++++++++++--------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components/LineChart.tsx') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 8d6671e65..dd6a6b007 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -236,21 +236,16 @@ export class LineChart extends ObservableReactComponent { } } - // TODO: nda - can use d3.create() to create html element instead of appending drawChart = (dataSet: any[][], rangeVals: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }, width: number, height: number) => { // clearing tooltip and the current chart d3.select(this._lineChartRef.current).select('svg').remove(); d3.select(this._lineChartRef.current).select('.tooltip').remove(); - const { xMin, xMax, yMin, yMax } = rangeVals; + var { xMin, xMax, yMin, yMax } = rangeVals; if (xMin === undefined || xMax === undefined || yMin === undefined || yMax === undefined) { return; } - // creating the x and y scales - const xScale = scaleCreatorNumerical(xMin, xMax, 0, width); - const yScale = scaleCreatorNumerical(0, yMax, height, 0); - // adding svg const margin = this._props.margin; const svg = (this._lineChartSvg = d3 @@ -262,15 +257,40 @@ export class LineChart extends ObservableReactComponent { .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)); + validSecondData = next.filter(d => { + if (!d.x || Number.isNaN(d.x) || !d.y || Number.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! { Object.keys(data[0]).map(key => { if (!d[key] || Number.isNaN(d[key])) return false; @@ -278,19 +298,6 @@ export class LineChart extends ObservableReactComponent { return true; }); - if (this._props.axes.length>2){ - 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)); - var validNext = next.filter(d => { - // Object.keys(next[0]).map(key => { - // if (!d[key] || Number.isNaN(d[key])) return false; - // }); - if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) valid = false; - return true; - }); - drawLine(svg.append('path'), validNext, lineGen); - this.drawDataPoints(validNext, 0, xScale, yScale); - } - // draw the plot line drawLine(svg.append('path'), validData, lineGen); // draw the datapoint circle -- cgit v1.2.3-70-g09d2 From a1939f7547413aa97c8d8967f57b4bb5aea0cdef Mon Sep 17 00:00:00 2001 From: srichman333 Date: Thu, 1 Feb 2024 00:15:05 -0500 Subject: 2 lines on line chart have a legend --- .../nodes/DataVizBox/components/LineChart.tsx | 34 ++++++++++++++++++---- src/client/views/nodes/DataVizBox/utils/D3Utils.ts | 4 +-- 2 files changed, 30 insertions(+), 8 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components/LineChart.tsx') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index dd6a6b007..8268d22b6 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -269,8 +269,6 @@ export class LineChart extends ObservableReactComponent { if (secondDataRange.yMax!>yMax) yMax = secondDataRange.yMax; if (secondDataRange.xMin! { yAxisCreator(svg.append('g'), width, yScale); if (validSecondData) { - drawLine(svg.append('path'), validSecondData, lineGen); + drawLine(svg.append('path'), validSecondData, lineGen, true); this.drawDataPoints(validSecondData, 0, xScale, yScale); + 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") + .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") + .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") } // get valid data points @@ -299,7 +321,7 @@ export class LineChart extends ObservableReactComponent { }); // draw the plot line - drawLine(svg.append('path'), validData, lineGen); + drawLine(svg.append('path'), validData, lineGen, false); // draw the datapoint circle this.drawDataPoints(validData, 0, xScale, yScale); @@ -312,7 +334,7 @@ export class LineChart extends ObservableReactComponent { const xPos = d3.pointer(e)[0]; const x0 = Math.min(data.length - 1, 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]; - if (!d0) return; + if (d0) this.updateTooltip(higlightFocusPt, xScale, d0, yScale, tooltip); this.updateTooltip(higlightFocusPt, xScale, d0, yScale, tooltip); }); @@ -348,7 +370,7 @@ export class LineChart extends ObservableReactComponent { svg.append('text') .attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')') .attr('x', -(height / 2)) - .attr('y', -20) + .attr('y', -30) .attr('height', 20) .attr('width', 20) .style('text-anchor', 'middle') diff --git a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts index 10bfb0c64..336935d23 100644 --- a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts +++ b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts @@ -61,6 +61,6 @@ export const yGrid = (g: d3.Selection, wi ); }; -export const drawLine = (p: d3.Selection, dataPts: DataPoint[], lineGen: d3.Line) => { - p.datum(dataPts).attr('fill', 'none').attr('stroke', 'rgba(53, 162, 235, 0.5)').attr('stroke-width', 2).attr('class', 'line').attr('d', lineGen); +export const drawLine = (p: d3.Selection, dataPts: DataPoint[], lineGen: d3.Line, extra: boolean) => { + p.datum(dataPts).attr('fill', 'none').attr('stroke', 'rgba(53, 162, 235, 0.5)').attr('stroke-width', 2).attr('stroke', extra? 'blue' : 'black').attr('class', 'line').attr('d', lineGen); }; -- cgit v1.2.3-70-g09d2