aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-03-07 15:54:05 +0100
committerStas Vilchik <vilchiks@gmail.com>2016-03-07 16:10:23 +0100
commit711c144b6dad1c6e245d1f86c5978dc9b8335155 (patch)
tree05c8aead0c0edc04a54521d4d2a65232897499db /server/sonar-web/src/main/js
parentb5248a2c1c163d99e75b6e2bac56adc1a9dfa4ec (diff)
downloadsonarqube-711c144b6dad1c6e245d1f86c5978dc9b8335155.tar.gz
sonarqube-711c144b6dad1c6e245d1f86c5978dc9b8335155.zip
SONAR-7408 Drop "Technical Debt", "Coverage", "Duplications" and "Structure" pages
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r--server/sonar-web/src/main/js/apps/overview/app.js4
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/complexity-distribution.js12
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/coverage-measures-list.js94
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/coverage-measures.js172
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/detailed-measure.js58
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/domain-bubble-chart.js177
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js258
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js172
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/issue-measure.js298
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/issues-assignees.js50
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/issues-tags.js36
-rw-r--r--server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js122
-rw-r--r--server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js164
-rw-r--r--server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js253
-rw-r--r--server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js213
-rw-r--r--server/sonar-web/src/main/js/apps/overview/domains/structure-domain.js217
-rw-r--r--server/sonar-web/src/main/js/apps/overview/gate/gate-condition.js16
-rw-r--r--server/sonar-web/src/main/js/apps/overview/gate/gate-conditions.js2
-rw-r--r--server/sonar-web/src/main/js/apps/overview/gate/gate-empty.js2
-rw-r--r--server/sonar-web/src/main/js/apps/overview/gate/gate.js6
-rw-r--r--server/sonar-web/src/main/js/apps/overview/helpers/metrics.js37
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/components.js31
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/coverage.js11
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/debt.js5
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/duplications.js9
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/main.js22
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/structure.js7
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/timeline.js10
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta.js16
-rw-r--r--server/sonar-web/src/main/js/apps/overview/overview.js44
-rw-r--r--server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js119
31 files changed, 131 insertions, 2506 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/app.js b/server/sonar-web/src/main/js/apps/overview/app.js
index bc8f6322409..e7b6d020943 100644
--- a/server/sonar-web/src/main/js/apps/overview/app.js
+++ b/server/sonar-web/src/main/js/apps/overview/app.js
@@ -30,12 +30,12 @@ const LEAK_PERIOD = '1';
class App {
start (options) {
- let opts = _.extend({}, options, window.sonarqube.overview);
+ const opts = _.extend({}, options, window.sonarqube.overview);
_.extend(opts.component, options.component);
opts.urlRoot = '/overview';
$('html').toggleClass('dashboard-page', opts.component.hasSnapshot);
- let el = document.querySelector(opts.el);
+ const el = document.querySelector(opts.el);
if (opts.component.hasSnapshot) {
ReactDOM.render(<Overview {...opts} leakPeriodIndex={LEAK_PERIOD}/>, el);
diff --git a/server/sonar-web/src/main/js/apps/overview/components/complexity-distribution.js b/server/sonar-web/src/main/js/apps/overview/components/complexity-distribution.js
index ada42eafa3a..dc9dc1e7460 100644
--- a/server/sonar-web/src/main/js/apps/overview/components/complexity-distribution.js
+++ b/server/sonar-web/src/main/js/apps/overview/components/complexity-distribution.js
@@ -34,10 +34,10 @@ export const ComplexityDistribution = React.createClass({
},
renderBarChart () {
- let data = this.props.distribution.split(';').map((point, index) => {
- let tokens = point.split('=');
- let y = parseInt(tokens[1], 10);
- let value = parseInt(tokens[0], 10);
+ const data = this.props.distribution.split(';').map((point, index) => {
+ const tokens = point.split('=');
+ const y = parseInt(tokens[1], 10);
+ const value = parseInt(tokens[0], 10);
return {
x: index,
y,
@@ -46,9 +46,9 @@ export const ComplexityDistribution = React.createClass({
};
});
- let xTicks = data.map(point => point.value);
+ const xTicks = data.map(point => point.value);
- let xValues = data.map(point => formatMeasure(point.y, 'INT'));
+ const xValues = data.map(point => formatMeasure(point.y, 'INT'));
return <BarChart data={data}
xTicks={xTicks}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/coverage-measures-list.js b/server/sonar-web/src/main/js/apps/overview/components/coverage-measures-list.js
deleted file mode 100644
index cc2acc7b545..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/coverage-measures-list.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import React from 'react';
-
-import { DetailedMeasure } from './detailed-measure';
-import { CoverageMeasures } from './coverage-measures';
-import { filterMetricsForDomains } from '../helpers/metrics';
-
-
-const TEST_DOMAINS = ['Tests'];
-const TEST_METRICS = ['tests', 'test_execution_time', 'test_errors', 'test_failures', 'skipped_tests',
- 'test_success_density'];
-
-
-export const CoverageMeasuresList = React.createClass({
- shouldRenderOverallCoverage() {
- return this.props.measures['overall_coverage'] != null &&
- this.shouldRenderUTCoverage() &&
- this.shouldRenderITCoverage();
- },
-
- shouldRenderUTCoverage() {
- return this.props.measures['coverage'] != null;
- },
-
- shouldRenderITCoverage() {
- return this.props.measures['it_coverage'] != null;
- },
-
- renderOtherMeasures() {
- let knownMetrics = [].concat(TEST_METRICS, [
- 'coverage', 'line_coverage', 'branch_coverage',
- 'uncovered_lines', 'uncovered_conditions',
-
- 'it_coverage', 'it_line_coverage', 'it_branch_coverage',
- 'it_uncovered_lines', 'it_uncovered_conditions',
-
- 'overall_coverage', 'overall_line_coverage', 'overall_branch_coverage',
- 'overall_uncovered_lines', 'overall_uncovered_conditions',
-
- 'lines_to_cover', 'conditions_to_cover'
- ]);
- let metrics = filterMetricsForDomains(this.props.metrics, TEST_DOMAINS)
- .filter(metric => knownMetrics.indexOf(metric.key) === -1)
- .map(metric => metric.key);
- return this.renderListOfMeasures(metrics);
- },
-
- renderListOfMeasures(list) {
- let metrics = list.map(key => _.findWhere(this.props.metrics, { key }));
-
- if (_.every(metrics, metric => this.props.measures[metric.key] == null)) {
- // if no measures exist
- return null;
- }
-
- metrics = metrics.map(metric => {
- return <DetailedMeasure key={metric.key}
- {...this.props}
- {...this.props}
- metric={metric.key}
- type={metric.type}/>;
- });
- return <div className="overview-detailed-measures-list">{metrics}</div>;
- },
-
- render () {
- return <div>
- {this.shouldRenderOverallCoverage() && <CoverageMeasures {...this.props} prefix="overall_"/>}
- {this.shouldRenderUTCoverage() && <CoverageMeasures {...this.props} prefix=""/>}
- {this.shouldRenderITCoverage() && <CoverageMeasures {...this.props} prefix="it_"/>}
- {this.renderListOfMeasures(TEST_METRICS)}
- {this.renderOtherMeasures()}
- </div>;
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/components/coverage-measures.js b/server/sonar-web/src/main/js/apps/overview/components/coverage-measures.js
deleted file mode 100644
index 081d833eeee..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/coverage-measures.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import React from 'react';
-
-import { DetailedMeasure } from './detailed-measure';
-import { DonutChart } from '../../../components/charts/donut-chart';
-import { DrilldownLink } from '../../../components/shared/drilldown-link';
-import { formatMeasure, formatMeasureVariation } from '../../../helpers/measures';
-import { translate } from '../../../helpers/l10n';
-
-
-export const CoverageMeasures = React.createClass({
- propTypes: {
- measures: React.PropTypes.object.isRequired,
- leak: React.PropTypes.object.isRequired,
- prefix: React.PropTypes.string.isRequired
- },
-
- getMetricName(metric) {
- const { prefix } = this.props;
- return prefix + metric;
- },
-
- getNewCoverageMetricName () {
- const { prefix } = this.props;
- return 'new_' + prefix + 'coverage';
- },
-
- getCoverageMeasure() {
- const coverageMetricName = this.getMetricName('coverage');
- return this.props.measures[coverageMetricName];
- },
-
- getCoverageLeak() {
- const coverageMetricName = this.getMetricName('coverage');
- return this.props.leak[coverageMetricName];
- },
-
- getNewCoverageMeasure() {
- const newCoverageMetricName = this.getNewCoverageMetricName();
- return this.props.leak[newCoverageMetricName];
- },
-
- renderCoverageLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
- const coverageLeak = this.getCoverageLeak();
- return <div className="overview-detailed-measure-leak">
- <span className="overview-detailed-measure-value">
- {formatMeasureVariation(coverageLeak, 'PERCENT')}
- </span>
- </div>;
- },
-
- renderCoverageOnNewCode() {
- const newCoverageMetricName = this.getNewCoverageMetricName();
- const newCoverage = this.getNewCoverageMeasure();
-
- if (!this.props.leakPeriodDate || newCoverage == null) {
- return null;
- }
-
- const donutData = [
- { value: newCoverage, fill: '#85bb43' },
- { value: 100 - newCoverage, fill: '#d4333f' }
- ];
- return <div className="overview-detailed-measure" style={{ lineHeight: '30px' }}>
- <div className="overview-detailed-measure-nutshell overview-leak">
- <span className="overview-detailed-measure-name">
- {translate('metric', newCoverageMetricName, 'name')}
- </span>
- </div>
-
- <div className="overview-detailed-measure-leak">
- <span className="overview-detailed-measure-value">
- <span className="spacer-right">
- <DonutChart width="30"
- height="30"
- thickness="4"
- data={donutData}/>
- </span>
- <DrilldownLink component={this.props.component.key}
- metric={newCoverageMetricName}
- period={this.props.leakPeriodIndex}>
- {formatMeasure(newCoverage, 'PERCENT')}
- </DrilldownLink>
- </span>
- </div>
- </div>;
- },
-
- renderDonut() {
- const coverage = this.getCoverageMeasure();
- const donutData = [
- { value: coverage, fill: '#85bb43' },
- { value: 100 - coverage, fill: '#d4333f' }
- ];
- return <DonutChart width="30"
- height="30"
- thickness="4"
- data={donutData}/>;
- },
-
- render() {
- const coverageMetricName = this.getMetricName('coverage');
- const coverage = this.getCoverageMeasure();
-
- return (
- <div className="overview-detailed-measures-list">
- <div className="overview-detailed-measure" style={{ lineHeight: '30px' }}>
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name big">
- {translate('metric', coverageMetricName, 'name')}
- </span>
- <span className="overview-detailed-measure-value">
- <span className="spacer-right">{this.renderDonut()}</span>
- <DrilldownLink component={this.props.component.key} metric={coverageMetricName}>
- {formatMeasure(coverage, 'PERCENT')}
- </DrilldownLink>
- </span>
- </div>
-
- {this.renderCoverageLeak()}
- </div>
-
- <DetailedMeasure {...this.props} {...this.props}
- metric={this.getMetricName('line_coverage')}
- type="PERCENT"/>
-
- <DetailedMeasure {...this.props} {...this.props}
- metric={this.getMetricName('uncovered_lines')}
- type="INT"/>
-
- <DetailedMeasure {...this.props} {...this.props}
- metric="lines_to_cover"
- type="INT"/>
-
- <DetailedMeasure {...this.props} {...this.props}
- metric={this.getMetricName('branch_coverage')}
- type="PERCENT"/>
-
- <DetailedMeasure {...this.props} {...this.props}
- metric={this.getMetricName('uncovered_conditions')}
- type="INT"/>
-
- <DetailedMeasure {...this.props} {...this.props}
- metric="conditions_to_cover"
- type="INT"/>
-
- {this.renderCoverageOnNewCode()}
- </div>
- );
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/components/detailed-measure.js b/server/sonar-web/src/main/js/apps/overview/components/detailed-measure.js
deleted file mode 100644
index 8a8e1c9af84..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/detailed-measure.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import React from 'react';
-
-import { formatMeasure, formatMeasureVariation, localizeMetric } from '../../../helpers/measures';
-import { DrilldownLink } from '../../../components/shared/drilldown-link';
-import { getShortType } from '../helpers/metrics';
-
-
-export const DetailedMeasure = React.createClass({
- renderLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
- let leak = this.props.leak[this.props.metric];
- let formatted = leak != null ? formatMeasureVariation(leak, getShortType(this.props.type)) : '—';
- return <div className="overview-detailed-measure-leak">
- <span className="overview-detailed-measure-value">{formatted}</span>
- </div>;
- },
-
- render () {
- let measure = this.props.measures[this.props.metric];
- if (measure == null) {
- return null;
- }
-
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name">{localizeMetric(this.props.metric)}</span>
- <span className="overview-detailed-measure-value">
- <DrilldownLink component={this.props.component.key} metric={this.props.metric}>
- {formatMeasure(measure, this.props.type)}
- </DrilldownLink>
- </span>
- {this.props.children}
- </div>
- {this.renderLeak()}
- </div>;
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/components/domain-bubble-chart.js b/server/sonar-web/src/main/js/apps/overview/components/domain-bubble-chart.js
deleted file mode 100644
index 92d30f87811..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/domain-bubble-chart.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import React from 'react';
-
-import { BubbleChart } from '../../../components/charts/bubble-chart';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { getFiles } from '../../../api/components';
-import { formatMeasure } from '../../../helpers/measures';
-import Workspace from '../../../components/workspace/main';
-
-
-const HEIGHT = 360;
-const BUBBLES_LIMIT = 500;
-
-
-function getMeasure (component, metric) {
- return Number(component.measures[metric]) || 0;
-}
-
-
-export class DomainBubbleChart extends React.Component {
- constructor (props) {
- super(props);
- this.state = {
- loading: true,
- files: [],
- xMetric: this.getMetricObject(props.metrics, props.xMetric),
- yMetric: this.getMetricObject(props.metrics, props.yMetric),
- sizeMetrics: props.sizeMetrics.map(this.getMetricObject.bind(null, props.metrics))
- };
- }
-
- componentDidMount () {
- this.requestFiles();
- }
-
- requestFiles () {
- const metrics = [].concat(this.props.xMetric, this.props.yMetric, this.props.sizeMetrics);
- const options = {
- s: 'metric',
- metricSort: this.props.sizeMetrics,
- asc: false,
- ps: BUBBLES_LIMIT
- };
- return getFiles(this.props.component.key, metrics, options).then(r => {
- let files = r.map(file => {
- let measures = {};
- (file.measures || []).forEach(measure => {
- measures[measure.metric] = measure.value;
- });
- return _.extend(file, { measures });
- });
- this.setState({
- loading: false,
- files,
- total: files.length
- });
- });
- }
-
- getMetricObject (metrics, metricKey) {
- return _.findWhere(metrics, { key: metricKey });
- }
-
- getSizeMetricsValue (component) {
- return this.props.sizeMetrics.reduce((previousValue, currentValue) => {
- return previousValue + getMeasure(component, currentValue);
- }, 0);
- }
-
- getSizeMetricsTitle () {
- return this.state.sizeMetrics.map(metric => metric.name).join(' & ');
- }
-
- getTooltip (component) {
- let sizeMetricsTitle = this.getSizeMetricsTitle();
- let sizeMetricsType = this.state.sizeMetrics[0].type;
-
- /* eslint max-len: 0 */
- let inner = [
- component.name,
- `${this.state.xMetric.name}: ${formatMeasure(getMeasure(component, this.props.xMetric),
- this.state.xMetric.type)}`,
- `${this.state.yMetric.name}: ${formatMeasure(getMeasure(component, this.props.yMetric),
- this.state.yMetric.type)}`,
- `${sizeMetricsTitle}: ${formatMeasure(this.getSizeMetricsValue(component), sizeMetricsType)}`
- ].join('<br>');
- return `<div class="text-left">${inner}</div>`;
- }
-
- handleBubbleClick (id) {
- Workspace.openComponent({ uuid: id });
- }
-
- renderLoading () {
- return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
- <i className="spinner"/>
- </div>;
- }
-
- renderBubbleChart () {
- if (this.state.loading) {
- return this.renderLoading();
- }
-
- let items = this.state.files.map(component => {
- return {
- x: getMeasure(component, this.props.xMetric),
- y: getMeasure(component, this.props.yMetric),
- size: this.getSizeMetricsValue(component),
- link: component.id,
- tooltip: this.getTooltip(component)
- };
- });
- let formatXTick = (tick) => formatMeasure(tick, this.state.xMetric.type);
- let formatYTick = (tick) => formatMeasure(tick, this.state.yMetric.type);
- return <BubbleChart items={items}
- height={HEIGHT}
- padding={[25, 60, 50, 60]}
- formatXTick={formatXTick}
- formatYTick={formatYTick}
- onBubbleClick={this.handleBubbleClick}/>;
- }
-
- render () {
- if (this.props.component.qualifier === 'DEV' || this.props.component.qualifier === 'VW') {
- return null;
- }
-
- return <div className="overview-domain-chart">
- <div className="overview-card-header">
- <h2 className="overview-title">{translate('overview.chart.files')}</h2>
- <ul className="list-inline small">
- <li>
- {translateWithParameters('overview.chart.legend.size_x', this.getSizeMetricsTitle())}
- </li>
- </ul>
- </div>
- <div className="overview-bubble-chart" style={{ height: HEIGHT }}>
- <div className="note" style={{ position: 'relative', top: '10px', left: '10px' }}>
- {this.state.yMetric.name}
- </div>
- {this.renderBubbleChart()}
- <div className="note text-right" style={{ position: 'relative', top: '-10px', left: '-10px' }}>
- {this.state.xMetric.name}
- </div>
- {this.state.total > BUBBLES_LIMIT &&
- <div className="note text-center">{translateWithParameters('overview.chart.files.limit_message',
- BUBBLES_LIMIT)}</div>}
- </div>
- </div>;
- }
-}
-
-DomainBubbleChart.propTypes = {
- xMetric: React.PropTypes.string.isRequired,
- yMetric: React.PropTypes.string.isRequired,
- sizeMetrics: React.PropTypes.arrayOf(React.PropTypes.string).isRequired
-};
diff --git a/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js b/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js
deleted file mode 100644
index 8309907aba5..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import moment from 'moment';
-import React from 'react';
-import Select from 'react-select';
-
-import { getTimeMachineData } from '../../../api/time-machine';
-import { getEvents } from '../../../api/events';
-import { formatMeasure, groupByDomain } from '../../../helpers/measures';
-import { getShortType } from '../helpers/metrics';
-import Timeline from './../../../components/charts/Timeline';
-import { translate } from '../../../helpers/l10n';
-
-
-const HEIGHT = 280;
-
-
-function parseValue (value, type) {
- return type === 'RATING' && typeof value === 'string' ? value.charCodeAt(0) - 'A'.charCodeAt(0) + 1 : value;
-}
-
-
-export const DomainTimeline = React.createClass({
- propTypes: {
- allMetrics: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
- metrics: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
- initialMetric: React.PropTypes.string.isRequired
- },
-
- getInitialState() {
- return {
- loading: true,
- currentMetric: this.props.initialMetric,
- comparisonMetric: ''
- };
- },
-
- componentDidMount () {
- Promise.all([
- this.requestTimeMachineData(this.state.currentMetric, this.state.comparisonMetric),
- this.requestEvents()
- ]).then(responses => {
- this.setState({
- loading: false,
- snapshots: responses[0],
- events: responses[1]
- });
- });
- },
-
- requestTimeMachineData (currentMetric, comparisonMetric) {
- let metricsToRequest = [currentMetric];
- if (comparisonMetric) {
- metricsToRequest.push(comparisonMetric);
- }
- return getTimeMachineData(this.props.component.key, metricsToRequest.join()).then(r => {
- return r[0].cells.map(cell => {
- return { date: moment(cell.d).toDate(), values: cell.v };
- });
- });
- },
-
- requestEvents () {
- return getEvents(this.props.component.key, 'Version').then(r => {
- let events = r.map(event => {
- return { version: event.n, date: moment(event.dt).toDate() };
- });
- return _.sortBy(events, 'date');
- });
- },
-
- handleMetricChange (selected) {
- let newMetric = selected.value;
- let comparisonMetric = this.state.comparisonMetric;
- if (newMetric === comparisonMetric) {
- comparisonMetric = '';
- }
- this.requestTimeMachineData(newMetric, comparisonMetric).then(snapshots => {
- this.setState({ currentMetric: newMetric, comparisonMetric, snapshots });
- });
- },
-
- handleComparisonMetricChange (selected) {
- let newMetric = selected && selected.value;
- this.requestTimeMachineData(this.state.currentMetric, newMetric).then(snapshots => {
- this.setState({ comparisonMetric: newMetric, snapshots });
- });
- },
-
- groupMetricsByDomain () {
- return groupByDomain(this.props.metrics);
- },
-
- renderLoading () {
- return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
- <i className="spinner"/>
- </div>;
- },
-
- renderWhenNoHistoricalData () {
- return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
- There is no historical data.
- </div>;
- },
-
- renderLineCharts () {
- if (this.state.loading) {
- return this.renderLoading();
- }
- return <div>
- {this.renderLineChart(this.state.snapshots, this.state.currentMetric, 0)}
- {this.renderLineChart(this.state.snapshots, this.state.comparisonMetric, 1)}
- </div>;
- },
-
- renderLineChart (snapshots, metric, index) {
- if (!metric) {
- return null;
- }
-
- if (snapshots.length < 2) {
- return this.renderWhenNoHistoricalData();
- }
-
- let metricType = _.findWhere(this.props.allMetrics, { key: metric }).type;
- let data = snapshots.map(snapshot => {
- return {
- x: snapshot.date,
- y: parseValue(snapshot.values[index], metricType)
- };
- });
-
- let formatValue = (value) => formatMeasure(value, metricType);
- let formatYTick = (tick) => formatMeasure(tick, getShortType(metricType));
-
- return <div className={'overview-timeline-' + index} style={{ height: HEIGHT }}>
- <Timeline key={metric}
- data={data}
- metricType={metricType}
- events={this.state.events}
- height={HEIGHT}
- interpolate="linear"
- formatValue={formatValue}
- formatYTick={formatYTick}
- leakPeriodDate={this.props.leakPeriodDate}
- padding={[25, 25, 25, 60]}/>
- </div>;
- },
-
- renderTimelineMetricSelect () {
- if (this.state.loading) {
- return null;
- }
-
- const options = this.props.metrics.map(metric => {
- return {
- value: metric.key,
- label: metric.name,
- domain: metric.domain
- };
- });
-
- // use "disabled" property to emulate optgroups
- const optionsWithDomains = [];
- options.forEach((option, index, options) => {
- const previous = index > 0 ? options[index - 1] : null;
- if (!previous || previous.domain !== option.domain) {
- optionsWithDomains.push({
- value: option.domain,
- label: option.domain,
- disabled: true
- });
- }
- optionsWithDomains.push(option);
- });
-
- return <span>
- <span className="overview-timeline-sample overview-timeline-sample-0"/>
- <Select value={this.state.currentMetric}
- options={optionsWithDomains}
- clearable={false}
- style={{ width: 170 }}
- onChange={this.handleMetricChange}/>
- </span>;
- },
-
- renderComparisonMetricSelect () {
- if (this.state.loading) {
- return null;
- }
-
- const options = _.sortBy(this.props.allMetrics, 'domain')
- .filter(metric => metric.key !== this.state.currentMetric)
- .map(metric => {
- return {
- value: metric.key,
- label: metric.name,
- domain: metric.domain
- };
- });
-
- // use "disabled" property to emulate optgroups
- const optionsWithDomains = [];
- options.forEach((option, index, options) => {
- const previous = index > 0 ? options[index - 1] : null;
- if (!previous || previous.domain !== option.domain) {
- optionsWithDomains.push({
- value: option.domain,
- label: option.domain,
- disabled: true
- });
- }
- optionsWithDomains.push(option);
- });
-
- return <span>
- {this.state.comparisonMetric ? <span className="overview-timeline-sample overview-timeline-sample-1"/> : null}
- <Select value={this.state.comparisonMetric}
- options={optionsWithDomains}
- placeholder="Compare with..."
- style={{ width: 170 }}
- onChange={this.handleComparisonMetricChange}/>
- </span>;
- },
-
- render () {
- return <div className="overview-domain-chart">
- <div className="overview-card-header">
- <div>
- <h2 className="overview-title">{translate('overview.chart.history')}</h2>
- {this.renderTimelineMetricSelect()}
- </div>
- {this.renderComparisonMetricSelect()}
- </div>
- <div className="overview-timeline">
- {this.renderLineCharts()}
- </div>
- </div>;
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js b/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js
deleted file mode 100644
index 3addeefc02b..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import React from 'react';
-
-import { Treemap } from '../../../components/charts/treemap';
-import { getChildren } from '../../../api/components';
-import { formatMeasure } from '../../../helpers/measures';
-import { getComponentUrl } from '../../../helpers/urls';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-
-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,
- breadcrumbs: []
- };
- }
-
- componentDidMount () {
- this.requestComponents(this.props.component.key);
- }
-
- requestComponents (componentKey) {
- let metrics = [this.props.sizeMetric, this.props.colorMetric];
- return getChildren(componentKey, metrics).then(r => {
- let components = r.map(component => {
- let measures = {};
- (component.measures || []).forEach(measure => {
- measures[measure.metric] = measure.value;
- });
- return _.extend(component, {
- measures,
- key: component.refKey || component.key
- });
- });
- 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) {
- let measure = component.measures[this.props.colorMetric];
- let formatted = measure != null ? formatMeasure(measure, this.state.colorMetric.type) : '—';
- inner.push(`${this.state.colorMetric.name}: ${formatted}`);
- }
- inner = inner.join('<br>');
- return `<div class="text-left">${inner}</div>`;
- }
-
- handleRectangleClick (node) {
- this.requestComponents(node.key).then(() => {
- let nextBreadcrumbs = [...this.state.breadcrumbs];
- let index = _.findIndex(this.state.breadcrumbs, b => b.key === node.key);
- if (index !== -1) {
- nextBreadcrumbs = nextBreadcrumbs.slice(0, index);
- }
- nextBreadcrumbs = [...nextBreadcrumbs, {
- key: node.key,
- name: node.name,
- qualifier: node.qualifier
- }];
- this.setState({ breadcrumbs: nextBreadcrumbs });
- });
- }
-
- handleReset() {
- this.requestComponents(this.props.component.key).then(() => {
- this.setState({ breadcrumbs: [] });
- });
- }
-
- renderLoading () {
- return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
- <i className="spinner"/>
- </div>;
- }
-
- renderTreemap () {
- if (this.state.loading) {
- return this.renderLoading();
- }
-
- let items = this.state.components
- .filter(component => component.measures[this.props.sizeMetric])
- .map(component => {
- let colorMeasure = this.props.colorMetric ? component.measures[this.props.colorMetric] : null;
- return {
- key: component.key,
- name: component.name,
- qualifier: component.qualifier,
- size: component.measures[this.props.sizeMetric],
- color: colorMeasure != null ? this.props.scale(colorMeasure) : '#777',
- tooltip: this.getTooltip(component),
- label: component.name,
- link: getComponentUrl(component.key)
- };
- });
-
- const canBeClicked = node => node.qualifier !== 'FIL' && node.qualifier !== 'UTS';
-
- // FIXME remove this magic number
- const height = HEIGHT - 35;
-
- return <Treemap
- items={items}
- breadcrumbs={this.state.breadcrumbs}
- height={height}
- canBeClicked={canBeClicked}
- onRectangleClick={this.handleRectangleClick.bind(this)}
- onReset={this.handleReset.bind(this)}/>;
- }
-
- render () {
- let color = this.props.colorMetric ?
- <li>{translateWithParameters('overview.chart.legend.color_x', this.state.colorMetric.name)}</li> : null;
- return <div className="overview-domain-chart">
- <div className="overview-card-header">
- <h2 className="overview-title">{translate('overview.chart.components')}</h2>
- <ul className="list-inline small">
- <li>
- {translateWithParameters('overview.chart.legend.size_x', this.state.sizeMetric.name)}
- </li>
- {color}
- </ul>
- </div>
- <div className="overview-treemap" style={{ height: HEIGHT }}>
- {this.renderTreemap()}
- </div>
- </div>;
- }
-}
-
-DomainTreemap.propTypes = {
- sizeMetric: React.PropTypes.string.isRequired,
- colorMetric: React.PropTypes.string,
- scale: React.PropTypes.func
-};
diff --git a/server/sonar-web/src/main/js/apps/overview/components/issue-measure.js b/server/sonar-web/src/main/js/apps/overview/components/issue-measure.js
deleted file mode 100644
index ab06c2c243f..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/issue-measure.js
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import moment from 'moment';
-import React from 'react';
-
-import { formatMeasure, localizeMetric } from '../../../helpers/measures';
-import { DrilldownLink } from '../../../components/shared/drilldown-link';
-import { IssuesLink } from '../../../components/shared/issues-link';
-import { getShortType } from '../helpers/metrics';
-import SeverityHelper from '../../../components/shared/severity-helper';
-import { translate } from '../../../helpers/l10n';
-
-
-export const IssueMeasure = React.createClass({
- renderLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
-
- let leak = this.props.leak[this.props.metric];
- let added = this.props.leak[this.props.leakMetric];
- let removed = added - leak;
-
- return <div className="overview-detailed-measure-leak">
- <ul className="list-inline">
- <li className="text-danger">
- <IssuesLink className="text-danger overview-detailed-measure-value"
- component={this.props.component.key} params={{ resolved: 'false' }}>
- +{formatMeasure(added, getShortType(this.props.type))}
- </IssuesLink>
- </li>
- <li className="text-success">
- <span className="text-success overview-detailed-measure-value">
- -{formatMeasure(removed, getShortType(this.props.type))}
- </span>
- </li>
- </ul>
- </div>;
- },
-
- render () {
- let measure = this.props.measures[this.props.metric];
- if (measure == null) {
- return null;
- }
-
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name">{localizeMetric(this.props.metric)}</span>
- <span className="overview-detailed-measure-value">
- <DrilldownLink component={this.props.component.key} metric={this.props.metric}>
- {formatMeasure(measure, this.props.type)}
- </DrilldownLink>
- </span>
- {this.props.children}
- </div>
- {this.renderLeak()}
- </div>;
- }
-});
-
-
-export const AddedRemovedMeasure = React.createClass({
- renderLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
-
- let leak = this.props.leak[this.props.metric];
- let added = this.props.leak[this.props.leakMetric] || 0;
- let removed = added - leak;
-
- let createdAfter = moment(this.props.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
-
- return <div className="overview-detailed-measure-leak">
- <ul>
- <li style={{ display: 'flex', alignItems: 'baseline' }}>
- <small className="flex-1 text-left">{translate('overview.added')}</small>
- <IssuesLink className="text-danger"
- component={this.props.component.key} params={{ resolved: 'false', createdAfter }}>
- <span className="overview-detailed-measure-value">
- {formatMeasure(added, getShortType(this.props.type))}
- </span>
- </IssuesLink>
- </li>
- <li className="little-spacer-top" style={{ display: 'flex', alignItems: 'baseline' }}>
- <small className="flex-1 text-left">{translate('overview.removed')}</small>
- <span className="text-success">
- {formatMeasure(removed, getShortType(this.props.type))}
- </span>
- </li>
- </ul>
- </div>;
- },
-
- render () {
- let measure = this.props.measures[this.props.metric];
- if (measure == null) {
- return null;
- }
-
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name">{localizeMetric(this.props.metric)}</span>
- <span className="overview-detailed-measure-value">
- <DrilldownLink component={this.props.component.key} metric={this.props.metric}>
- {formatMeasure(measure, this.props.type)}
- </DrilldownLink>
- </span>
- {this.props.children}
- </div>
- {this.renderLeak()}
- </div>;
- }
-});
-
-
-export const AddedRemovedDebt = React.createClass({
- renderLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
-
- let leak = this.props.leak[this.props.metric];
- let added = this.props.leak[this.props.leakMetric] || 0;
- let removed = added - leak;
-
- return <div className="overview-detailed-measure-leak">
- <ul>
- <li style={{ display: 'flex', alignItems: 'baseline' }}>
- <small className="flex-1 text-left">{translate('overview.added')}</small>
- <DrilldownLink className="text-danger" component={this.props.component.key} metric={this.props.leakMetric}
- period={this.props.leakPeriodIndex}>
- <span className="overview-detailed-measure-value">
- {formatMeasure(added, getShortType(this.props.type))}
- </span>
- </DrilldownLink>
- </li>
- <li className="little-spacer-top" style={{ display: 'flex', alignItems: 'baseline' }}>
- <small className="flex-1 text-left">{translate('overview.removed')}</small>
- <span className="text-success">
- {formatMeasure(removed, getShortType(this.props.type))}
- </span>
- </li>
- </ul>
- </div>;
- },
-
- render () {
- let measure = this.props.measures[this.props.metric];
- if (measure == null) {
- return null;
- }
-
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name">{localizeMetric(this.props.metric)}</span>
- <span className="overview-detailed-measure-value">
- <DrilldownLink component={this.props.component.key} metric={this.props.metric}>
- {formatMeasure(measure, this.props.type)}
- </DrilldownLink>
- </span>
- {this.props.children}
- </div>
- {this.renderLeak()}
- </div>;
- }
-});
-
-
-export const OnNewCodeMeasure = React.createClass({
- renderLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
-
- let onNewCode = this.props.leak[this.props.leakMetric];
-
- return <div className="overview-detailed-measure-leak">
- <ul>
- <li className="little-spacer-top" style={{ display: 'flex', alignItems: 'center' }}>
- <small className="flex-1 text-left">{translate('overview.on_new_code')}</small>
- <DrilldownLink component={this.props.component.key} metric={this.props.leakMetric}
- period={this.props.leakPeriodIndex}>
- <span className="overview-detailed-measure-value">
- {formatMeasure(onNewCode, getShortType(this.props.type))}
- </span>
- </DrilldownLink>
- </li>
- </ul>
- </div>;
- },
-
- render () {
- let measure = this.props.measures[this.props.metric];
- if (measure == null) {
- return null;
- }
-
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name">{localizeMetric(this.props.metric)}</span>
- <span className="overview-detailed-measure-value">
- <DrilldownLink component={this.props.component.key} metric={this.props.metric}>
- {formatMeasure(measure, this.props.type)}
- </DrilldownLink>
- </span>
- {this.props.children}
- </div>
- {this.renderLeak()}
- </div>;
- }
-});
-
-
-export const SeverityMeasure = React.createClass({
- getMetric () {
- return this.props.severity.toLowerCase() + '_violations';
- },
-
- getNewMetric () {
- return 'new_' + this.props.severity.toLowerCase() + '_violations';
- },
-
-
- renderLeak () {
- if (!this.props.leakPeriodDate) {
- return null;
- }
-
- let leak = this.props.leak[this.getMetric()] || 0;
- let added = this.props.leak[this.getNewMetric()] || 0;
- let removed = added - leak;
-
- let createdAfter = moment(this.props.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
-
- return <div className="overview-detailed-measure-leak">
- <ul>
- <li style={{ display: 'flex', alignItems: 'baseline' }}>
- <small className="flex-1 text-left text-ellipsis">{translate('overview.added')}</small>
- <IssuesLink className="text-danger"
- component={this.props.component.key}
- params={{ resolved: 'false', severities: this.props.severity, createdAfter }}>
- <span className="overview-detailed-measure-value">
- {formatMeasure(added, 'SHORT_INT')}
- </span>
- </IssuesLink>
- </li>
- <li className="little-spacer-top" style={{ display: 'flex', alignItems: 'baseline' }}>
- <small className="flex-1 text-left text-ellipsis">{translate('overview.removed')}</small>
- <span className="text-success">
- {formatMeasure(removed, 'SHORT_INT')}
- </span>
- </li>
- </ul>
- </div>;
- },
-
- render () {
- let measure = this.props.measures[this.getMetric()];
- if (measure == null) {
- return null;
- }
-
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name">
- <SeverityHelper severity={this.props.severity}/>
- </span>
- <span className="overview-detailed-measure-value">
- <IssuesLink component={this.props.component.key}
- params={{ resolved: 'false', severities: this.props.severity }}>
- {formatMeasure(measure, 'SHORT_INT')}
- </IssuesLink>
- </span>
- {this.props.children}
- </div>
- {this.renderLeak()}
- </div>;
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/components/issues-assignees.js b/server/sonar-web/src/main/js/apps/overview/components/issues-assignees.js
deleted file mode 100644
index 06c0b5713e3..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/issues-assignees.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import React from 'react';
-import Assignee from '../../../components/shared/assignee-helper';
-import { getComponentIssuesUrl } from '../../../helpers/urls';
-import { formatMeasure } from '../../../helpers/measures';
-
-
-export default class extends React.Component {
- render () {
- let rows = this.props.assignees.map(s => {
- let params = { statuses: 'OPEN,REOPENED' };
- if (s.val) {
- params.assignees = s.val;
- } else {
- params.assigned = 'false';
- }
- let href = getComponentIssuesUrl(this.props.component.key, params);
- return <tr key={s.val}>
- <td>
- <Assignee user={s.user}/>
- </td>
- <td className="thin text-right">
- <a href={href}>{formatMeasure(s.count, 'SHORT_INT')}</a>
- </td>
- </tr>;
- });
-
- return <table className="data zebra">
- <tbody>{rows}</tbody>
- </table>;
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/overview/components/issues-tags.js b/server/sonar-web/src/main/js/apps/overview/components/issues-tags.js
deleted file mode 100644
index a62d65eba49..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/issues-tags.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import React from 'react';
-
-import { WordCloud } from '../../../components/charts/word-cloud';
-import { getComponentIssuesUrl } from '../../../helpers/urls';
-import { formatMeasure } from '../../../helpers/measures';
-
-
-export const IssuesTags = React.createClass({
- render () {
- let tags = this.props.tags.map(tag => {
- let link = getComponentIssuesUrl(this.props.component.key, { resolved: 'false', tags: tag.val });
- let tooltip = `Issues: ${formatMeasure(tag.count, 'SHORT_INT')}`;
- return { text: tag.val, size: tag.count, link, tooltip };
- });
- return <WordCloud items={tags}/>;
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js b/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js
deleted file mode 100644
index eb1a6f38be2..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import React from 'react';
-
-import { Histogram } from '../../../components/charts/histogram';
-import { formatMeasure } from '../../../helpers/measures';
-import { collapsePath } from '../../../helpers/path';
-import { getComponentDrilldownUrl } from '../../../helpers/urls';
-import { getChildren } from '../../../api/components';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-
-const HEIGHT = 302;
-const METRIC = 'ncloc';
-
-
-export const NclocDistribution = React.createClass({
- propTypes: {
- component: React.PropTypes.object.isRequired
- },
-
- getInitialState() {
- return { loading: true, files: [] };
- },
-
- componentDidMount () {
- this.requestComponents();
- },
-
- requestComponents () {
- let metrics = [METRIC];
- return getChildren(this.props.component.key, metrics).then(r => {
- let components = r.map(component => {
- let measures = {};
- (component.measures || []).forEach(measure => {
- measures[measure.metric] = measure.value;
- });
- return _.extend(component, { measures });
- });
- this.setState({ loading: false, components });
- });
- },
-
- handleBarClick(d) {
- window.location = getComponentDrilldownUrl(d.component.key, 'ncloc');
- },
-
- renderLoading () {
- return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
- <i className="spinner"/>
- </div>;
- },
-
- renderBarChart () {
- if (this.state.loading) {
- return this.renderLoading();
- }
-
- let data = this.state.components.map((component, index) => {
- return {
- x: component.measures[METRIC] ? parseInt(component.measures[METRIC], 10) : 0,
- y: index,
- value: component.name,
- component
- };
- });
-
- data = _.sortBy(data, d => -d.x);
-
- let yTicks = data.map(d => {
- return {
- label: collapsePath(d.value, 20),
- tooltip: d.value
- };
- });
-
- let yValues = data.map(d => formatMeasure(d.x, 'SHORT_INT'));
-
- return <Histogram data={data}
- yTicks={yTicks}
- yValues={yValues}
- height={data.length * 25}
- barsWidth={10}
- onBarClick={this.handleBarClick}
- padding={[0, 50, 0, 240]}/>;
- },
-
- render () {
- const componentsCount = this.state.components ? this.state.components.length : 1;
- const height = componentsCount * 25;
-
- return <div className="overview-domain-chart">
- <div className="overview-card-header">
- <h2 className="overview-title">{translate('overview.chart.components')}</h2>
- <span className="small">
- {translateWithParameters('overview.chart.legend.size_x', translate('metric.ncloc.name'))}
- </span>
- </div>
- <div className="overview-bar-chart" style={{ height }}>
- {this.renderBarChart()}
- </div>
- </div>;
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js
deleted file mode 100644
index d26dc85d1fa..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/domains/coverage-domain.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import d3 from 'd3';
-import React from 'react';
-
-import { getMeasures } from '../../../api/measures';
-import { DomainTimeline } from '../components/domain-timeline';
-import { DomainTreemap } from '../components/domain-treemap';
-import { DomainBubbleChart } from '../components/domain-bubble-chart';
-import { CoverageSelectionMixin } from '../components/coverage-selection-mixin';
-import { getPeriodLabel, getPeriodDate } from './../helpers/periods';
-import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin';
-import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics';
-import { DomainLeakTitle } from '../main/components';
-import { CHART_REVERSED_COLORS_RANGE_PERCENT } from '../../../helpers/constants';
-import { CoverageMeasuresList } from '../components/coverage-measures-list';
-import { translate } from '../../../helpers/l10n';
-
-
-const TEST_DOMAINS = ['Tests'];
-
-
-export const CoverageMain = React.createClass({
- mixins: [TooltipsMixin, CoverageSelectionMixin],
-
- getInitialState() {
- return {
- ready: false,
- leakPeriodLabel: getPeriodLabel(this.props.component.periods, this.props.leakPeriodIndex),
- leakPeriodDate: getPeriodDate(this.props.component.periods, this.props.leakPeriodIndex)
- };
- },
-
- componentDidMount() {
- this.requestMeasures().then(r => {
- let measures = this.getMeasuresValues(r);
- let leak = this.getMeasuresValues(r, Number(this.props.leakPeriodIndex));
- this.setState({
- ready: true,
- measures,
- leak,
- coverageMetricPrefix: this.getCoverageMetricPrefix(measures)
- });
- });
- },
-
- getMeasuresValues (measures, period) {
- let values = {};
- measures.forEach(measure => {
- const container = period ? _.findWhere(measure.periods, { index: period }) : measure;
- if (container) {
- values[measure.metric] = container.value;
- }
- });
- return values;
- },
-
- getMetricsForDomain() {
- return this.props.metrics
- .filter(metric => TEST_DOMAINS.indexOf(metric.domain) !== -1)
- .map(metric => metric.key);
- },
-
- getMetricsForTimeline() {
- return filterMetricsForDomains(this.props.metrics, TEST_DOMAINS);
- },
-
- getAllMetricsForTimeline() {
- return filterMetrics(this.props.metrics);
- },
-
- requestMeasures () {
- return getMeasures(this.props.component.key, this.getMetricsForDomain());
- },
-
- renderLoading () {
- return <div className="flex-1 text-center">
- <i className="spinner spinner-margin"/>
- </div>;
- },
-
- renderEmpty() {
- return <div className="overview-detailed-page">
- <div className="page">
- <p>{translate('overview.no_coverage')}</p>
- </div>
- </div>;
- },
-
- renderLegend () {
- return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/>;
- },
-
- render () {
- if (!this.state.ready) {
- return this.renderLoading();
- }
-
- let treemapScale = d3.scale.linear()
- .domain([0, 25, 50, 75, 100])
- .range(CHART_REVERSED_COLORS_RANGE_PERCENT);
-
- let coverageMetric = this.state.coverageMetricPrefix + 'coverage';
- let uncoveredLinesMetric = this.state.coverageMetricPrefix + 'uncovered_lines';
-
- if (this.state.measures[coverageMetric] == null) {
- return this.renderEmpty();
- }
-
- return <div className="overview-detailed-page">
- <div className="overview-cards-list">
- <div className="overview-card overview-card-fixed-width">
- <div className="overview-card-header">
- <div className="overview-title">{translate('overview.domain.coverage')}</div>
- {this.renderLegend()}
- </div>
- <CoverageMeasuresList {...this.props} {...this.state}/>
- </div>
-
- <div className="overview-card">
- <DomainBubbleChart {...this.props}
- xMetric="complexity"
- yMetric={coverageMetric}
- sizeMetrics={[uncoveredLinesMetric]}/>
- </div>
- </div>
-
- <div className="overview-cards-list">
- <div className="overview-card">
- <DomainTimeline {...this.props} {...this.state}
- initialMetric={coverageMetric}
- metrics={this.getMetricsForTimeline()}
- allMetrics={this.getAllMetricsForTimeline()}/>
- </div>
-
- <div className="overview-card">
- <DomainTreemap {...this.props}
- sizeMetric="ncloc"
- colorMetric={coverageMetric}
- scale={treemapScale}/>
- </div>
- </div>
- </div>;
-
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js
deleted file mode 100644
index 3f998f684a3..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import d3 from 'd3';
-import React from 'react';
-
-import { getMeasures } from '../../../api/measures';
-import { DetailedMeasure } from '../components/detailed-measure';
-import { DomainTimeline } from '../components/domain-timeline';
-import { DomainTreemap } from '../components/domain-treemap';
-import { DomainBubbleChart } from '../components/domain-bubble-chart';
-import { getPeriodLabel, getPeriodDate } from './../helpers/periods';
-import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin';
-import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics';
-import { CHART_COLORS_RANGE_PERCENT } from '../../../helpers/constants';
-import { AddedRemovedMeasure,
- AddedRemovedDebt,
- OnNewCodeMeasure,
- SeverityMeasure } from './../components/issue-measure';
-import { IssuesTags } from './../components/issues-tags';
-import Assignees from './../components/issues-assignees';
-import { getFacet, extractAssignees } from '../../../api/issues';
-import { Rating } from '../../../components/shared/rating';
-import { DrilldownLink } from '../../../components/shared/drilldown-link';
-import { DomainLeakTitle } from '../main/components';
-import { translate } from '../../../helpers/l10n';
-
-
-const KNOWN_METRICS = ['violations', 'sqale_index', 'sqale_rating', 'sqale_debt_ratio', 'blocker_violations',
- 'critical_violations', 'major_violations', 'minor_violations', 'info_violations', 'confirmed_issues'];
-
-
-export const DebtMain = React.createClass({
- mixins: [TooltipsMixin],
-
- getInitialState() {
- return {
- ready: false,
- leakPeriodLabel: getPeriodLabel(this.props.component.periods, this.props.leakPeriodIndex),
- leakPeriodDate: getPeriodDate(this.props.component.periods, this.props.leakPeriodIndex)
- };
- },
-
- componentDidMount() {
- Promise.all([
- this.requestMeasures(),
- this.requestIssues(),
- this.requestAssignees()
- ]).then(responses => {
- let measures = this.getMeasuresValues(responses[0]);
- let leak = this.getMeasuresValues(responses[0], Number(this.props.leakPeriodIndex));
- let tags = responses[1].facet;
- let assignees = extractAssignees(responses[2].facet, responses[2].response);
- this.setState({ ready: true, measures, leak, tags, assignees });
- });
- },
-
- getMeasuresValues (measures, period) {
- let values = {};
- measures.forEach(measure => {
- const container = period ? _.findWhere(measure.periods, { index: period }) : measure;
- if (container) {
- values[measure.metric] = container.value;
- }
- });
- return values;
- },
-
- getMetricsForDomain() {
- return this.props.metrics
- .filter(metric => ['Issues', 'Technical Debt'].indexOf(metric.domain) !== -1)
- .map(metric => metric.key);
- },
-
- getMetricsForTimeline() {
- return filterMetricsForDomains(this.props.metrics, ['Issues', 'Technical Debt']);
- },
-
- getAllMetricsForTimeline() {
- return filterMetrics(this.props.metrics);
- },
-
- requestMeasures () {
- return getMeasures(this.props.component.key, this.getMetricsForDomain());
- },
-
- getFacet (facets, facetKey) {
- return _.findWhere(facets, { property: facetKey }).values;
- },
-
- requestIssues () {
- return getFacet({
- componentUuids: this.props.component.id,
- resolved: 'false'
- }, 'tags');
- },
-
- requestAssignees () {
- return getFacet({
- componentUuids: this.props.component.id,
- resolved: 'false',
- statuses: 'OPEN,REOPENED'
- }, 'assignees');
- },
-
- renderLoading () {
- return <div className="flex-1 text-center">
- <i className="spinner spinner-margin"/>
- </div>;
- },
-
- renderLegend () {
- return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/>;
- },
-
- renderOtherMeasures() {
- let metrics = filterMetricsForDomains(this.props.metrics, ['Issues', 'Technical Debt'])
- .filter(metric => KNOWN_METRICS.indexOf(metric.key) === -1)
- .filter(metric => this.state.measures[metric.key] != null)
- .map(metric => {
- return <DetailedMeasure key={metric.key}
- {...this.props}
- {...this.state}
- metric={metric.key}
- type={metric.type}/>;
- });
- if (!metrics.length) {
- return null;
- }
- return <div className="overview-detailed-measures-list">{metrics}</div>;
- },
-
- renderRating () {
- if (this.state.measures['sqale_rating'] == null) {
- return null;
- }
- return <div className="overview-detailed-measure overview-detailed-measure-rating">
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-value">
- <DrilldownLink component={this.props.component.key} metric="sqale_rating">
- <Rating value={this.state.measures['sqale_rating']}/>
- </DrilldownLink>
- </span>
- </div>
- </div>;
- },
-
- renderTags () {
- if (!this.state.tags.length) {
- return null;
- }
- return <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <IssuesTags {...this.props} tags={this.state.tags}/>
- </div>
- </div>;
- },
-
- render () {
- if (!this.state.ready) {
- return this.renderLoading();
- }
-
- let treemapScale = d3.scale.ordinal()
- .domain([1, 2, 3, 4, 5])
- .range(CHART_COLORS_RANGE_PERCENT);
-
- return <div className="overview-detailed-page">
- <div className="overview-cards-list">
- <div className="overview-card overview-card-fixed-width">
- <div className="overview-card-header">
- <div className="overview-title">{translate('overview.domain.debt')}</div>
- {this.renderLegend()}
- </div>
-
- <div className="overview-detailed-measures-list overview-detailed-measures-list-inline">
- {this.renderRating()}
- <AddedRemovedDebt {...this.props} {...this.state}
- metric="sqale_index" leakMetric="new_technical_debt" type="WORK_DUR"/>
- <OnNewCodeMeasure {...this.props} {...this.state}
- metric="sqale_debt_ratio" leakMetric="new_sqale_debt_ratio" type="PERCENT"/>
- <AddedRemovedMeasure {...this.props} {...this.state}
- metric="violations" leakMetric="new_violations" type="INT"/>
- </div>
-
- <div className="overview-detailed-measures-list overview-detailed-measures-list-inline">
- <SeverityMeasure {...this.props} {...this.state} severity="BLOCKER"/>
- <SeverityMeasure {...this.props} {...this.state} severity="CRITICAL"/>
- <SeverityMeasure {...this.props} {...this.state} severity="MAJOR"/>
- <SeverityMeasure {...this.props} {...this.state} severity="MINOR"/>
- <SeverityMeasure {...this.props} {...this.state} severity="INFO"/>
- </div>
-
- <div className="overview-detailed-measures-list overview-detailed-measures-list-inline">
- {this.renderTags()}
- <div className="overview-detailed-measure">
- <div className="overview-detailed-measure-nutshell">
- <div className="overview-detailed-measure-name">
- {translate('overview.unmanaged_issues')}
- </div>
- <div className="spacer-top">
- <Assignees {...this.props} assignees={this.state.assignees}/>
- </div>
- </div>
- </div>
- </div>
-
- {this.renderOtherMeasures()}
- </div>
-
- <div className="overview-card">
- <DomainBubbleChart {...this.props}
- xMetric="ncloc"
- yMetric="violations"
- sizeMetrics={['sqale_index']}/>
- </div>
- </div>
-
- <div className="overview-cards-list">
- <div className="overview-card">
- <DomainTimeline {...this.props} {...this.state}
- initialMetric="sqale_index"
- metrics={this.getMetricsForTimeline()}
- allMetrics={this.getAllMetricsForTimeline()}/>
- </div>
- <div className="overview-card">
- <DomainTreemap {...this.props}
- sizeMetric="ncloc"
- colorMetric="sqale_rating"
- scale={treemapScale}/>
- </div>
- </div>
- </div>;
-
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js
deleted file mode 100644
index 6946cbdf962..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import d3 from 'd3';
-import React from 'react';
-
-import { getMeasures } from '../../../api/measures';
-import { DetailedMeasure } from '../components/detailed-measure';
-import { DomainTimeline } from '../components/domain-timeline';
-import { DomainTreemap } from '../components/domain-treemap';
-import { DomainBubbleChart } from '../components/domain-bubble-chart';
-import { getPeriodLabel, getPeriodDate } from './../helpers/periods';
-import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin';
-import { filterMetrics, filterMetricsForDomains, getMetricName } from '../helpers/metrics';
-import { DomainLeakTitle } from '../main/components';
-import { CHART_COLORS_RANGE_PERCENT } from '../../../helpers/constants';
-import { formatMeasure, formatMeasureVariation } from '../../../helpers/measures';
-import { DonutChart } from '../../../components/charts/donut-chart';
-import { DrilldownLink } from '../../../components/shared/drilldown-link';
-import { translate } from '../../../helpers/l10n';
-
-
-export const DuplicationsMain = React.createClass({
- mixins: [TooltipsMixin],
-
- getInitialState() {
- return {
- ready: false,
- leakPeriodLabel: getPeriodLabel(this.props.component.periods, this.props.leakPeriodIndex),
- leakPeriodDate: getPeriodDate(this.props.component.periods, this.props.leakPeriodIndex)
- };
- },
-
- componentDidMount() {
- this.requestMeasures().then(r => {
- let measures = this.getMeasuresValues(r);
- let leak = this.getMeasuresValues(r, Number(this.props.leakPeriodIndex));
- this.setState({ ready: true, measures, leak });
- });
- },
-
- getMeasuresValues (measures, period) {
- let values = {};
- measures.forEach(measure => {
- const container = period ? _.findWhere(measure.periods, { index: period }) : measure;
- if (container) {
- values[measure.metric] = container.value;
- }
- });
- return values;
- },
-
- getMetricsForDomain() {
- return this.props.metrics
- .filter(metric => ['Duplication'].indexOf(metric.domain) !== -1)
- .map(metric => metric.key);
- },
-
- getMetricsForTimeline() {
- return filterMetricsForDomains(this.props.metrics, ['Duplication']);
- },
-
- getAllMetricsForTimeline() {
- return filterMetrics(this.props.metrics);
- },
-
- requestMeasures () {
- return getMeasures(this.props.component.key, this.getMetricsForDomain());
- },
-
- renderLoading () {
- return <div className="flex-1 text-center">
- <i className="spinner spinner-margin"/>
- </div>;
- },
-
- renderEmpty() {
- return <div className="overview-detailed-page">
- <div className="page">
- <p>{translate('overview.no_duplications')}</p>
- </div>
- </div>;
- },
-
- renderLegend () {
- return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/>;
- },
-
- renderMeasures() {
- let metrics = filterMetricsForDomains(this.props.metrics, ['Duplication'])
- .filter(metric => metric.key !== 'duplicated_lines_density')
- .map(metric => {
- return <DetailedMeasure key={metric.key}
- {...this.props}
- {...this.state}
- metric={metric.key}
- type={metric.type}/>;
- });
- return <div>{metrics}</div>;
- },
-
- renderDonut() {
- const duplicationsMetric = 'duplicated_lines_density';
- const duplications = this.state.measures[duplicationsMetric];
- const donutData = [
- { value: duplications, fill: '#f3ca8e' },
- { value: Math.max(0, 20 - duplications), fill: '#e6e6e6' }
- ];
- return <DonutChart width="30"
- height="30"
- thickness="4"
- data={donutData}/>;
- },
-
- renderDuplicationsLeak() {
- if (!this.state.leakPeriodDate) {
- return null;
- }
- const duplicationsMetric = 'duplicated_lines_density';
- const leak = this.state.leak[duplicationsMetric];
- return <div className="overview-detailed-measure-leak">
- <span className="overview-detailed-measure-value">
- {formatMeasureVariation(leak, 'PERCENT')}
- </span>
- </div>;
- },
-
- render () {
- if (!this.state.ready) {
- return this.renderLoading();
- }
-
- const duplicationsMetric = 'duplicated_lines_density';
- const duplications = this.state.measures[duplicationsMetric];
-
- if (duplications == null) {
- return this.renderEmpty();
- }
-
- let treemapScale = d3.scale.linear()
- .domain([0, 25, 50, 75, 100])
- .range(CHART_COLORS_RANGE_PERCENT);
-
- return <div className="overview-detailed-page">
- <div className="overview-cards-list">
- <div className="overview-card overview-card-fixed-width">
- <div className="overview-card-header">
- <div className="overview-title">{translate('overview.domain.duplications')}</div>
- {this.renderLegend()}
- </div>
- <div className="overview-detailed-measures-list">
- <div className="overview-detailed-measure" style={{ lineHeight: '30px' }}>
- <div className="overview-detailed-measure-nutshell">
- <span className="overview-detailed-measure-name big">
- {getMetricName('duplications')}
- </span>
- <span className="overview-detailed-measure-value">
- <span className="spacer-right">{this.renderDonut()}</span>
- <DrilldownLink component={this.props.component.key} metric={duplicationsMetric}>
- {formatMeasure(duplications, 'PERCENT')}
- </DrilldownLink>
- </span>
- </div>
-
- {this.renderDuplicationsLeak()}
- </div>
-
- {this.renderMeasures()}
- </div>
- </div>
- <div className="overview-card">
- <DomainBubbleChart {...this.props}
- xMetric="ncloc"
- yMetric="duplicated_lines"
- sizeMetrics={['duplicated_blocks']}/>
- </div>
- </div>
-
- <div className="overview-cards-list">
- <div className="overview-card">
- <DomainTimeline {...this.props} {...this.state}
- initialMetric="duplicated_lines_density"
- metrics={this.getMetricsForTimeline()}
- allMetrics={this.getAllMetricsForTimeline()}/>
- </div>
- <div className="overview-card">
- <DomainTreemap {...this.props}
- sizeMetric="ncloc"
- colorMetric="duplicated_lines_density"
- scale={treemapScale}/>
- </div>
- </div>
- </div>;
-
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/domains/structure-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/structure-domain.js
deleted file mode 100644
index 7caa737642f..00000000000
--- a/server/sonar-web/src/main/js/apps/overview/domains/structure-domain.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import _ from 'underscore';
-import React from 'react';
-
-import { LanguageDistribution } from './../components/language-distribution';
-import { ComplexityDistribution } from './../components/complexity-distribution';
-import { NclocDistribution } from '../components/ncloc-distribution';
-import { getMeasures } from '../../../api/measures';
-import { DetailedMeasure } from '../components/detailed-measure';
-import { DomainTimeline } from '../components/domain-timeline';
-import { getPeriodLabel, getPeriodDate } from './../helpers/periods';
-import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin';
-import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics';
-import { DomainLeakTitle } from '../main/components';
-import { translate } from '../../../helpers/l10n';
-
-
-export const StructureMain = React.createClass({
- mixins: [TooltipsMixin],
-
- getInitialState() {
- return {
- ready: false,
- leakPeriodLabel: getPeriodLabel(this.props.component.periods, this.props.leakPeriodIndex),
- leakPeriodDate: getPeriodDate(this.props.component.periods, this.props.leakPeriodIndex)
- };
- },
-
- componentDidMount() {
- this.requestMeasures().then(r => {
- let measures = this.getMeasuresValues(r);
- let leak = this.getMeasuresValues(r, Number(this.props.leakPeriodIndex));
- this.setState({ ready: true, measures, leak });
- });
- },
-
- getMeasuresValues (measures, period) {
- let values = {};
- measures.forEach(measure => {
- const container = period ? _.findWhere(measure.periods, { index: period }) : measure;
- if (container) {
- values[measure.metric] = container.value;
- }
- });
- return values;
- },
-
- getMetricsForDomain() {
- return this.props.metrics
- .filter(metric => ['Size', 'Complexity', 'Documentation'].indexOf(metric.domain) !== -1)
- .map(metric => metric.key);
- },
-
- getMetricsForTimeline() {
- return filterMetricsForDomains(this.props.metrics, ['Size', 'Complexity', 'Documentation']);
- },
-
- getAllMetricsForTimeline() {
- return filterMetrics(this.props.metrics);
- },
-
- requestMeasures () {
- return getMeasures(this.props.component.key, this.getMetricsForDomain());
- },
-
- renderLoading () {
- return <div className="flex-1 text-center">
- <i className="spinner spinner-margin"/>
- </div>;
- },
-
- renderLegend () {
- return <DomainLeakTitle inline={true} label={this.state.leakPeriodLabel} date={this.state.leakPeriodDate}/>;
- },
-
- renderOtherMeasures(domain, hiddenMetrics) {
- let metrics = filterMetricsForDomains(this.props.metrics, [domain])
- .filter(metric => hiddenMetrics.indexOf(metric.key) === -1)
- .map(metric => {
- return <DetailedMeasure key={metric.key}
- {...this.props}
- {...this.state}
- metric={metric.key}
- type={metric.type}/>;
- });
- return <div>{metrics}</div>;
- },
-
- renderOtherSizeMeasures() {
- return this.renderOtherMeasures('Size', ['ncloc']);
- },
-
- renderOtherComplexityMeasures() {
- return this.renderOtherMeasures('Complexity',
- ['complexity', 'function_complexity', 'file_complexity', 'class_complexity']);
- },
-
- renderOtherDocumentationMeasures() {
- return this.renderOtherMeasures('Documentation', []);
- },
-
- renderLanguageDistribution() {
- let distribution = this.state.measures['ncloc_language_distribution'];
- if (distribution == null) {
- return null;
- }
- return <LanguageDistribution lines={Number(this.state.measures['ncloc'])} distribution={distribution}/>;
- },
-
- renderComplexityDistribution(distribution, props) {
- if (distribution == null) {
- return null;
- }
- return <ComplexityDistribution distribution={distribution} {...props}/>;
- },
-
- renderComplexityCard() {
- if (this.state.measures['complexity'] == null) {
- return null;
- }
-
- return <div className="overview-detailed-layout-column">
- <div className="overview-detailed-measures-list">
- <DetailedMeasure {...this.props}
- {...this.state}
- metric="complexity"
- type="INT"/>
- <DetailedMeasure {...this.props}
- {...this.state}
- metric="function_complexity"
- type="FLOAT">
- {this.renderComplexityDistribution(this.state.measures['function_complexity_distribution'],
- { of: 'function' })}
- </DetailedMeasure>
- <DetailedMeasure {...this.props}
- {...this.state}
- metric="file_complexity"
- type="FLOAT">
- {this.renderComplexityDistribution(this.state.measures['file_complexity_distribution'],
- { of: 'file' })}
- </DetailedMeasure>
- <DetailedMeasure {...this.props}
- {...this.state}
- metric="class_complexity"
- type="FLOAT"/>
- {this.renderOtherComplexityMeasures()}
- </div>
- </div>;
- },
-
- render () {
- if (!this.state.ready) {
- return this.renderLoading();
- }
- return <div className="overview-detailed-page">
- <div className="overview-card">
- <div className="overview-card-header">
- <div className="overview-title">{translate('overview.domain.structure')}</div>
- {this.renderLegend()}
- </div>
-
- <div className="overview-detailed-layout-size">
- <div className="overview-detailed-layout-column">
- <div className="overview-detailed-measures-list">
- <DetailedMeasure {...this.props}
- {...this.state}
- metric="ncloc"
- type="INT">
- {this.renderLanguageDistribution()}
- </DetailedMeasure>
- {this.renderOtherSizeMeasures()}
- </div>
- </div>
-
- {this.renderComplexityCard()}
-
- <div className="overview-detailed-layout-column">
- <div className="overview-detailed-measures-list">
- {this.renderOtherDocumentationMeasures()}
- </div>
- </div>
- </div>
- </div>
-
- <div className="overview-cards-list">
- <div className="overview-card">
- <DomainTimeline {...this.props} {...this.state}
- initialMetric="ncloc"
- metrics={this.getMetricsForTimeline()}
- allMetrics={this.getAllMetricsForTimeline()}/>
- </div>
- <div className="overview-card">
- <NclocDistribution {...this.props}/>
- </div>
- </div>
- </div>;
-
- }
-});
diff --git a/server/sonar-web/src/main/js/apps/overview/gate/gate-condition.js b/server/sonar-web/src/main/js/apps/overview/gate/gate-condition.js
index 4b13f065170..5279ab40176 100644
--- a/server/sonar-web/src/main/js/apps/overview/gate/gate-condition.js
+++ b/server/sonar-web/src/main/js/apps/overview/gate/gate-condition.js
@@ -30,7 +30,7 @@ const Measure = React.createClass({
if (this.props.value == null || isNaN(this.props.value)) {
return null;
}
- let formatted = formatMeasure(this.props.value, this.props.type);
+ const formatted = formatMeasure(this.props.value, this.props.type);
return <span>{formatted}</span>;
}
});
@@ -38,14 +38,14 @@ const Measure = React.createClass({
export default React.createClass({
render() {
- let metricName = translate('metric', this.props.condition.metric.name, 'name');
- let threshold = this.props.condition.level === 'ERROR' ?
- this.props.condition.error : this.props.condition.warning;
- let period = this.props.condition.period ?
- getPeriodLabel(this.props.component.periods, this.props.condition.period) : null;
- let periodDate = getPeriodDate(this.props.component.periods, this.props.condition.period);
+ const metricName = translate('metric', this.props.condition.metric.name, 'name');
+ const threshold = this.props.condition.level === 'ERROR' ?
+ this.props.condition.error : this.props.condition.warning;
+ const period = this.props.condition.period ?
+ getPeriodLabel(this.props.component.periods, this.props.condition.period) : null;
+ const periodDate = getPeriodDate(this.props.component.periods, this.props.condition.period);
- let classes = 'alert_' + this.props.condition.level.toUpperCase();
+ const classes = 'alert_' + this.props.condition.level.toUpperCase();
return (
<li className="overview-gate-condition">
diff --git a/server/sonar-web/src/main/js/apps/overview/gate/gate-conditions.js b/server/sonar-web/src/main/js/apps/overview/gate/gate-conditions.js
index 9943c6fab72..99dd41b43f6 100644
--- a/server/sonar-web/src/main/js/apps/overview/gate/gate-conditions.js
+++ b/server/sonar-web/src/main/js/apps/overview/gate/gate-conditions.js
@@ -27,7 +27,7 @@ export default React.createClass({
},
render() {
- let conditions = this.props.gate.conditions
+ const conditions = this.props.gate.conditions
.filter(c => c.level !== 'OK')
.map(c => <GateCondition key={c.metric.name} condition={c} component={this.props.component}/>);
return <ul className="overview-gate-conditions-list">{conditions}</ul>;
diff --git a/server/sonar-web/src/main/js/apps/overview/gate/gate-empty.js b/server/sonar-web/src/main/js/apps/overview/gate/gate-empty.js
index 4ad5565b59b..fa339aca23c 100644
--- a/server/sonar-web/src/main/js/apps/overview/gate/gate-empty.js
+++ b/server/sonar-web/src/main/js/apps/overview/gate/gate-empty.js
@@ -22,7 +22,7 @@ import { translate } from '../../../helpers/l10n';
export default React.createClass({
render() {
- let qualityGatesUrl = '/quality_gates';
+ const qualityGatesUrl = '/quality_gates';
return (
<div className="overview-gate">
diff --git a/server/sonar-web/src/main/js/apps/overview/gate/gate.js b/server/sonar-web/src/main/js/apps/overview/gate/gate.js
index 4705e8f7af6..934e117f286 100644
--- a/server/sonar-web/src/main/js/apps/overview/gate/gate.js
+++ b/server/sonar-web/src/main/js/apps/overview/gate/gate.js
@@ -46,9 +46,9 @@ export default React.createClass({
return this.props.component.qualifier === 'TRK' ? <GateEmpty/> : null;
}
- let level = this.props.gate.level.toLowerCase();
- let badgeClassName = 'badge badge-' + level;
- let badgeText = translate('overview.gate', this.props.gate.level);
+ const level = this.props.gate.level.toLowerCase();
+ const badgeClassName = 'badge badge-' + level;
+ const badgeText = translate('overview.gate', this.props.gate.level);
return (
<div className="overview-gate">
diff --git a/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js b/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js
index ce3cd1d6b60..1a37e037c2a 100644
--- a/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js
+++ b/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js
@@ -19,43 +19,6 @@
*/
import { translate } from '../../../helpers/l10n';
-function hasRightDomain (metric, domains) {
- return domains.indexOf(metric.domain) !== -1;
-}
-
-function isNotHidden (metric) {
- return !metric.hidden;
-}
-
-function hasSimpleType (metric) {
- return metric.type !== 'DATA' && metric.type !== 'DISTRIB';
-}
-
-function isNotDifferential (metric) {
- return metric.key.indexOf('new_') !== 0;
-}
-
-export function filterMetrics (metrics) {
- return metrics.filter(metric => {
- return isNotHidden(metric) && hasSimpleType(metric) && isNotDifferential(metric);
- });
-}
-
-export function filterMetricsForDomains (metrics, domains) {
- return filterMetrics(metrics).filter(metric => hasRightDomain(metric, domains));
-}
-
-
-export function getShortType (type) {
- if (type === 'INT') {
- return 'SHORT_INT';
- } else if (type === 'WORK_DUR') {
- return 'SHORT_WORK_DUR';
- }
- return type;
-}
-
-
export function getMetricName (metricKey) {
return translate('overview.metric', metricKey);
}
diff --git a/server/sonar-web/src/main/js/apps/overview/main/components.js b/server/sonar-web/src/main/js/apps/overview/main/components.js
index 80ab66122d7..7113db33759 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/components.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/components.js
@@ -21,7 +21,7 @@ import moment from 'moment';
import React from 'react';
import { Timeline } from './timeline';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translateWithParameters } from '../../../helpers/l10n';
export const Domain = React.createClass({
@@ -33,20 +33,7 @@ export const Domain = React.createClass({
export const DomainTitle = React.createClass({
render () {
- if (this.props.linkTo) {
- let url = '/overview' + this.props.linkTo + '?id=' + encodeURIComponent(this.props.component.key);
- return <div>
- <div className="overview-title">
- {this.props.children}
- <a className="small big-spacer-left link-no-underline" href={url}>
- {translate('more')}&nbsp;
- <i className="icon-chevron-right" style={{ position: 'relative', top: -1 }}/>
- </a>
- </div>
- </div>;
- } else {
- return <div className="overview-title">{this.props.children}</div>;
- }
+ return <div className="overview-title">{this.props.children}</div>;
}
});
@@ -63,9 +50,9 @@ export const DomainLeakTitle = React.createClass({
if (!this.props.label || !this.props.date) {
return null;
}
- let momentDate = moment(this.props.date);
- let fromNow = momentDate.fromNow();
- let tooltip = 'Started on ' + momentDate.format('LL');
+ const momentDate = moment(this.props.date);
+ const fromNow = momentDate.fromNow();
+ const tooltip = 'Started on ' + momentDate.format('LL');
if (this.props.inline) {
return this.renderInline(tooltip, fromNow);
}
@@ -156,10 +143,10 @@ export const Measure = React.createClass({
export const DomainMixin = {
renderTimelineStartDate() {
- let momentDate = moment(this.props.historyStartDate);
- let fromNow = momentDate.fromNow();
+ const momentDate = moment(this.props.historyStartDate);
+ const fromNow = momentDate.fromNow();
return (
- <span className="overview-domain-timeline-date">
+ <span className="overview-domain-timeline-date">
{translateWithParameters('overview.started_x', fromNow)}
</span>
);
@@ -169,7 +156,7 @@ export const DomainMixin = {
if (!this.props.history) {
return null;
}
- let props = { history: this.props.history };
+ const props = { history: this.props.history };
props[range] = this.props.leakPeriodDate;
return <div className="overview-domain-timeline">
<Timeline {...props}/>
diff --git a/server/sonar-web/src/main/js/apps/overview/main/coverage.js b/server/sonar-web/src/main/js/apps/overview/main/coverage.js
index 84637a24738..dcab23f842b 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/coverage.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/coverage.js
@@ -54,7 +54,7 @@ export const GeneralCoverage = React.createClass({
},
renderNewCoverage () {
- let newCoverageMetric = this.getNewCoverageMetric();
+ const newCoverageMetric = this.getNewCoverageMetric();
if (this.props.leak[newCoverageMetric] != null) {
return <DrilldownLink component={this.props.component.key} metric={newCoverageMetric}
@@ -82,7 +82,7 @@ export const GeneralCoverage = React.createClass({
},
renderTests() {
- let tests = this.props.measures['tests'];
+ const tests = this.props.measures['tests'];
if (tests == null) {
return null;
}
@@ -94,20 +94,19 @@ export const GeneralCoverage = React.createClass({
},
render () {
- let coverageMetric = this.getCoverageMetric();
+ const coverageMetric = this.getCoverageMetric();
if (this.props.measures[coverageMetric] == null) {
return null;
}
- let donutData = [
+ const donutData = [
{ value: this.props.measures[coverageMetric], fill: '#85bb43' },
{ value: 100 - this.props.measures[coverageMetric], fill: '#d4333f' }
];
return <Domain>
<DomainHeader component={this.props.component}
- title={translate('overview.domain.coverage')}
- linkTo="/coverage"/>
+ title={translate('overview.domain.coverage')}/>
<DomainPanel>
<DomainNutshell>
diff --git a/server/sonar-web/src/main/js/apps/overview/main/debt.js b/server/sonar-web/src/main/js/apps/overview/main/debt.js
index 51f4c810bd1..a8056ca254c 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/debt.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/debt.js
@@ -51,7 +51,7 @@ export const GeneralDebt = React.createClass({
return null;
}
- let createdAfter = moment(this.props.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
+ const createdAfter = moment(this.props.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
return <DomainLeak>
<Legend leakPeriodLabel={this.props.leakPeriodLabel} leakPeriodDate={this.props.leakPeriodDate}/>
@@ -77,8 +77,7 @@ export const GeneralDebt = React.createClass({
render () {
return <Domain>
<DomainHeader component={this.props.component}
- title={translate('overview.domain.debt')}
- linkTo="/debt"/>
+ title={translate('overview.domain.debt')}/>
<DomainPanel>
<DomainNutshell>
diff --git a/server/sonar-web/src/main/js/apps/overview/main/duplications.js b/server/sonar-web/src/main/js/apps/overview/main/duplications.js
index 181fc4c3e3f..066a4808eee 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/duplications.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/duplications.js
@@ -47,8 +47,8 @@ export const GeneralDuplications = React.createClass({
if (!this.hasLeakPeriod()) {
return null;
}
- let measure = this.props.leak['duplicated_lines_density'];
- let formatted = measure != null ? formatMeasureVariation(measure, 'PERCENT') : '—';
+ const measure = this.props.leak['duplicated_lines_density'];
+ const formatted = measure != null ? formatMeasureVariation(measure, 'PERCENT') : '—';
return <DomainLeak>
<MeasuresList>
<Measure label={getMetricName('duplications')}>
@@ -71,15 +71,14 @@ export const GeneralDuplications = React.createClass({
},
render () {
- let donutData = [
+ const donutData = [
{ value: this.props.measures['duplicated_lines_density'], fill: '#f3ca8e' },
{ value: Math.max(0, 20 - this.props.measures['duplicated_lines_density']), fill: '#e6e6e6' }
];
return <Domain>
<DomainHeader component={this.props.component}
- title={translate('overview.domain.duplications')}
- linkTo="/duplications"/>
+ title={translate('overview.domain.duplications')}/>
<DomainPanel>
<DomainNutshell>
diff --git a/server/sonar-web/src/main/js/apps/overview/main/main.js b/server/sonar-web/src/main/js/apps/overview/main/main.js
index c9d01b4b87c..12332ddd36b 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/main.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/main.js
@@ -76,7 +76,7 @@ export default React.createClass({
this.requestIssuesAndDebt(),
this.requestLeakIssuesAndDebt()
]).then(responses => {
- let measures = this.getMeasuresValues(responses[0]);
+ const measures = this.getMeasuresValues(responses[0]);
measures.issues = responses[1].issues;
measures.debt = responses[1].debt;
@@ -101,7 +101,7 @@ export default React.createClass({
},
getMeasuresValues (measures, period) {
- let values = {};
+ const values = {};
measures.forEach(measure => {
const container = period ? _.findWhere(measure.periods, { index: period }) : measure;
if (container) {
@@ -125,7 +125,7 @@ export default React.createClass({
return Promise.resolve();
}
- let createdAfter = moment(this.state.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
+ const createdAfter = moment(this.state.leakPeriodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
// FIXME requesting severities facet only to get debtTotal
return getIssuesCount({
@@ -137,18 +137,18 @@ export default React.createClass({
},
requestHistory () {
- let coverageMetric = this.state.coverageMetricPrefix + 'coverage';
- let metrics = [].concat(HISTORY_METRICS_LIST, coverageMetric).join(',');
+ const coverageMetric = this.state.coverageMetricPrefix + 'coverage';
+ const metrics = [].concat(HISTORY_METRICS_LIST, coverageMetric).join(',');
return getTimeMachineData(this.props.component.key, metrics).then(r => {
- let history = {};
+ const history = {};
r[0].cols.forEach((col, index) => {
history[col.metric] = r[0].cells.map(cell => {
- let date = moment(cell.d).toDate();
- let value = cell.v[index] || 0;
+ const date = moment(cell.d).toDate();
+ const value = cell.v[index] || 0;
return { date, value };
});
});
- let historyStartDate = history[HISTORY_METRICS_LIST[0]][0].date;
+ const historyStartDate = history[HISTORY_METRICS_LIST[0]][0].date;
this.setState({ history, historyStartDate });
});
},
@@ -164,8 +164,8 @@ export default React.createClass({
return this.renderLoading();
}
- let coverageMetric = this.state.coverageMetricPrefix + 'coverage';
- let props = _.extend({}, this.props, this.state);
+ const coverageMetric = this.state.coverageMetricPrefix + 'coverage';
+ const props = _.extend({}, this.props, this.state);
return <div className="overview-domains-list">
<GeneralDebt {...props} history={this.state.history['sqale_index']}/>
diff --git a/server/sonar-web/src/main/js/apps/overview/main/structure.js b/server/sonar-web/src/main/js/apps/overview/main/structure.js
index 0e794d06126..eb3c156293c 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/structure.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/structure.js
@@ -47,8 +47,8 @@ export const GeneralStructure = React.createClass({
if (!this.hasLeakPeriod()) {
return null;
}
- let measure = this.props.leak['ncloc'];
- let formatted = measure != null ? formatMeasureVariation(measure, 'SHORT_INT') : '—';
+ const measure = this.props.leak['ncloc'];
+ const formatted = measure != null ? formatMeasureVariation(measure, 'SHORT_INT') : '—';
return <DomainLeak>
<MeasuresList>
<Measure label={getMetricName('ncloc')}>{formatted}</Measure>
@@ -72,8 +72,7 @@ export const GeneralStructure = React.createClass({
render () {
return <Domain>
<DomainHeader component={this.props.component}
- title={translate('overview.domain.structure')}
- linkTo="/structure"/>
+ title={translate('overview.domain.structure')}/>
<DomainPanel>
<DomainNutshell>
diff --git a/server/sonar-web/src/main/js/apps/overview/main/timeline.js b/server/sonar-web/src/main/js/apps/overview/main/timeline.js
index 2be75a74bfc..89a36ac30d9 100644
--- a/server/sonar-web/src/main/js/apps/overview/main/timeline.js
+++ b/server/sonar-web/src/main/js/apps/overview/main/timeline.js
@@ -29,24 +29,24 @@ const HEIGHT = 80;
export class Timeline extends React.Component {
filterSnapshots () {
return this.props.history.filter(s => {
- let matchBefore = !this.props.before || s.date <= this.props.before;
- let matchAfter = !this.props.after || s.date >= this.props.after;
+ const matchBefore = !this.props.before || s.date <= this.props.before;
+ const matchAfter = !this.props.after || s.date >= this.props.after;
return matchBefore && matchAfter;
});
}
render () {
- let snapshots = this.filterSnapshots();
+ const snapshots = this.filterSnapshots();
if (snapshots.length < 2) {
return null;
}
- let data = snapshots.map((snapshot, index) => {
+ const data = snapshots.map((snapshot, index) => {
return { x: index, y: snapshot.value };
});
- let domain = [0, d3.max(this.props.history, d => d.value)];
+ const domain = [0, d3.max(this.props.history, d => d.value)];
return <LineChart data={data}
domain={domain}
diff --git a/server/sonar-web/src/main/js/apps/overview/meta.js b/server/sonar-web/src/main/js/apps/overview/meta.js
index 6557f397acd..69058bac60f 100644
--- a/server/sonar-web/src/main/js/apps/overview/meta.js
+++ b/server/sonar-web/src/main/js/apps/overview/meta.js
@@ -65,7 +65,7 @@ export default React.createClass({
},
render() {
- let profiles = (this.props.component.profiles || []).map(profile => {
+ const profiles = (this.props.component.profiles || []).map(profile => {
return (
<li key={profile.key}>
<span className="note spacer-right">({profile.language})</span>
@@ -73,8 +73,8 @@ export default React.createClass({
</li>
);
});
- let links = (this.props.component.links || []).map(link => {
- let iconClassName = `spacer-right icon-color-link icon-${link.type}`;
+ const links = (this.props.component.links || []).map(link => {
+ const iconClassName = `spacer-right icon-color-link icon-${link.type}`;
return (
<li key={link.type}>
<i className={iconClassName}/>
@@ -83,19 +83,19 @@ export default React.createClass({
);
});
- let descriptionCard = this.props.component.description ? (
+ const descriptionCard = this.props.component.description ? (
<div className="overview-meta-description big-spacer-bottom">
{this.props.component.description}
</div>
) : null;
- let linksCard = _.size(this.props.component.links) > 0 ? (
+ const linksCard = _.size(this.props.component.links) > 0 ? (
<ul className="overview-meta-list big-spacer-bottom">
{links}
</ul>
) : null;
- let keyCard = (
+ const keyCard = (
<div>
<h4 className="overview-meta-header">{translate('key')}</h4>
<input
@@ -106,14 +106,14 @@ export default React.createClass({
</div>
);
- let profilesCard = !this.isView() && !this.isDeveloper() && _.size(this.props.component.profiles) > 0 ? (
+ const profilesCard = !this.isView() && !this.isDeveloper() && _.size(this.props.component.profiles) > 0 ? (
<div>
<h4 className="overview-meta-header">{translate('overview.quality_profiles')}</h4>
<ul className="overview-meta-list">{profiles}</ul>
</div>
) : null;
- let gateCard = !this.isView() && !this.isDeveloper() && this.props.component.gate ? (
+ const gateCard = !this.isView() && !this.isDeveloper() && this.props.component.gate ? (
<div className="big-spacer-bottom">
<h4 className="overview-meta-header">{translate('overview.quality_gate')}</h4>
<ul className="overview-meta-list">
diff --git a/server/sonar-web/src/main/js/apps/overview/overview.js b/server/sonar-web/src/main/js/apps/overview/overview.js
index ad358b4ed11..00f592bdae3 100644
--- a/server/sonar-web/src/main/js/apps/overview/overview.js
+++ b/server/sonar-web/src/main/js/apps/overview/overview.js
@@ -22,10 +22,6 @@ import React from 'react';
import Gate from './gate/gate';
import GeneralMain from './main/main';
import Meta from './meta';
-import { StructureMain } from './domains/structure-domain';
-import { DuplicationsMain } from './domains/duplications-domain';
-import { CoverageMain } from './domains/coverage-domain';
-import { DebtMain } from './domains/debt-domain';
import { getMetrics } from '../../api/metrics';
import { RouterMixin } from '../../components/router/router';
@@ -63,48 +59,12 @@ export const Overview = React.createClass({
</div>;
},
- renderSize () {
- return <div className="overview">
- <StructureMain {...this.props} {...this.state}/>
- </div>;
- },
-
- renderDuplications () {
- return <div className="overview">
- <DuplicationsMain {...this.props} {...this.state}/>
- </div>;
- },
-
- renderTests () {
- return <div className="overview">
- <CoverageMain {...this.props} {...this.state}/>
- </div>;
- },
-
- renderIssues () {
- return <div className="overview">
- <DebtMain {...this.props} {...this.state}/>
- </div>;
- },
-
render () {
if (!this.state.ready) {
return this.renderLoading();
}
- switch (this.state.route) {
- case '':
- return this.renderMain();
- case '/structure':
- return this.renderSize();
- case '/duplications':
- return this.renderDuplications();
- case '/coverage':
- return this.renderTests();
- case '/debt':
- return this.renderIssues();
- default:
- throw new Error('Unknown route: ' + this.state.route);
- }
+
+ return this.renderMain();
}
});
diff --git a/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js b/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js
index 84c4f277689..eb7223ab3f3 100644
--- a/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js
+++ b/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js
@@ -30,15 +30,6 @@ import {
getComponentDashboardManagementUrl
} from '../../../helpers/urls';
-
-const FIXED_DASHBOARDS = [
- { link: '', name: 'overview.page' },
- { link: '/debt', name: 'overview.domain.debt' },
- { link: '/coverage', name: 'overview.domain.coverage' },
- { link: '/duplications', name: 'overview.domain.duplications' },
- { link: '/structure', name: 'overview.domain.structure' }
-];
-
const SETTINGS_URLS = [
'/project/settings',
'/project/profile',
@@ -68,69 +59,67 @@ export default React.createClass({
},
periodParameter() {
- let params = qs.parse(window.location.search.substr(1));
+ const params = qs.parse(window.location.search.substr(1));
return params.period ? `&period=${params.period}` : '';
},
getPeriod() {
- let params = qs.parse(window.location.search.substr(1));
+ const params = qs.parse(window.location.search.substr(1));
return params.period;
},
- isFixedDashboardActive(fixedDashboard) {
- let path = window.location.pathname;
- return path === `/overview${fixedDashboard.link}`;
+ isFixedDashboardActive() {
+ const path = window.location.pathname;
+ return path.indexOf('/overview') === 0;
},
isCustomDashboardActive(customDashboard) {
- let path = window.location.pathname;
- let params = qs.parse(window.location.search.substr(1));
+ const path = window.location.pathname;
+ const params = qs.parse(window.location.search.substr(1));
return path.indexOf('/dashboard') === 0 && params['did'] === `${customDashboard.key}`;
},
isCustomDashboardsActive () {
- let dashboards = this.props.component.dashboards;
+ const dashboards = this.props.component.dashboards;
return _.any(dashboards, this.isCustomDashboardActive) ||
this.isDashboardManagementActive() ||
this.isDefaultDeveloperDashboardActive();
},
isDefaultDeveloperDashboardActive() {
- let path = window.location.pathname;
+ const path = window.location.pathname;
return this.isDeveloper() && path.indexOf('/dashboard') === 0;
},
isDashboardManagementActive () {
- let path = window.location.pathname;
+ const path = window.location.pathname;
return path.indexOf('/dashboards') === 0;
},
- renderFixedDashboards() {
- return FIXED_DASHBOARDS.map(fixedDashboard => {
- let key = 'fixed-dashboard-' + fixedDashboard.link.substr(1);
- let url = getComponentFixedDashboardUrl(this.props.component.key, fixedDashboard.link);
- let name = fixedDashboard.link !== '' ?
- translate(fixedDashboard.name) : <i className="icon-home"/>;
- let className = classNames({ active: this.isFixedDashboardActive(fixedDashboard) });
- return <li key={key} className={className}>
- <a href={url}>{name}</a>
- </li>;
- });
+ renderOverviewLink() {
+ const url = getComponentFixedDashboardUrl(this.props.component.key, '');
+ const name = <i className="icon-home"/>;
+ const className = classNames({ active: this.isFixedDashboardActive() });
+ return (
+ <li key="overview" className={className}>
+ <a href={url}>{name}</a>
+ </li>
+ );
},
renderCustomDashboard(customDashboard) {
- let key = 'custom-dashboard-' + customDashboard.key;
- let url = getComponentDashboardUrl(this.props.component.key, customDashboard.key, this.getPeriod());
- let name = getLocalizedDashboardName(customDashboard.name);
- let className = classNames({ active: this.isCustomDashboardActive(customDashboard) });
+ const key = 'custom-dashboard-' + customDashboard.key;
+ const url = getComponentDashboardUrl(this.props.component.key, customDashboard.key, this.getPeriod());
+ const name = getLocalizedDashboardName(customDashboard.name);
+ const className = classNames({ active: this.isCustomDashboardActive(customDashboard) });
return <li key={key} className={className}>
<a href={url}>{name}</a>
</li>;
},
renderCustomDashboards() {
- let dashboards = this.props.component.dashboards.map(this.renderCustomDashboard);
- let className = classNames('dropdown', { active: this.isCustomDashboardsActive() });
+ const dashboards = this.props.component.dashboards.map(this.renderCustomDashboard);
+ const className = classNames('dropdown', { active: this.isCustomDashboardsActive() });
const managementLink = this.renderDashboardsManagementLink();
return <li className={className}>
<a className="dropdown-toggle" data-toggle="dropdown" href="#">
@@ -149,10 +138,10 @@ export default React.createClass({
if (!window.SS.user) {
return null;
}
- let key = 'dashboard-management';
- let url = getComponentDashboardManagementUrl(this.props.component.key);
- let name = translate('dashboard.manage_dashboards');
- let className = classNames('pill-right', { active: this.isDashboardManagementActive() });
+ const key = 'dashboard-management';
+ const url = getComponentDashboardManagementUrl(this.props.component.key);
+ const name = translate('dashboard.manage_dashboards');
+ const className = classNames('pill-right', { active: this.isDashboardManagementActive() });
return <li key={key} className={className}>
<a className="note" href={url}>{name}</a>
</li>;
@@ -187,7 +176,7 @@ export default React.createClass({
},
renderAdministration() {
- let shouldShowAdministration =
+ const shouldShowAdministration =
this.props.conf.showActionPlans ||
this.props.conf.showBackgroundTasks ||
this.props.conf.showDeletion ||
@@ -202,10 +191,10 @@ export default React.createClass({
if (!shouldShowAdministration) {
return null;
}
- let isSettingsActive = SETTINGS_URLS.some(url => {
+ const isSettingsActive = SETTINGS_URLS.some(url => {
return window.location.href.indexOf(url) !== -1;
});
- let className = 'dropdown' + (isSettingsActive ? ' active' : '');
+ const className = 'dropdown' + (isSettingsActive ? ' active' : '');
return (
<li className={className}>
<a className="dropdown-toggle navbar-admin-link" data-toggle="dropdown" href="#">
@@ -319,18 +308,18 @@ export default React.createClass({
},
renderExtensions() {
- let extensions = this.props.conf.extensions || [];
+ const extensions = this.props.conf.extensions || [];
return extensions.map(e => {
return this.renderLink(e.url, e.name, e.url);
});
},
renderTools() {
- let component = this.props.component;
+ const component = this.props.component;
if (!component.isComparable && !_.size(component.extensions)) {
return null;
}
- let tools = [];
+ const tools = [];
(component.extensions || []).forEach(e => {
tools.push(this.renderLink(e.url, e.name));
});
@@ -338,17 +327,31 @@ export default React.createClass({
},
render() {
- return (
- <ul className="nav navbar-nav nav-tabs">
- {!this.isDeveloper() && this.renderFixedDashboards()}
- {this.renderCustomDashboards()}
- {this.renderCodeLink()}
- {this.renderProjectsLink()}
- {this.renderComponentIssuesLink()}
- {this.renderComponentMeasuresLink()}
- {this.renderTools()}
- {this.renderAdministration()}
- </ul>
- );
+ if (this.isDeveloper()) {
+ return (
+ <ul className="nav navbar-nav nav-tabs">
+ {this.renderCustomDashboards()}
+ {this.renderComponentIssuesLink()}
+ {this.renderComponentMeasuresLink()}
+ {this.renderCodeLink()}
+ {this.renderProjectsLink()}
+ {this.renderTools()}
+ {this.renderAdministration()}
+ </ul>
+ );
+ } else {
+ return (
+ <ul className="nav navbar-nav nav-tabs">
+ {this.renderOverviewLink()}
+ {this.renderComponentIssuesLink()}
+ {this.renderComponentMeasuresLink()}
+ {this.renderCodeLink()}
+ {this.renderProjectsLink()}
+ {this.renderCustomDashboards()}
+ {this.renderTools()}
+ {this.renderAdministration()}
+ </ul>
+ );
+ }
}
});