aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/components
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2015-11-05 09:54:55 +0100
committerStas Vilchik <vilchiks@gmail.com>2015-11-06 16:48:25 +0100
commitbb00fc56370280793250bc06638f689295af2f01 (patch)
treedf8cafb77a2032ab7c0063b289e2c9621636e303 /server/sonar-web/src/main/js/components
parent266e3139c3ef6112d43d3422489a0654937b1816 (diff)
downloadsonarqube-bb00fc56370280793250bc06638f689295af2f01.tar.gz
sonarqube-bb00fc56370280793250bc06638f689295af2f01.zip
SONAR-6357 add detailed "Size" panel for the "Overview" main page
Diffstat (limited to 'server/sonar-web/src/main/js/components')
-rw-r--r--server/sonar-web/src/main/js/components/charts/bar-chart.js2
-rw-r--r--server/sonar-web/src/main/js/components/charts/bubble-chart.js2
-rw-r--r--server/sonar-web/src/main/js/components/charts/histogram.js93
-rw-r--r--server/sonar-web/src/main/js/components/charts/line-chart.js2
-rw-r--r--server/sonar-web/src/main/js/components/charts/treemap.js9
-rw-r--r--server/sonar-web/src/main/js/components/mixins/resize-mixin.js (renamed from server/sonar-web/src/main/js/components/charts/mixins/resize-mixin.js)0
-rw-r--r--server/sonar-web/src/main/js/components/router/router.js48
7 files changed, 147 insertions, 9 deletions
diff --git a/server/sonar-web/src/main/js/components/charts/bar-chart.js b/server/sonar-web/src/main/js/components/charts/bar-chart.js
index f82a9c7cda2..7ce292921bc 100644
--- a/server/sonar-web/src/main/js/components/charts/bar-chart.js
+++ b/server/sonar-web/src/main/js/components/charts/bar-chart.js
@@ -1,7 +1,7 @@
import d3 from 'd3';
import React from 'react';
-import { ResizeMixin } from './mixins/resize-mixin';
+import { ResizeMixin } from './../mixins/resize-mixin';
import { TooltipsMixin } from './../mixins/tooltips-mixin';
export const BarChart = React.createClass({
diff --git a/server/sonar-web/src/main/js/components/charts/bubble-chart.js b/server/sonar-web/src/main/js/components/charts/bubble-chart.js
index 9e3facaa74d..2dd929c7c4c 100644
--- a/server/sonar-web/src/main/js/components/charts/bubble-chart.js
+++ b/server/sonar-web/src/main/js/components/charts/bubble-chart.js
@@ -1,7 +1,7 @@
import d3 from 'd3';
import React from 'react';
-import { ResizeMixin } from './mixins/resize-mixin';
+import { ResizeMixin } from './../mixins/resize-mixin';
import { TooltipsMixin } from './../mixins/tooltips-mixin';
diff --git a/server/sonar-web/src/main/js/components/charts/histogram.js b/server/sonar-web/src/main/js/components/charts/histogram.js
new file mode 100644
index 00000000000..d406d14eedf
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/charts/histogram.js
@@ -0,0 +1,93 @@
+import d3 from 'd3';
+import React from 'react';
+
+import { ResizeMixin } from './../mixins/resize-mixin';
+import { TooltipsMixin } from './../mixins/tooltips-mixin';
+
+export const Histogram = React.createClass({
+ mixins: [ResizeMixin, TooltipsMixin],
+
+ propTypes: {
+ data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
+ yTicks: React.PropTypes.arrayOf(React.PropTypes.any),
+ yValues: React.PropTypes.arrayOf(React.PropTypes.any),
+ width: React.PropTypes.number,
+ height: React.PropTypes.number,
+ padding: React.PropTypes.arrayOf(React.PropTypes.number),
+ barsHeight: React.PropTypes.number
+ },
+
+ getDefaultProps() {
+ return {
+ xTicks: [],
+ xValues: [],
+ padding: [10, 10, 10, 10],
+ barsHeight: 10
+ };
+ },
+
+ getInitialState () {
+ return { width: this.props.width, height: this.props.height };
+ },
+
+ renderTicks (xScale, yScale) {
+ if (!this.props.yTicks.length) {
+ return null;
+ }
+ let ticks = this.props.yTicks.map((tick, index) => {
+ let point = this.props.data[index];
+ let x = xScale.range()[0];
+ let y = Math.round(yScale(point.y) + yScale.rangeBand() / 2 + this.props.barsHeight / 2);
+ return <text key={index} className="bar-chart-tick histogram-tick" x={x} y={y} dx="-1em" dy="0.3em">{tick}</text>;
+ });
+ return <g>{ticks}</g>;
+ },
+
+ renderValues (xScale, yScale) {
+ if (!this.props.yValues.length) {
+ return null;
+ }
+ let ticks = this.props.yValues.map((value, index) => {
+ let point = this.props.data[index];
+ let x = xScale(point.x);
+ let y = Math.round(yScale(point.y) + yScale.rangeBand() / 2 + this.props.barsHeight / 2);
+ return <text key={index} className="bar-chart-tick histogram-value" x={x} y={y} dx="1em" dy="0.3em">{value}</text>;
+ });
+ return <g>{ticks}</g>;
+ },
+
+ renderBars (xScale, yScale) {
+ let bars = this.props.data.map((d, index) => {
+ let x = Math.round(xScale(d.x)) + /* minimum bar width */ 1;
+ let y = Math.round(yScale(d.y) + yScale.rangeBand() / 2);
+ return <rect key={index} className="bar-chart-bar"
+ x={0} y={y} width={x} height={this.props.barsHeight}/>;
+ });
+ return <g>{bars}</g>;
+ },
+
+ render () {
+ if (!this.state.width || !this.state.height) {
+ return <div/>;
+ }
+
+ let availableWidth = this.state.width - this.props.padding[1] - this.props.padding[3];
+ let availableHeight = this.state.height - this.props.padding[0] - this.props.padding[2];
+
+ let maxX = d3.max(this.props.data, d => d.x);
+ let xScale = d3.scale.linear()
+ .domain([0, maxX])
+ .range([0, availableWidth]);
+ let yScale = d3.scale.ordinal()
+ .domain(this.props.data.map(d => d.y))
+ .rangeRoundBands([0, availableHeight]);
+
+ return <svg className="bar-chart" width={this.state.width} height={this.state.height}>
+ <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}>
+ {this.renderTicks(xScale, yScale)}
+ {this.renderValues(xScale, yScale)}
+ {this.renderBars(xScale, yScale)}
+ </g>
+ </svg>;
+ }
+});
diff --git a/server/sonar-web/src/main/js/components/charts/line-chart.js b/server/sonar-web/src/main/js/components/charts/line-chart.js
index eeaed5e88a9..375931ea9f5 100644
--- a/server/sonar-web/src/main/js/components/charts/line-chart.js
+++ b/server/sonar-web/src/main/js/components/charts/line-chart.js
@@ -1,7 +1,7 @@
import d3 from 'd3';
import React from 'react';
-import { ResizeMixin } from './mixins/resize-mixin';
+import { ResizeMixin } from './../mixins/resize-mixin';
import { TooltipsMixin } from './../mixins/tooltips-mixin';
diff --git a/server/sonar-web/src/main/js/components/charts/treemap.js b/server/sonar-web/src/main/js/components/charts/treemap.js
index 24bcff49ce2..de56351ff7e 100644
--- a/server/sonar-web/src/main/js/components/charts/treemap.js
+++ b/server/sonar-web/src/main/js/components/charts/treemap.js
@@ -2,7 +2,7 @@ import _ from 'underscore';
import d3 from 'd3';
import React from 'react';
-import { ResizeMixin } from './mixins/resize-mixin';
+import { ResizeMixin } from './../mixins/resize-mixin';
import { TooltipsMixin } from './../mixins/tooltips-mixin';
@@ -81,14 +81,11 @@ export const Treemap = React.createClass({
return <div>&nbsp;</div>;
}
- let sizeScale = d3.scale.linear()
- .domain([0, d3.max(this.props.items, d => d.size)])
- .range([5, 45]);
let treemap = d3.layout.treemap()
.round(true)
- .value(d => sizeScale(d.size))
+ .value(d => d.size)
.sort((a, b) => a.value - b.value)
- .size([this.state.width, 360]);
+ .size([this.state.width, this.state.height]);
let nodes = treemap
.nodes({ children: this.props.items })
.filter(d => !d.children)
diff --git a/server/sonar-web/src/main/js/components/charts/mixins/resize-mixin.js b/server/sonar-web/src/main/js/components/mixins/resize-mixin.js
index ebd7360fe07..ebd7360fe07 100644
--- a/server/sonar-web/src/main/js/components/charts/mixins/resize-mixin.js
+++ b/server/sonar-web/src/main/js/components/mixins/resize-mixin.js
diff --git a/server/sonar-web/src/main/js/components/router/router.js b/server/sonar-web/src/main/js/components/router/router.js
new file mode 100644
index 00000000000..7489700841e
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/router/router.js
@@ -0,0 +1,48 @@
+let listener;
+
+
+export const RouterMixin = {
+ getDefaultProps() {
+ return { urlRoot: '/' };
+ },
+
+ getInitialState() {
+ return { route: this.getRoute() };
+ },
+
+ getRoute() {
+ let path = window.location.pathname;
+ if (path.indexOf(this.props.urlRoot) === 0) {
+ return path.substr(this.props.urlRoot.length);
+ } else {
+ return null;
+ }
+ },
+
+ componentDidMount () {
+ listener = this;
+ window.addEventListener('popstate', this.handleRouteChange);
+ },
+
+ componentWillUnmount() {
+ window.removeEventListener('popstate', this.handleRouteChange);
+ },
+
+ handleRouteChange() {
+ let route = this.getRoute();
+ this.setState({ route });
+ },
+
+ navigate (route) {
+ let url = this.props.urlRoot + route + window.location.search + window.location.hash;
+ window.history.pushState({ route }, document.title, url);
+ this.setState({ route });
+ }
+};
+
+
+export function navigate (route) {
+ if (listener) {
+ listener.navigate(route);
+ }
+}