From aa3c70399ac2b6a337a9c85fb30f57f82ee44063 Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
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 <sarah_n_richman@brown.edu>
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<LineChartProps> {
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _lineChartRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _lineChartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | 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<LineChartProps> {
         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]]) ? (
                 <div className="chart-container" style={{ width: this._props.width + this._props.margin.right }}>
@@ -376,9 +387,9 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
                     {selectedPt != 'none' ? (
                         <div className={'selected-data'}>
                             {`Selected: ${selectedPt}`}
+                            {`${selectedTitle}`}
                             <Button
                                 onClick={e => {
-                                    console.log('test plzz');
                                     this._props.vizBox.sidebarBtnDown;
                                     this._props.vizBox.sidebarAddDocument;
                                 }}></Button>
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<PieChartProps> {
         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(/\</g, '') : sliceTitle;
-            selected = '{ ';
             Object.keys(this._currSelected).map(key => {
                 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 <sarah_n_richman@brown.edu>
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<LineChartProps> {
         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<TableBoxProps> {
                 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<TableBoxProps> {
                                         <th
                                             key={this.columns.indexOf(col)}
                                             style={{
-                                                color: this._props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this._props.axes.lastElement() === col ? 'darkred' : undefined,
-                                                background: this._props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this._props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
+                                                color: this._props.axes.slice().reverse().lastElement() === col ? 'darkgreen' 
+                                                    : (this._props.axes.length>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<TableBoxProps> {
                                                 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 (
                                                     <td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}>
-- 
cgit v1.2.3-70-g09d2


From 4a0f77ae19934273a34e3a57541e7e8c4172b469 Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
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<LineChartProps> {
         }
     }
 
-    // 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<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));
+            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!<xMin) xMin = secondDataRange.xMin;
+            if (secondDataRange.yMin!<yMin) yMin = secondDataRange.yMin;
+            // drawLine(svg.append('path'), validNext, lineGen);
+            // this.drawDataPoints(validNext, 0, xScale, yScale);
+        }
+
+        // creating the x and y scales
+        const xScale = scaleCreatorNumerical(xMin!, xMax!, 0, width);
+        const yScale = scaleCreatorNumerical(0, yMax!, height, 0);
+        const lineGen = createLineGenerator(xScale, yScale);
+
         // create x and y grids
         xGrid(svg.append('g'), height, xScale);
         yGrid(svg.append('g'), width, yScale);
         xAxisCreator(svg.append('g'), height, xScale);
         yAxisCreator(svg.append('g'), width, yScale);
 
+        if (validSecondData) {
+            drawLine(svg.append('path'), validSecondData, lineGen);
+            this.drawDataPoints(validSecondData, 0, xScale, yScale);
+        }
+
         // get valid data points
         const data = dataSet[0];
-        const lineGen = createLineGenerator(xScale, yScale);
         var validData = data.filter(d => {
             Object.keys(data[0]).map(key => {
                 if (!d[key] || Number.isNaN(d[key])) return false;
@@ -278,19 +298,6 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
             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 <sarah_n_richman@brown.edu>
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<LineChartProps> {
             if (secondDataRange.yMax!>yMax) yMax = secondDataRange.yMax;
             if (secondDataRange.xMin!<xMin) xMin = secondDataRange.xMin;
             if (secondDataRange.yMin!<yMin) yMin = secondDataRange.yMin;
-            // drawLine(svg.append('path'), validNext, lineGen);
-            // this.drawDataPoints(validNext, 0, xScale, yScale);
         }
 
         // creating the x and y scales
@@ -285,8 +283,32 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
         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<LineChartProps> {
         });
 
         // 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<LineChartProps> {
             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<LineChartProps> {
         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<SVGGElement, unknown, null, undefined>, wi
     );
 };
 
-export const drawLine = (p: d3.Selection<SVGPathElement, unknown, null, undefined>, dataPts: DataPoint[], lineGen: d3.Line<DataPoint>) => {
-    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<SVGPathElement, unknown, null, undefined>, dataPts: DataPoint[], lineGen: d3.Line<DataPoint>, 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

