From e6d1dd82f5d472bddaf66f9210142249d6fa09aa Mon Sep 17 00:00:00 2001
From: Naafiyan Ahmed <naafiyan@gmail.com>
Date: Wed, 6 Jul 2022 20:21:04 -0400
Subject: added endpoint routes for csv and integrated chartjs

---
 src/client/views/nodes/DataVizBox/HistogramBox.tsx | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'src/client/views/nodes/DataVizBox/HistogramBox.tsx')

diff --git a/src/client/views/nodes/DataVizBox/HistogramBox.tsx b/src/client/views/nodes/DataVizBox/HistogramBox.tsx
index 00dc2ef46..4488323fe 100644
--- a/src/client/views/nodes/DataVizBox/HistogramBox.tsx
+++ b/src/client/views/nodes/DataVizBox/HistogramBox.tsx
@@ -3,6 +3,7 @@ import { observer } from "mobx-react";
 import * as React from "react";
 import { Doc } from "../../../../fields/Doc";
 import { NumCast } from "../../../../fields/Types";
+import { DragManager } from "../../../util/DragManager";
 import "./HistogramBox.scss";
 
 interface HistogramBoxProps {
@@ -15,6 +16,8 @@ interface HistogramBoxProps {
 
 
 export class HistogramBox extends React.Component<HistogramBoxProps> {
+    private _dropXDispoer?: DragManager.DragDropDisposer;
+    private _dropYDispoer?: DragManager.DragDropDisposer;
 
     private origin = {x: 0.1 * this.width, y: 0.9 * this.height};
 
-- 
cgit v1.2.3-70-g09d2


From ba8cb4194062b0f939afd136a269625f9f26dcaa Mon Sep 17 00:00:00 2001
From: Naafiyan Ahmed <naafiyan@gmail.com>
Date: Mon, 25 Jul 2022 19:10:55 -0400
Subject: cleaned up code and moved files around

---
 src/client/views/nodes/DataVizBox/ChartBox.tsx     | 101 +-------
 .../views/nodes/DataVizBox/ChartInterface.ts       |  33 +++
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   |   2 +-
 src/client/views/nodes/DataVizBox/DrawHelper.ts    | 247 -------------------
 .../views/nodes/DataVizBox/HistogramBox.scss       |  18 --
 src/client/views/nodes/DataVizBox/HistogramBox.tsx | 162 -------------
 .../nodes/DataVizBox/HistogramBoxPrimitives.scss   |   0
 .../nodes/DataVizBox/HistogramBoxPrimitives.tsx    |  16 --
 .../nodes/DataVizBox/HistogramLabelPrimitives.scss |   0
 .../nodes/DataVizBox/HistogramLabelPrimitives.tsx  |  13 -
 src/client/views/nodes/DataVizBox/LineChart.tsx    | 269 --------------------
 src/client/views/nodes/DataVizBox/TableBox.scss    |  22 --
 src/client/views/nodes/DataVizBox/TableBox.tsx     |  37 ---
 .../views/nodes/DataVizBox/components/Chart.scss   |  10 +
 .../nodes/DataVizBox/components/LineChart.tsx      | 270 +++++++++++++++++++++
 .../nodes/DataVizBox/components/TableBox.scss      |  22 ++
 .../views/nodes/DataVizBox/components/TableBox.tsx |  37 +++
 src/client/views/nodes/DataVizBox/utils/D3Utils.ts |  12 +-
 18 files changed, 386 insertions(+), 885 deletions(-)
 create mode 100644 src/client/views/nodes/DataVizBox/ChartInterface.ts
 delete mode 100644 src/client/views/nodes/DataVizBox/DrawHelper.ts
 delete mode 100644 src/client/views/nodes/DataVizBox/HistogramBox.scss
 delete mode 100644 src/client/views/nodes/DataVizBox/HistogramBox.tsx
 delete mode 100644 src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.scss
 delete mode 100644 src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.tsx
 delete mode 100644 src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.scss
 delete mode 100644 src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.tsx
 delete mode 100644 src/client/views/nodes/DataVizBox/LineChart.tsx
 delete mode 100644 src/client/views/nodes/DataVizBox/TableBox.scss
 delete mode 100644 src/client/views/nodes/DataVizBox/TableBox.tsx
 create mode 100644 src/client/views/nodes/DataVizBox/components/Chart.scss
 create mode 100644 src/client/views/nodes/DataVizBox/components/LineChart.tsx
 create mode 100644 src/client/views/nodes/DataVizBox/components/TableBox.scss
 create mode 100644 src/client/views/nodes/DataVizBox/components/TableBox.tsx

(limited to 'src/client/views/nodes/DataVizBox/HistogramBox.tsx')

diff --git a/src/client/views/nodes/DataVizBox/ChartBox.tsx b/src/client/views/nodes/DataVizBox/ChartBox.tsx
index f2450bc7c..a2e4fd73c 100644
--- a/src/client/views/nodes/DataVizBox/ChartBox.tsx
+++ b/src/client/views/nodes/DataVizBox/ChartBox.tsx
@@ -1,11 +1,10 @@
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, HeightSym } from '../../../../fields/Doc';
-import { ChartJSOrUndefined } from 'react-chartjs-2/dist/types';
 import { action, computed, observable } from 'mobx';
 import { Cast, NumCast, StrCast } from '../../../../fields/Types';
-import { CategoricalChartState } from 'recharts/types/chart/generateCategoricalChart';
-import { LineChart } from './LineChart';
+import { LineChart } from './components/LineChart';
+import { Chart, ChartData } from './ChartInterface';
 
 export interface ChartBoxProps {
     rootDoc: Doc;
@@ -15,26 +14,11 @@ export interface ChartBoxProps {
     getAnchor: () => Doc;
 }
 
-const primaryColor = 'rgba(53, 162, 235, 0.5)';
-const selectedColor = 'rgba(255, 99, 132, 0.5)';
-
-export interface RechartData {
-    name: string | number;
-    y: number;
-}
-
 export interface DataPoint {
     x: number;
     y: number;
 }
 
-export interface ChartData {
-    xLabel: string;
-    yLabel: string;
-    data: DataPoint[];
-    tooltipContent: (data: DataPoint) => string;
-}
-
 @observer
 export class ChartBox extends React.Component<ChartBoxProps> {
     @observable private _chartData: ChartData | undefined = undefined;
@@ -55,7 +39,7 @@ export class ChartBox extends React.Component<ChartBoxProps> {
         }
     }
 
-    setCurrChart(chart: LineChart | undefined) {
+    setCurrChart(chart: Chart | undefined) {
         // this.currChart = chart;
     }
 
@@ -69,17 +53,15 @@ export class ChartBox extends React.Component<ChartBoxProps> {
         const data: ChartData = {
             xLabel: '',
             yLabel: '',
-            data: [],
-            tooltipContent: (data: DataPoint) => {
-                return `<b>x: ${data.x} y: ${data.y}</b>`;
-            },
+            data: [[]],
         };
 
         if (this.props.pairs && this.props.pairs.length > 0) {
             data.xLabel = 'x';
             data.yLabel = 'y';
             this.props.pairs.forEach(pair => {
-                data.data.push({ x: pair.x, y: pair.y });
+                // TODO: nda - add actual support for multiple sets of data
+                data.data[0].push({ x: pair.x, y: pair.y });
             });
         }
 
@@ -87,30 +69,7 @@ export class ChartBox extends React.Component<ChartBoxProps> {
         this.props.rootDoc._chartData = JSON.stringify(data);
     }
 
-    // @action
-    // generateChartJsData() {
-    //     if (this.props.rootDoc._chartData) {
-    //         // parse the string into a json object
-    //         this._chartJsData = JSON.parse(StrCast(this.props.rootDoc._chartData));
-    //         this._prevColor = StrCast(this.props.rootDoc._prevColor);
-    //         this._prevIndex = JSON.parse(StrCast(this.props.rootDoc._prevIndex));
-    //         return;
-    //     }
-    //     const labels = this.props.pairs.map(p => p.x);
-    //     const dataset = {
-    //         label: 'Dataset 1',
-    //         data: this.props.pairs.map(p => p.y),
-    //         backgroundColor: this.props.pairs.map(p => primaryColor),
-    //     };
-    //     const data = {
-    //         labels,
-    //         datasets: [dataset],
-    //     };
-    //     this._chartJsData = data;
-    // }
-
     componentDidMount() {
-        // this.generateChartJsData();
         this.generateChartData();
         // setting timeout to allow rerender cycle of the actual chart tof inish
         setTimeout(() => {
@@ -127,21 +86,6 @@ export class ChartBox extends React.Component<ChartBoxProps> {
         this.props.rootDoc._currChartView = e.currentTarget.value.toLowerCase();
     };
 
-    onMouseMove = (e: CategoricalChartState) => {
-        console.log(e);
-
-        // pops up at 526 when it should be at 263
-        // at 100%scale it pops up at 526 but mouse shows 263 at 50% scale
-        if (e.chartX && e.chartY) {
-            e.chartX += 263;
-            e.chartY += 263;
-        }
-        // if (e.chartX && e.chartY) {
-        //     e.chartX -= 200;
-        //     e.chartY -= 200;
-        // }
-    };
-
     scrollFocus(doc: Doc, smooth: boolean) {}
 
     handleDotClick = (e: any) => {
@@ -152,37 +96,6 @@ export class ChartBox extends React.Component<ChartBoxProps> {
         return this.currChart?._getAnchor();
     }
 
-    // handleTextClick = (e: any) => {
-    //     console.log(e);
-    // }
-
-    // @computed get reLineChart() {
-    //     return (
-    //         // <ResponsiveContainer width="80%" height="80%">
-    //         <LineChart
-    //             width={500}
-    //             height={300}
-    //             data={this._chartData}
-    //             margin={{
-    //                 top: 5,
-    //                 right: 30,
-    //                 left: 20,
-    //                 bottom: 5,
-    //             }}
-    //             onMouseDown={e => console.log(e)}
-    //             onMouseMove={e => this.onMouseMove(e)}>
-    //             <CartesianGrid strokeDasharray="3 3" />
-    //             <XAxis dataKey="name" onMouseDown={e => console.log(e)} />
-    //             <YAxis />
-    //             <Tooltip />
-    //             <Legend />
-    //             <Line type="monotone" dataKey="y" stroke="#8884d8" activeDot={{ r: 8, onClick: this.handleDotClick }} />
-    //             {/* <Line type="monotone" dataKey="uv" stroke="#82ca9d" /> */}
-    //         </LineChart>
-    //         // </ResponsiveContainer>
-    //     );
-    // }
-
     render() {
         if (this.props.pairs && this._chartData) {
             let width = NumCast(this.props.rootDoc._width);
@@ -200,7 +113,7 @@ export class ChartBox extends React.Component<ChartBoxProps> {
                             <Bar ref={this._chartRef} options={this.options} data={this._chartJsData} onClick={e => this.onClick(e)} />
                         )} */}
                         {/* {this.reLineChart} */}
-                        <LineChart margin={margin} width={width} height={height} data={this._chartData} setCurrChart={this.setCurrChart} dataDoc={this.props.dataDoc} fieldKey={'data'} getAnchor={this.props.getAnchor} />
+                        <LineChart margin={margin} width={width} height={height} chartData={this._chartData} setCurrChart={this.setCurrChart} dataDoc={this.props.dataDoc} fieldKey={'data'} getAnchor={this.props.getAnchor} />
                     </div>
                     <button onClick={e => this.onClickChangeChart(e)} value="line">
                         Line
diff --git a/src/client/views/nodes/DataVizBox/ChartInterface.ts b/src/client/views/nodes/DataVizBox/ChartInterface.ts
new file mode 100644
index 000000000..6e37f966c
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/ChartInterface.ts
@@ -0,0 +1,33 @@
+import { Doc } from '../../../../fields/Doc';
+import { DataPoint } from './ChartBox';
+import { LineChart } from './components/LineChart';
+
+export interface Chart {
+    tooltipContent: (data: DataPoint) => string;
+    drawChart: () => void;
+    height: number;
+    width: number;
+}
+
+export interface ChartProps {
+    chartData: ChartData;
+    width: number;
+    height: number;
+    dataDoc: Doc;
+    fieldKey: string;
+    // returns linechart component but should be generic chart
+    setCurrChart: (chart: Chart) => void;
+    getAnchor: () => Doc;
+    margin: {
+        top: number;
+        right: number;
+        bottom: number;
+        left: number;
+    };
+}
+
+export interface ChartData {
+    xLabel: string;
+    yLabel: string;
+    data: DataPoint[][];
+}
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 4883385bb..1d9b309ce 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -9,7 +9,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxBaseComponent } from '../../DocComp
 import { FieldViewProps, FieldView } from '../FieldView';
 import { ChartBox } from './ChartBox';
 import './DataVizBox.scss';
-import { TableBox } from './TableBox';
+import { TableBox } from './components/TableBox';
 
 enum DataVizView {
     TABLE = 'table',
diff --git a/src/client/views/nodes/DataVizBox/DrawHelper.ts b/src/client/views/nodes/DataVizBox/DrawHelper.ts
deleted file mode 100644
index 595cecebf..000000000
--- a/src/client/views/nodes/DataVizBox/DrawHelper.ts
+++ /dev/null
@@ -1,247 +0,0 @@
-export class PIXIPoint {
-    public get x() { return this.coords[0]; }
-    public get y() { return this.coords[1]; }
-    public set x(value: number) { this.coords[0] = value; }
-    public set y(value: number) { this.coords[1] = value; }
-    public coords: number[] = [0, 0];
-    constructor(x: number, y: number) {
-        this.coords[0] = x;
-        this.coords[1] = y;
-    }
-}
-
-export class PIXIRectangle {
-    public x: number;
-    public y: number;
-    public width: number;
-    public height: number;
-    public get left() { return this.x; }
-    public get right() { return this.x + this.width; }
-    public get top() { return this.y; }
-    public get bottom() { return this.top + this.height; }
-    public static get EMPTY() { return new PIXIRectangle(0, 0, -1, -1); }
-    constructor(x: number, y: number, width: number, height: number) {
-        this.x = x;
-        this.y = y;
-        this.width = width;
-        this.height = height;
-    }
-}
-
-export class MathUtil {
-
-    public static EPSILON: number = 0.001;
-
-    public static Sign(value: number): number {
-        return value >= 0 ? 1 : -1;
-    }
-
-    public static AddPoint(p1: PIXIPoint, p2: PIXIPoint, inline: boolean = false): PIXIPoint {
-        if (inline) {
-            p1.x += p2.x;
-            p1.y += p2.y;
-            return p1;
-        }
-        else {
-            return new PIXIPoint(p1.x + p2.x, p1.y + p2.y);
-        }
-    }
-
-    public static Perp(p1: PIXIPoint): PIXIPoint {
-        return new PIXIPoint(-p1.y, p1.x);
-    }
-
-    public static DividePoint(p1: PIXIPoint, by: number, inline: boolean = false): PIXIPoint {
-        if (inline) {
-            p1.x /= by;
-            p1.y /= by;
-            return p1;
-        }
-        else {
-            return new PIXIPoint(p1.x / by, p1.y / by);
-        }
-    }
-
-    public static MultiplyConstant(p1: PIXIPoint, by: number, inline: boolean = false) {
-        if (inline) {
-            p1.x *= by;
-            p1.y *= by;
-            return p1;
-        }
-        else {
-            return new PIXIPoint(p1.x * by, p1.y * by);
-        }
-    }
-
-    public static SubtractPoint(p1: PIXIPoint, p2: PIXIPoint, inline: boolean = false): PIXIPoint {
-        if (inline) {
-            p1.x -= p2.x;
-            p1.y -= p2.y;
-            return p1;
-        }
-        else {
-            return new PIXIPoint(p1.x - p2.x, p1.y - p2.y);
-        }
-    }
-
-    public static Area(rect: PIXIRectangle): number {
-        return rect.width * rect.height;
-    }
-
-    public static DistToLineSegment(v: PIXIPoint, w: PIXIPoint, p: PIXIPoint) {
-        // Return minimum distance between line segment vw and point p
-        var l2 = MathUtil.DistSquared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
-        if (l2 === 0.0) return MathUtil.Dist(p, v);   // v === w case
-        // Consider the line extending the segment, parameterized as v + t (w - v).
-        // We find projection of point p onto the line. 
-        // It falls where t = [(p-v) . (w-v)] / |w-v|^2
-        // We clamp t from [0,1] to handle points outside the segment vw.
-        var dot = MathUtil.Dot(
-            MathUtil.SubtractPoint(p, v),
-            MathUtil.SubtractPoint(w, v)) / l2;
-        var t = Math.max(0, Math.min(1, dot));
-        // Projection falls on the segment
-        var projection = MathUtil.AddPoint(v,
-            MathUtil.MultiplyConstant(
-                MathUtil.SubtractPoint(w, v), t));
-        return MathUtil.Dist(p, projection);
-    }
-
-    public static LineSegmentIntersection(ps1: PIXIPoint, pe1: PIXIPoint, ps2: PIXIPoint, pe2: PIXIPoint): PIXIPoint | undefined {
-        var a1 = pe1.y - ps1.y;
-        var b1 = ps1.x - pe1.x;
-
-        var a2 = pe2.y - ps2.y;
-        var b2 = ps2.x - pe2.x;
-
-        var delta = a1 * b2 - a2 * b1;
-        if (delta === 0) {
-            return undefined;
-        }
-        var c2 = a2 * ps2.x + b2 * ps2.y;
-        var c1 = a1 * ps1.x + b1 * ps1.y;
-        var invdelta = 1 / delta;
-        return new PIXIPoint((b2 * c1 - b1 * c2) * invdelta, (a1 * c2 - a2 * c1) * invdelta);
-    }
-
-    public static PointInPIXIRectangle(p: PIXIPoint, rect: PIXIRectangle): boolean {
-        if (p.x < rect.left - this.EPSILON) {
-            return false;
-        }
-        if (p.x > rect.right + this.EPSILON) {
-            return false;
-        }
-        if (p.y < rect.top - this.EPSILON) {
-            return false;
-        }
-        if (p.y > rect.bottom + this.EPSILON) {
-            return false;
-        }
-
-        return true;
-    }
-
-    public static LinePIXIRectangleIntersection(lineFrom: PIXIPoint, lineTo: PIXIPoint, rect: PIXIRectangle): Array<PIXIPoint> {
-        var r1 = new PIXIPoint(rect.left, rect.top);
-        var r2 = new PIXIPoint(rect.right, rect.top);
-        var r3 = new PIXIPoint(rect.right, rect.bottom);
-        var r4 = new PIXIPoint(rect.left, rect.bottom);
-        var ret = new Array<PIXIPoint>();
-        var dist = this.Dist(lineFrom, lineTo);
-        var inter = this.LineSegmentIntersection(lineFrom, lineTo, r1, r2);
-        if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
-            ret.push(inter);
-        }
-        inter = this.LineSegmentIntersection(lineFrom, lineTo, r2, r3);
-        if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
-            ret.push(inter);
-        }
-        inter = this.LineSegmentIntersection(lineFrom, lineTo, r3, r4);
-        if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
-            ret.push(inter);
-        }
-        inter = this.LineSegmentIntersection(lineFrom, lineTo, r4, r1);
-        if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
-            ret.push(inter);
-        }
-        return ret;
-    }
-
-    public static Intersection(rect1: PIXIRectangle, rect2: PIXIRectangle): PIXIRectangle {
-        const left = Math.max(rect1.x, rect2.x);
-        const right = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
-        const top = Math.max(rect1.y, rect2.y);
-        const bottom = Math.min(rect1.y + rect1.height, rect2.y + rect2.height);
-        return new PIXIRectangle(left, top, right - left, bottom - top);
-    }
-
-    public static Dist(p1: PIXIPoint, p2: PIXIPoint): number {
-        return Math.sqrt(MathUtil.DistSquared(p1, p2));
-    }
-
-    public static Dot(p1: PIXIPoint, p2: PIXIPoint): number {
-        return p1.x * p2.x + p1.y * p2.y;
-    }
-
-    public static Normalize(p1: PIXIPoint) {
-        var d = this.Length(p1);
-        return new PIXIPoint(p1.x / d, p1.y / d);
-    }
-
-    public static Length(p1: PIXIPoint): number {
-        return Math.sqrt(p1.x * p1.x + p1.y * p1.y);
-    }
-
-    public static DistSquared(p1: PIXIPoint, p2: PIXIPoint): number {
-        const a = p1.x - p2.x;
-        const b = p1.y - p2.y;
-        return (a * a + b * b);
-    }
-
-    public static RectIntersectsRect(r1: PIXIRectangle, r2: PIXIRectangle): boolean {
-        return !(r2.x > r1.x + r1.width ||
-            r2.x + r2.width < r1.x ||
-            r2.y > r1.y + r1.height ||
-            r2.y + r2.height < r1.y);
-    }
-
-    public static ArgMin(temp: number[]): number {
-        let index = 0;
-        let value = temp[0];
-        for (let i = 1; i < temp.length; i++) {
-            if (temp[i] < value) {
-                value = temp[i];
-                index = i;
-            }
-        }
-        return index;
-    }
-
-    public static ArgMax(temp: number[]): number {
-        let index = 0;
-        let value = temp[0];
-        for (let i = 1; i < temp.length; i++) {
-            if (temp[i] > value) {
-                value = temp[i];
-                index = i;
-            }
-        }
-        return index;
-    }
-
-    public static Combinations<T>(chars: T[]) {
-        let result = new Array<T>();
-        let f = (prefix: any, chars: any) => {
-            for (let i = 0; i < chars.length; i++) {
-                result.push(prefix.concat(chars[i]));
-                f(prefix.concat(chars[i]), chars.slice(i + 1));
-            }
-        };
-        f([], chars);
-        return result;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/HistogramBox.scss b/src/client/views/nodes/DataVizBox/HistogramBox.scss
deleted file mode 100644
index 5aac9dc77..000000000
--- a/src/client/views/nodes/DataVizBox/HistogramBox.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-// change the stroke color of line-svg class
-.svgLine {
-    position: absolute;
-    background: darkGray;
-    stroke: #000;
-    stroke-width: 1px;
-    width:100%;
-    height:100%;
-    opacity: 0.4;
-}
-
-.svgContainer {
-    position: absolute;
-    top:0;
-    left:0;
-    width:100%;
-    height: 100%;
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/HistogramBox.tsx b/src/client/views/nodes/DataVizBox/HistogramBox.tsx
deleted file mode 100644
index 4488323fe..000000000
--- a/src/client/views/nodes/DataVizBox/HistogramBox.tsx
+++ /dev/null
@@ -1,162 +0,0 @@
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-import { Doc } from "../../../../fields/Doc";
-import { NumCast } from "../../../../fields/Types";
-import { DragManager } from "../../../util/DragManager";
-import "./HistogramBox.scss";
-
-interface HistogramBoxProps {
-    rootDoc: Doc;
-    pairs: {
-        x: number,
-        y: number
-    }[]
-}
-
-
-export class HistogramBox extends React.Component<HistogramBoxProps> {
-    private _dropXDispoer?: DragManager.DragDropDisposer;
-    private _dropYDispoer?: DragManager.DragDropDisposer;
-
-    private origin = {x: 0.1 * this.width, y: 0.9 * this.height};
-
-    @computed get width() {
-        return NumCast(this.props.rootDoc.width);
-    }
-
-    @computed get height() {
-        return NumCast(this.props.rootDoc.height);
-    }
-
-    @computed get x() {
-        return NumCast(this.props.rootDoc.x);
-    }
-
-    @computed get y() {
-        return NumCast(this.props.rootDoc.y);
-    }
-
-    @computed get generatePoints() {
-        // evenly distribute points along the x axis
-        const xVals: number[] = this.props.pairs.map(p => p.x);
-        const yVals: number[] = this.props.pairs.map(p => p.y);
-
-        const xMin = Math.min(...xVals);
-        const xMax = Math.max(...xVals);
-        const yMin = Math.min(...yVals);
-        const yMax = Math.max(...yVals);
-
-        const xRange = xMax - xMin;
-        const yRange = yMax - yMin;
-
-        const xScale = this.width / xRange;
-        const yScale = this.height / yRange;
-
-        const xOffset = (this.x + (0.1 * this.width)) - xMin * xScale;
-        const yOffset = (this.y + (0.25 * this.height)) - yMin * yScale;
-
-        const points: {
-            x: number,
-            y: number
-        }[] = this.props.pairs.map(p => {
-            return {
-                x: (p.x * xScale + xOffset) + this.origin.x,
-                y: (p.y * yScale + yOffset)
-            }
-        });
-
-        return points;
-    }
-
-    @computed get generateGraphLine() {
-        const points = this.generatePoints;
-        // loop through points and create a line from each point to the next
-        let lines: {
-            x1: number,
-            y1: number,
-            x2: number,
-            y2: number
-        }[] = [];
-        for (let i = 0; i < points.length - 1; i++) {
-            lines.push({
-                x1: points[i].x,
-                y1: points[i].y,
-                x2: points[i + 1].x,
-                y2: points[i + 1].y
-            });
-        }
-        // generate array of svg with lines
-        let svgLines: JSX.Element[] = [];
-        for (let i = 0; i < lines.length; i++) {
-            svgLines.push(
-                <line
-                    className="svgLine"
-                    key={i}
-                    x1={lines[i].x1}
-                    y1={lines[i].y1}
-                    x2={lines[i].x2}
-                    y2={lines[i].y2}
-                    stroke="black"
-                    strokeWidth={2}
-                />
-            );
-        }
-
-        let res = [];
-        for (let i = 0; i < svgLines.length; i++) {
-            res.push(<svg className="svgContainer">{svgLines[i]}</svg>)
-        }
-        return res;
-    }
-
-    @computed get generateAxes() {       
-
-        const xAxis = {
-            x1: 0.1 * this.width,
-            x2: 0.9 * this.width,
-            y1: 0.9 * this.height,
-            y2: 0.9 * this.height,
-        };
-
-        const yAxis = {
-            x1: 0.1 * this.width,
-            x2: 0.1 * this.width,
-            y1: 0.25 * this.height,
-            y2: 0.9 * this.height,
-        };
-
-
-        return (
-            [
-                (<svg className="svgContainer">
-                    {/* <line className="svgLine" x1={yAxis} y1={xAxis} x2={this.width - (0.1 * this.width)} y2={xAxis} /> */}
-                    <line className="svgLine" x1={xAxis.x1} y1={xAxis.y1} x2={xAxis.x2} y2={xAxis.y2}/>
-
-                    {/* <line className="svgLine" x1={yAxis} y1={xAxis} x2={yAxis} y2={this.y + 50} /> */}
-                </svg>),
-                (
-                <svg className="svgContainer">
-                    <line className="svgLine" x1={yAxis.x1} y1={yAxis.y1} x2={yAxis.x2} y2={yAxis.y2} />
-                {/* <line className="svgLine" x1={yAxis} y1={xAxis} x2={yAxis} y2={this.y + 50} /> */}
-                </svg>)
-            ]
-        )
-    }
-
-
-    render() {
-        return (
-            <div>histogram box
-                {/* <svg className="svgContainer">
-                    {this.generateSVGLine}
-                </svg> */}
-                {this.generateAxes[0]}
-                {this.generateAxes[1]}
-                {this.generateGraphLine.map(line => line)}
-            </div>
-        )
-            
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.scss b/src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.scss
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.tsx b/src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.tsx
deleted file mode 100644
index ac1b7699b..000000000
--- a/src/client/views/nodes/DataVizBox/HistogramBoxPrimitives.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { observer } from "mobx-react";
-import * as React from "react";
-import { HistogramBox } from "./HistogramBox";
-
-export interface HistogramPrimitivesProps {
-    HistoBox: HistogramBox;
-}
-
-@observer
-export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesProps> {
-    render() {
-        return <div className="histogramboxprimitives-container">
-            
-        </div>
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.scss b/src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.scss
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.tsx b/src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.tsx
deleted file mode 100644
index d3440dea1..000000000
--- a/src/client/views/nodes/DataVizBox/HistogramLabelPrimitives.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { observer } from "mobx-react";
-import * as React from "react";
-import { HistogramPrimitivesProps } from "./HistogramBoxPrimitives";
-import "./HistogramLabelPrimitives.scss";
-
-@observer
-export class HistogramLabelPrimitives extends React.Component<HistogramPrimitivesProps> {
-    render() {
-        return <div className="histogramLabelPrimitives-container">
-
-        </div>
-    }    
-}
diff --git a/src/client/views/nodes/DataVizBox/LineChart.tsx b/src/client/views/nodes/DataVizBox/LineChart.tsx
deleted file mode 100644
index 0aeaacf34..000000000
--- a/src/client/views/nodes/DataVizBox/LineChart.tsx
+++ /dev/null
@@ -1,269 +0,0 @@
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { ChartData, DataPoint } from './ChartBox';
-// import d3
-import * as d3 from 'd3';
-import { minMaxRange, createLineGenerator, xGrid, yGrid, drawLine, xAxisCreator, yAxisCreator, scaleCreatorNumerical, scaleCreatorCategorical } from './utils/D3Utils';
-import { Docs } from '../../../documents/Documents';
-import { Doc, DocListCast } from '../../../../fields/Doc';
-
-interface LineChartProps {
-    data: ChartData;
-    width: number;
-    height: number;
-    dataDoc: Doc;
-    fieldKey: string;
-    // returns linechart component but should be generic chart
-    setCurrChart: (chart: LineChart | undefined) => void;
-    getAnchor: () => Doc;
-    margin: {
-        top: number;
-        right: number;
-        bottom: number;
-        left: number;
-    };
-}
-
-type minMaxRange = {
-    xMin: number | undefined;
-    xMax: number | undefined;
-    yMin: number | undefined;
-    yMax: number | undefined;
-};
-
-interface SelectedDataPoint {
-    x: number;
-    y: number;
-    elem: d3.Selection<d3.BaseType, unknown, SVGGElement, unknown>;
-}
-
-@observer
-export class LineChart extends React.Component<LineChartProps> {
-    private _dataReactionDisposer: IReactionDisposer | undefined = undefined;
-    private _heightReactionDisposer: IReactionDisposer | undefined = undefined;
-    private _widthReactionDisposer: IReactionDisposer | undefined;
-    @observable private _x: number = 0;
-    @observable private _y: number = 0;
-    @observable private _currSelected: SelectedDataPoint | undefined = undefined;
-    // create ref for the div
-    private _chartRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _rangeVals: minMaxRange = {
-        xMin: undefined,
-        xMax: undefined,
-        yMin: undefined,
-        yMax: undefined,
-    };
-
-    // anything that doesn't need to be recalculated should just be stored as drawCharts (i.e. computed values) and drawChart is gonna iterate over these observables and generate svgs based on that
-
-    // write the getanchor function that gets whatever I want as the link anchor
-
-    componentDidMount() {
-        // this._rangeVals = minMaxRange(this.props.data.data);
-        // this.drawChart();
-        this._dataReactionDisposer = reaction(
-            () => this.props.data,
-            data => {
-                this._rangeVals = minMaxRange(data.data);
-                this.drawChart();
-            },
-            { fireImmediately: true }
-        );
-        this._heightReactionDisposer = reaction(() => this.props.height, this.drawChart.bind(this));
-        this._widthReactionDisposer = reaction(() => this.props.width, this.drawChart.bind(this));
-        reaction(
-            () => DocListCast(this.props.dataDoc[this.props.fieldKey + '-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
-            },
-            { fireImmediately: true }
-        );
-
-        setTimeout(() => {
-            this.props.setCurrChart(this);
-        });
-    }
-
-    // gets called whenever the "data-annotations" fields gets updated
-    drawAnnotations() {}
-
-    _getAnchor() {
-        // store whatever information would allow me to reselect the same thing (store parameters I would pass to get the exact same element)
-
-        // TODO: nda - look at pdfviewer get anchor for args
-        const doc = Docs.Create.TextanchorDocument({
-            /*put in some options*/
-        });
-        // access curr selected from the charts
-        doc.x = this._currSelected?.x;
-        doc.y = this._currSelected?.y;
-        doc.chartType = 'line';
-        return doc;
-        // have some other function in code that
-    }
-
-    componentWillUnmount() {
-        if (this._dataReactionDisposer) {
-            this._dataReactionDisposer();
-        }
-        if (this._heightReactionDisposer) {
-            this._heightReactionDisposer();
-        }
-        if (this._widthReactionDisposer) {
-            this._widthReactionDisposer();
-        }
-    }
-
-    tooltipContent(data: DataPoint) {
-        return `<b>x: ${data.x} y: ${data.y}</b>`;
-    }
-
-    @computed get height(): number {
-        return this.props.height - this.props.margin.top - this.props.margin.bottom;
-    }
-
-    @computed get width(): number {
-        return this.props.width - this.props.margin.left - this.props.margin.right;
-    }
-
-    @computed get svgContainer() {
-        const { margin } = this.props;
-        const svg = d3
-            .create('svg')
-            .attr('width', `${this.width + margin.right + margin.left}`)
-            .attr('height', `${this.height + margin.top + margin.bottom}`)
-            .append('g')
-            .attr('transform', `translate(${margin.left}, ${margin.top})`);
-        return svg;
-    }
-
-    // TODO: nda - can use d3.create() to create html element instead of appending
-    drawChart() {
-        const { data, margin } = this.props;
-        console.log(this.height, this.width);
-        // clearing tooltip
-        d3.select(this._chartRef.current).select('svg').remove();
-        d3.select(this._chartRef.current).select('.tooltip').remove();
-
-        // TODO: nda - refactor code so that it only recalculates min max and things related to data on data update
-
-        const { xMin, xMax, yMin, yMax } = this._rangeVals;
-        // const svg = d3.select(this._chartRef.current).append(this.svgContainer.html());
-        // adding svg
-        const svg = d3
-            .select(this._chartRef.current)
-            .append('svg')
-            .attr('width', `${this.width + margin.right + margin.left}`)
-            .attr('height', `${this.height + margin.top + margin.bottom}`)
-            .append('g')
-            .attr('transform', `translate(${margin.left}, ${margin.top})`);
-
-        if (xMin == undefined || xMax == undefined || yMin == undefined || yMax == undefined) {
-            // TODO: nda - error handle
-            return;
-        }
-
-        // creating the x and y scales
-        const xScale = scaleCreatorNumerical(xMin, xMax, 0, this.width);
-        const yScale = scaleCreatorNumerical(0, yMax, this.height, 0);
-
-        // create a line function that takes in the data.data.x and data.data.y
-        // TODO: nda - fix the types for the d here
-        const lineGen = createLineGenerator(xScale, yScale);
-
-        // create x and y grids
-        xGrid(svg.append('g'), this.height, xScale);
-        yGrid(svg.append('g'), this.width, yScale);
-        xAxisCreator(svg.append('g'), this.height, xScale);
-        yAxisCreator(svg.append('g'), this.width, yScale);
-
-        // draw the line
-        drawLine(svg.append('path'), data.data, lineGen);
-
-        // draw the datapoint circles
-        svg.selectAll('.circle-d1')
-            .data(data.data)
-            .join('circle') // enter append
-            .attr('class', 'circle-d1')
-            .attr('r', '3') // radius
-            .attr('cx', d => xScale(d.x))
-            .attr('cy', d => yScale(d.y))
-            .attr('data-x', d => d.x)
-            .attr('data-y', d => d.y);
-
-        const focus = svg.append('g').attr('class', 'focus').style('display', 'none');
-        focus.append('circle').attr('r', 5).attr('class', 'circle');
-        const tooltip = d3
-            .select(this._chartRef.current)
-            .append('div')
-            .attr('class', 'tooltip')
-            .style('opacity', 0)
-            .style('background', '#fff')
-            .style('border', '1px solid #ccc')
-            .style('padding', '5px')
-            .style('position', 'absolute')
-            .style('font-size', '12px');
-        // add all the tooltipContent to the tooltip
-        // @action
-        const mousemove = action((e: any) => {
-            const bisect = d3.bisector((d: DataPoint) => d.x).left;
-            const xPos = d3.pointer(e)[0];
-            const x0 = bisect(data.data, xScale.invert(xPos));
-            const d0 = data.data[x0];
-            this._x = d0.x;
-            this._y = d0.y;
-            focus.attr('transform', `translate(${xScale(d0.x)},${yScale(d0.y)})`);
-            // TODO: nda - implement tooltips
-            tooltip.transition().duration(300).style('opacity', 0.9);
-            // TODO: nda - updating the inner html could be deadly cause injection attacks!
-            // 0 = 30px => -597px (-this.width - margin.left - margin.right)
-            // 1 =
-            tooltip.html(() => this.tooltipContent(d0)).style('transform', `translate(${xScale(d0.x) - (this.width + margin.left + margin.right)}px,${yScale(d0.y) + 30}px)`);
-        });
-
-        const onPointClick = action((e: any) => {
-            const bisect = d3.bisector((d: DataPoint) => d.x).left;
-            const xPos = d3.pointer(e)[0];
-            const x0 = bisect(data.data, xScale.invert(xPos));
-            const d0 = data.data[x0];
-            this._x = d0.x;
-            this._y = d0.y;
-            // find .circle-d1 with data-x = d0.x and data-y = d0.y
-            const selected = svg.selectAll('.circle-d1').filter((d: any) => d['data-x'] === d0.x && d['data-y'] === d0.y);
-            this._currSelected = { x: d0.x, y: d0.y, elem: selected };
-            console.log('Getting here');
-            setTimeout(() => this.props.getAnchor());
-            // this.props.getAnchor();
-            console.log(this._currSelected);
-        });
-
-        svg.append('rect')
-            .attr('class', 'overlay')
-            .attr('width', this.width)
-            .attr('height', this.height + margin.top + margin.bottom)
-            .attr('fill', 'none')
-            .attr('translate', `translate(${margin.left}, ${-(margin.top + margin.bottom)})`)
-            .style('opacity', 0)
-            .on('mouseover', () => {
-                focus.style('display', null);
-            })
-            .on('mouseout', () => {
-                tooltip.transition().duration(300).style('opacity', 0);
-            })
-            .on('mousemove', mousemove)
-            .on('click', onPointClick);
-    }
-
-    render() {
-        return (
-            <div ref={this._chartRef} className="chart-container">
-                <span>
-                    x: {this._x} y: {this._y}
-                    Curr Selected: {this._currSelected ? `x: ${this._currSelected.x} y: ${this._currSelected.y}` : 'none'}
-                </span>
-            </div>
-        );
-    }
-}
diff --git a/src/client/views/nodes/DataVizBox/TableBox.scss b/src/client/views/nodes/DataVizBox/TableBox.scss
deleted file mode 100644
index 1264d6a46..000000000
--- a/src/client/views/nodes/DataVizBox/TableBox.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-.table {
-    margin-top: 10px;
-    margin-bottom: 10px;
-    margin-left: 10px;
-    margin-right: 10px;
-}
-
-.table-row {
-    display: flex;
-    flex-direction: row;
-    justify-content: space-between;
-    align-items: center;
-    padding: 5px;
-    border-bottom: 1px solid #ccc;
-}
-
-.table-container {
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    align-items: center;
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/TableBox.tsx b/src/client/views/nodes/DataVizBox/TableBox.tsx
deleted file mode 100644
index dfa8262d8..000000000
--- a/src/client/views/nodes/DataVizBox/TableBox.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-
-interface TableBoxProps {
-    pairs: {x: number, y:number}[]
-}
-
-
-export class TableBox extends React.Component<TableBoxProps> {
-
-
-
-    render() {
-        return (
-            <div className="table-container">
-                <table className="table">
-                    <thead>
-                        <tr className="table-row">
-                            <th>x</th>
-                            <th>y</th>
-                        </tr>
-                    </thead>
-                    <tbody>
-                    {this.props.pairs.map(p => {
-                        return (<tr className="table-row">
-                            <td>{p.x}</td>
-                            <td>{p.y}</td>
-                        </tr>)
-                    })}
-                    </tbody>
-                </table>
-            </div>
-        )
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss
new file mode 100644
index 000000000..7792a2758
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/components/Chart.scss
@@ -0,0 +1,10 @@
+.tooltip {
+    // make the height width bigger
+    width: 50px;
+    height: 50px;
+}
+
+.highlight {
+    // change the color of the circle element to be red
+    fill: red;
+}
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
new file mode 100644
index 000000000..88598be3d
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -0,0 +1,270 @@
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { DataPoint } from '../ChartBox';
+// import d3
+import * as d3 from 'd3';
+import { minMaxRange, createLineGenerator, xGrid, yGrid, drawLine, xAxisCreator, yAxisCreator, scaleCreatorNumerical, scaleCreatorCategorical } from '../utils/D3Utils';
+import { Docs } from '../../../../documents/Documents';
+import { Doc, DocListCast } from '../../../../../fields/Doc';
+import { Chart, ChartProps } from '../ChartInterface';
+import './Chart.scss';
+
+type minMaxRange = {
+    xMin: number | undefined;
+    xMax: number | undefined;
+    yMin: number | undefined;
+    yMax: number | undefined;
+};
+
+interface SelectedDataPoint {
+    x: number;
+    y: number;
+    elem: d3.Selection<d3.BaseType, unknown, SVGGElement, unknown>;
+}
+
+@observer
+export class LineChart extends React.Component<ChartProps> implements Chart {
+    private _dataReactionDisposer: IReactionDisposer | undefined = undefined;
+    private _heightReactionDisposer: IReactionDisposer | undefined = undefined;
+    private _widthReactionDisposer: IReactionDisposer | undefined;
+    @observable private _x: number = 0;
+    @observable private _y: number = 0;
+    @observable private _currSelected: SelectedDataPoint | undefined = undefined;
+    // create ref for the div
+    private _chartRef: React.RefObject<HTMLDivElement> = React.createRef();
+    private _rangeVals: minMaxRange = {
+        xMin: undefined,
+        xMax: undefined,
+        yMin: undefined,
+        yMax: undefined,
+    };
+
+    private _chartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
+
+    // anything that doesn't need to be recalculated should just be stored as drawCharts (i.e. computed values) and drawChart is gonna iterate over these observables and generate svgs based on that
+
+    // write the getanchor function that gets whatever I want as the link anchor
+
+    componentDidMount() {
+        this._dataReactionDisposer = reaction(
+            () => this.props.chartData,
+            chartData => {
+                this._rangeVals = minMaxRange(chartData.data);
+                this.drawChart();
+            },
+            { fireImmediately: true }
+        );
+        this._heightReactionDisposer = reaction(() => this.props.height, this.drawChart.bind(this));
+        this._widthReactionDisposer = reaction(() => this.props.width, this.drawChart.bind(this));
+        reaction(
+            () => DocListCast(this.props.dataDoc[this.props.fieldKey + '-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(this.props.chartData.data[0][1].x, this.props.chartData.data[0][1].y);
+            },
+            { fireImmediately: true }
+        );
+
+        setTimeout(() => {
+            this.props.setCurrChart(this);
+        });
+    }
+
+    // gets called whenever the "data-annotations" fields gets updated
+    drawAnnotations(dataX: number, dataY: number) {
+        // TODO: nda - can optimize this by having some sort of mapping of the x and y values to the individual circle elements
+        // loop through all html elements with class .circle-d1 and find the one that has "data-x" and "data-y" attributes that match the dataX and dataY
+        // if it exists, then highlight it
+        // if it doesn't exist, then remove the highlight
+        const elements = document.querySelectorAll('datapoint');
+        for (let i = 0; i < elements.length; i++) {
+            const element = elements[i];
+            const x = element.getAttribute('data-x');
+            const y = element.getAttribute('data-y');
+            if (x === dataX.toString() && y === dataY.toString()) {
+                element.classList.add('highlight');
+            } else {
+                element.classList.remove('highlight');
+            }
+        }
+    }
+
+    _getAnchor() {
+        // store whatever information would allow me to reselect the same thing (store parameters I would pass to get the exact same element)
+
+        // TODO: nda - look at pdfviewer get anchor for args
+        const doc = Docs.Create.TextanchorDocument({
+            /*put in some options*/
+        });
+        // access curr selected from the charts
+        doc.x = this._currSelected?.x;
+        doc.y = this._currSelected?.y;
+        doc.chartType = 'line';
+        return doc;
+        // have some other function in code that
+    }
+
+    componentWillUnmount() {
+        if (this._dataReactionDisposer) {
+            this._dataReactionDisposer();
+        }
+        if (this._heightReactionDisposer) {
+            this._heightReactionDisposer();
+        }
+        if (this._widthReactionDisposer) {
+            this._widthReactionDisposer();
+        }
+    }
+
+    tooltipContent(data: DataPoint) {
+        return `<b>x: ${data.x} y: ${data.y}</b>`;
+    }
+
+    @computed get height(): number {
+        return this.props.height - this.props.margin.top - this.props.margin.bottom;
+    }
+
+    @computed get width(): number {
+        return this.props.width - this.props.margin.left - this.props.margin.right;
+    }
+
+    setupTooltip() {
+        const tooltip = d3
+            .select(this._chartRef.current)
+            .append('div')
+            .attr('class', 'tooltip')
+            .style('opacity', 0)
+            .style('background', '#fff')
+            .style('border', '1px solid #ccc')
+            .style('padding', '5px')
+            .style('position', 'absolute')
+            .style('font-size', '12px');
+        return tooltip;
+    }
+
+    drawDataPoints(data: DataPoint[], idx: number, xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>) {
+        if (this._chartSvg) {
+            const circleClass = '.circle-' + idx;
+            this._chartSvg
+                .selectAll(circleClass)
+                .data(data)
+                .join('circle') // enter append
+                .attr('class', `${circleClass} datapoint`)
+                .attr('r', '3') // radius
+                .attr('cx', d => xScale(d.x))
+                .attr('cy', d => yScale(d.y))
+                .attr('data-x', d => d.x)
+                .attr('data-y', d => d.y);
+        }
+    }
+
+    // TODO: nda - can use d3.create() to create html element instead of appending
+    drawChart() {
+        const { chartData, margin } = this.props;
+        const data = chartData.data[0];
+        // clearing tooltip and the current chart
+        d3.select(this._chartRef.current).select('svg').remove();
+        d3.select(this._chartRef.current).select('.tooltip').remove();
+
+        // TODO: nda - refactor code so that it only recalculates min max and things related to data on data update
+
+        const { xMin, xMax, yMin, yMax } = this._rangeVals;
+        // const svg = d3.select(this._chartRef.current).append(this.svgContainer.html());
+        // adding svg
+        this._chartSvg = d3
+            .select(this._chartRef.current)
+            .append('svg')
+            .attr('width', `${this.width + margin.right + margin.left}`)
+            .attr('height', `${this.height + margin.top + margin.bottom}`)
+            .append('g')
+            .attr('transform', `translate(${margin.left}, ${margin.top})`);
+
+        const svg = this._chartSvg;
+
+        if (xMin == undefined || xMax == undefined || yMin == undefined || yMax == undefined) {
+            // TODO: nda - error handle
+            return;
+        }
+
+        // creating the x and y scales
+        const xScale = scaleCreatorNumerical(xMin, xMax, 0, this.width);
+        const yScale = scaleCreatorNumerical(0, yMax, this.height, 0);
+
+        // create a line function that takes in the data.data.x and data.data.y
+        // TODO: nda - fix the types for the d here
+        const lineGen = createLineGenerator(xScale, yScale);
+
+        // create x and y grids
+        xGrid(svg.append('g'), this.height, xScale);
+        yGrid(svg.append('g'), this.width, yScale);
+        xAxisCreator(svg.append('g'), this.height, xScale);
+        yAxisCreator(svg.append('g'), this.width, yScale);
+
+        // draw the line
+        drawLine(svg.append('path'), data, lineGen);
+
+        // draw the datapoint circle
+        this.drawDataPoints(data, 0, xScale, yScale);
+
+        const focus = svg.append('g').attr('class', 'focus').style('display', 'none');
+        focus.append('circle').attr('r', 5).attr('class', 'circle');
+        const tooltip = this.setupTooltip();
+        // add all the tooltipContent to the tooltip
+        const mousemove = action((e: any) => {
+            const bisect = d3.bisector((d: DataPoint) => d.x).left;
+            const xPos = d3.pointer(e)[0];
+            const x0 = bisect(data, xScale.invert(xPos));
+            const d0 = data[x0];
+            this._x = d0.x;
+            this._y = d0.y;
+            focus.attr('transform', `translate(${xScale(d0.x)},${yScale(d0.y)})`);
+            // TODO: nda - implement tooltips
+            tooltip.transition().duration(300).style('opacity', 0.9);
+            // TODO: nda - updating the inner html could be deadly cause injection attacks!
+            tooltip.html(() => this.tooltipContent(d0)).style('transform', `translate(${xScale(d0.x) - (this.width + margin.left + margin.right) + 30}px,${yScale(d0.y) + 30}px)`);
+        });
+
+        const onPointClick = action((e: any) => {
+            const bisect = d3.bisector((d: DataPoint) => d.x).left;
+            const xPos = d3.pointer(e)[0];
+            const x0 = bisect(data, xScale.invert(xPos));
+            const d0 = data[x0];
+            this._x = d0.x;
+            this._y = d0.y;
+            // find .circle-d1 with data-x = d0.x and data-y = d0.y
+            const selected = svg.selectAll('.circle-d1').filter((d: any) => d['data-x'] === d0.x && d['data-y'] === d0.y);
+            this._currSelected = { x: d0.x, y: d0.y, elem: selected };
+            console.log('Getting here');
+            setTimeout(() => this.props.getAnchor());
+            // this.props.getAnchor();
+            console.log(this._currSelected);
+        });
+
+        this._chartSvg
+            .append('rect')
+            .attr('class', 'overlay')
+            .attr('width', this.width)
+            .attr('height', this.height + margin.top + margin.bottom)
+            .attr('fill', 'none')
+            .attr('translate', `translate(${margin.left}, ${-(margin.top + margin.bottom)})`)
+            .style('opacity', 0)
+            .on('mouseover', () => {
+                focus.style('display', null);
+            })
+            .on('mouseout', () => {
+                tooltip.transition().duration(300).style('opacity', 0);
+            })
+            .on('mousemove', mousemove)
+            .on('click', onPointClick);
+    }
+
+    render() {
+        return (
+            <div ref={this._chartRef} className="chart-container">
+                <span>Curr Selected: {this._currSelected ? `x: ${this._currSelected.x} y: ${this._currSelected.y}` : 'none'}</span>
+            </div>
+        );
+    }
+}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.scss b/src/client/views/nodes/DataVizBox/components/TableBox.scss
new file mode 100644
index 000000000..1264d6a46
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.scss
@@ -0,0 +1,22 @@
+.table {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    margin-left: 10px;
+    margin-right: 10px;
+}
+
+.table-row {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    padding: 5px;
+    border-bottom: 1px solid #ccc;
+}
+
+.table-container {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
new file mode 100644
index 000000000..dfa8262d8
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -0,0 +1,37 @@
+import { action, computed, observable } from "mobx";
+import { observer } from "mobx-react";
+import * as React from "react";
+
+interface TableBoxProps {
+    pairs: {x: number, y:number}[]
+}
+
+
+export class TableBox extends React.Component<TableBoxProps> {
+
+
+
+    render() {
+        return (
+            <div className="table-container">
+                <table className="table">
+                    <thead>
+                        <tr className="table-row">
+                            <th>x</th>
+                            <th>y</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                    {this.props.pairs.map(p => {
+                        return (<tr className="table-row">
+                            <td>{p.x}</td>
+                            <td>{p.y}</td>
+                        </tr>)
+                    })}
+                    </tbody>
+                </table>
+            </div>
+        )
+    }
+
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts
index 5c7f9bce1..2bb091999 100644
--- a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts
+++ b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts
@@ -3,13 +3,13 @@ import { DataPoint } from '../ChartBox';
 
 // TODO: nda - implement function that can handle range for strings
 
-export const minMaxRange = (dataPts: DataPoint[]) => {
-    console.log(Number(dataPts[4].y));
-    const yMin = d3.min(dataPts, d => Number(d.y));
-    const yMax = d3.max(dataPts, d => Number(d.y));
+export const minMaxRange = (dataPts: DataPoint[][]) => {
+    // find the max and min of all the data points
+    const yMin = d3.min(dataPts, d => d3.min(d, d => Number(d.y)));
+    const yMax = d3.max(dataPts, d => d3.max(d, d => Number(d.y)));
 
-    const xMin = d3.min(dataPts, d => Number(d.x));
-    const xMax = d3.max(dataPts, d => Number(d.x));
+    const xMin = d3.min(dataPts, d => d3.min(d, d => Number(d.x)));
+    const xMax = d3.max(dataPts, d => d3.max(d, d => Number(d.x)));
 
     return { xMin, xMax, yMin, yMax };
 };
-- 
cgit v1.2.3-70-g09d2

