aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/overview/domain/treemap.js
blob: e22345f78d51d193bfa6631f56875c05ea1b6543 (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
import _ from 'underscore';
import React from 'react';

import { Treemap } from '../../../components/charts/treemap';
import { getChildren } from '../../../api/components';
import { formatMeasure } from '../../../helpers/measures';

const HEIGHT = 302;


export class DomainTreemap extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      loading: true,
      files: [],
      sizeMetric: this.getMetricObject(props.metrics, props.sizeMetric),
      colorMetric: props.colorMetric ? this.getMetricObject(props.metrics, props.colorMetric) : null
    };
  }

  componentDidMount () {
    this.requestComponents();
  }

  requestComponents () {
    let metrics = [this.props.sizeMetric, this.props.colorMetric];
    return getChildren(this.props.component.key, metrics).then(r => {
      let components = r.map(component => {
        let measures = {};
        (component.msr || []).forEach(measure => {
          measures[measure.key] = measure.val;
        });
        return _.extend(component, { measures });
      });
      this.setState({ loading: false, components });
    });
  }

  getMetricObject (metrics, metricKey) {
    return _.findWhere(metrics, { key: metricKey });
  }

  getTooltip (component) {
    let inner = [
      component.name,
      `${this.state.sizeMetric.name}: ${formatMeasure(component.measures[this.props.sizeMetric], this.state.sizeMetric.type)}`
    ];
    if (this.state.colorMetric) {
      inner.push(`${this.state.colorMetric.name}: ${formatMeasure(component.measures[this.props.colorMetric], this.state.colorMetric.type)}`);
    }
    inner = inner.join('<br>');
    return `<div class="text-left">${inner}</div>`;
  }

  renderLoading () {
    return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
      <i className="spinner"/>
    </div>;
  }

  renderTreemap () {
    if (this.state.loading) {
      return this.renderLoading();
    }

    // TODO filter out zero sized components
    let items = this.state.components.map(component => {
      let colorMeasure = this.props.colorMetric ? component.measures[this.props.colorMetric] : null;
      return {
        size: component.measures[this.props.sizeMetric],
        color: colorMeasure != null ? this.props.scale(colorMeasure) : '#777',
        tooltip: this.getTooltip(component),
        label: component.name
      };
    });
    return <Treemap items={items} height={HEIGHT}/>;
  }

  render () {
    let color = this.props.colorMetric ? <li>Color: {this.state.colorMetric.name}</li> : null;
    return <div className="overview-domain overview-domain-chart">
      <div className="overview-domain-header">
        <h2 className="overview-title">Treemap</h2>
        <ul className="list-inline small">
          <li>Size: {this.state.sizeMetric.name}</li>
          {color}
        </ul>
      </div>
      <div className="overview-treemap">
        {this.renderTreemap()}
      </div>
    </div>;
  }
}

DomainTreemap.propTypes = {
  sizeMetric: React.PropTypes.string.isRequired,
  colorMetric: React.PropTypes.string,
  scale: React.PropTypes.func
};