aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/LineChart.tsx
blob: 2d2e67d4f20e48b1645a4d08add602a426002f65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { computed, IReactionDisposer, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ChartData, DataPoints } from './ChartBox';
// import d3
import * as d3 from 'd3';

interface LineChartProps {
    data: ChartData;
    width: number;
    height: number;
}

@observer
export class LineChart extends React.Component<LineChartProps> {
    private _dataReactionDisposer: IReactionDisposer | undefined = undefined;

    componentDidMount() {
        console.log('Getting to line chart');
        this.drawChart();
        this._dataReactionDisposer = reaction(() => this.props.data, this.drawChart);
    }

    componentWillUnmount() {
        if (this._dataReactionDisposer) {
            this._dataReactionDisposer();
        }
    }

    drawChart() {
        console.log('Getting called');
        console.log(this.props.data);
        const margin = { top: 50, right: 50, bottom: 50, left: 50 };
        const { data } = this.props;

        const yMin = d3.min(data.data, d => d.y);
        const yMax = d3.max(data.data, d => d.y);

        // TODO: nda - modify data.x to support strings

        const xMin = d3.min(data.data, d => d.x);
        const xMax = d3.max(data.data, d => d.x);

        // adding svg
        const svg = d3.select('#chart-container').append('svg').attr('width', '100%').attr('height', '100%').append('g').attr('transform', `translate(${margin.left}, ${margin.top})`);

        // adding tooltip
        // const tooltip = d3.select('#chart-container').append('div').attr('class', 'tooltip');

        if (!xMin || !xMax || !yMin || !yMax) {
            // TODO: nda - error handle
            return;
        }
        // adding x axis
        const xScale = d3.scaleLinear().domain([xMin, xMax]).range([0, this.props.width]);

        const yScale = d3.scaleLinear().domain([yMin, yMax]).range([this.props.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 = d3
            .line<DataPoints>()
            .x(d => xScale(d.x))
            .y(d => yScale(d.y))
            .curve(d3.curveMonotoneX);

        // adding the line to the svg
        svg.append('g')
            .attr('class', 'grid')
            .attr('transform', `translate(0,${this.props.height})`)
            .call(
                d3
                    .axisBottom(xScale)
                    .tickSize(-this.props.height)
                    .tickFormat((a, b) => '')
            );
        svg.append('g')
            .attr('class', 'grid')
            .call(
                d3
                    .axisLeft(yScale)
                    .tickSize(-this.props.width)
                    .tickFormat((a, b) => '')
            );
        svg.append('g').attr('class', 'x-axis').attr('transform', `translate(0,${this.props.height})`).call(d3.axisBottom(xScale).tickSize(15));
        svg.append('g').attr('class', 'y-axis').call(d3.axisLeft(yScale));

        // draw the line
        svg.append('path').datum(data.data).attr('fill', 'none').attr('stroke', '#f6c3d0').attr('stroke-width', 4).attr('class', 'line').attr('d', lineGen);

        const focus = svg.append('g').attr('class', 'focus').style('display', 'none');
        focus.append('circle').attr('r', 5).attr('class', 'circle');
        // const tooltip = d3.select('#container').append('div').attr('class', 'tooltip').style('opacity', 0);

        // const mousemove = (event) => {
        //     const bisect = d3.bisector((d: DataPoints) => d.x).left;
        //     const xPos = d3.pointer(this)[0];
        //     const x0 = bisect(data.data, xScale.invert(xPos));
        //     const d0 = data.data[x0];
        //     focus.attr('transform', `translate(${xScale(d0.x)},${yScale(d0.y)})`);
        //     tooltip.transition().duration(300).style('opacity', 0.9);
        //     tooltip.html(d0.tooltipContent || d0.label).style('transform', `translate(${xScale(d0.label) + 30}px,${yScale(d0.value) - 30}px)`);
        // }

        // svg.append('rect')
        //     .attr('class', 'overlay')
        //     .attr('width', this.props.width)
        //     .attr('height', this.props.height)
        //     .style('opacity', 0)
        //     .on('mouseover', () => {
        //         focus.style('display', null);
        //     })
        //     .on('mouseout', () => {
        //         tooltip.transition().duration(300).style('opacity', 0);
        //     })
        //     .on('mousemove', mousemove);
    }

    render() {
        return <div id="chart-container"></div>;
    }
}