diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-11-05 09:54:55 +0100 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-11-06 16:48:25 +0100 |
commit | bb00fc56370280793250bc06638f689295af2f01 (patch) | |
tree | df8cafb77a2032ab7c0063b289e2c9621636e303 /server/sonar-web/src/main/js/components | |
parent | 266e3139c3ef6112d43d3422489a0654937b1816 (diff) | |
download | sonarqube-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.js | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/components/charts/bubble-chart.js | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/components/charts/histogram.js | 93 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/components/charts/line-chart.js | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/components/charts/treemap.js | 9 | ||||
-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.js | 48 |
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> </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); + } +} |