clientjs/packages/dashboard-components/src/ui/RowChart.jsx
author ymh <ymh.work@gmail.com>
Mon, 17 Sep 2018 00:28:58 +0200
changeset 3 7af67d500dd5
parent 0 5f4fcbc80b37
permissions -rw-r--r--
Correct prod dicussion js url
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
/* eslint func-names: "off" */
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import React, { Component } from 'react';
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
import PropTypes from 'prop-types';
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
import * as d3 from 'd3';
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
import { withRouter } from 'react-router-dom';
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
import './RowChart.scss';
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
/**
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 * TODO: As a first implementation we have chosen to delagate the barchart DOM drawing to D3.
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 * This may not be the optimum solution. This may have to be rewrittten to use
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * React for elementt creation and D3 as the visualisation kernel.
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 */
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
class RowChart extends Component {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
  static propTypes = {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
    data: PropTypes.PropTypes.arrayOf(PropTypes.object).isRequired,
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
    tagPrefix: PropTypes.string.isRequired,
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
    history: PropTypes.object.isRequired,
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
  }
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
  componentDidMount() {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
    this.drawChart();
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
  }
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
  componentDidUpdate() {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
    this.drawChart();
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
  }
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
  drawChart() {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
    const { node } = this;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
    const { data, tagPrefix } = this.props;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
    const width = 800;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    const barHeight = 30;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    const height = barHeight * data.length;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    const valueMargin = 4;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    const yAxisHMargin = 10;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    const yAxisVMargin = 10;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
    const barVMargin = 10;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    const y = d3.scaleBand()
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
      .rangeRound([0, height])
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
      .padding(0.1)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
      .domain(data.map(d => d.tag));
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    const yAxis = d3.axisLeft(y);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
    d3.select(node).selectAll('svg').remove();
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    const chart = d3.select(node)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
      .append('svg')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
      .attr('width', '100%');
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
    const barsContainer = chart.append('g')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
      .attr('class', 'bars-container');
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
    const yAxisContainer = chart.append('g')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
      .attr('class', 'y-axis axis')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
      .call(yAxis);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
    let yAxisWidth = 0;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    chart.selectAll('.y-axis text')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
      .each(function () { yAxisWidth = Math.max(yAxisWidth, this.getBBox().width); });
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
    const x = d3.scaleLinear()
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
      .range([0, width - yAxisWidth - yAxisHMargin])
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
      .domain([0, d3.max(data, d => d.count)]);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
    const xAxis = d3.axisBottom(x);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
    const xAxisContainer = chart.append('g')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
      .attr('class', 'y-axis axis')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
      .attr('transform', `translate(${[yAxisWidth + 2 * yAxisHMargin, height + yAxisVMargin]})`)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
      .call(xAxis);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
    const bar = barsContainer.selectAll('.bars-container')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
      .data(data)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
      .enter().append('g')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
      .attr('transform', (d, i) => `translate(0,${i * barHeight})`)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
      .attr('class', 'graph-bar');
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
    bar.append('rect')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
      .attr('width', d => x(d.count))
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
      .attr('height', barHeight - barVMargin)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
      .attr('fill', d => d.color)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
      .attr('stroke', d => d.color)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
      .attr('transform', 'translate(0,5)')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
      .on('click', (d) => {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
        const { history } = this.props;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
        history.push(`/annotations/${tagPrefix}${d.tag}`);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
      });
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
    bar.append('text')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
      .attr('y', barHeight / 2)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
      .attr('dy', '.35em')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
      .attr('dx', -valueMargin)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
      .attr('text-anchor', 'end')
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
      .text(d => d.count)
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
      .attr('x', function (d) {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
        const xWidth = this.getBBox().width;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
        return Math.max(xWidth + valueMargin, x(d.count));
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
      });
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
    yAxisContainer.attr('transform', `translate(${yAxisWidth + yAxisHMargin},0)`);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
    barsContainer.attr('transform', `translate(${yAxisWidth + 2 * yAxisHMargin},0)`);
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
    const totalHeight = height + xAxisContainer.node().getBBox().height + yAxisVMargin;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
    const totalWidth = width + 2 * yAxisHMargin;
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
    chart.attr('viewBox', [0, 0, totalWidth, totalHeight].join(' '));
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
  }
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
  render() {
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
    return (
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
      <div className="row chart-container">
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
        <div className="col col-12" ref={(elt) => { this.node = elt; }} />
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
      </div>
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
    );
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
  }
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
}
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
5f4fcbc80b37 Create new repository to host all dashboard developments
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
export default withRouter(RowChart);