From 1d2f7dabab0e8678775ebdaa65e41bebf75bbf26 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 3 Mar 2016 17:44:29 +0100 Subject: improve code quality --- .../src/main/js/apps/component-measures/app.js | 10 +- .../component-measures/components/AllMeasures.js | 105 +++++++++++++++ .../components/AllMeasuresDomain.js | 64 ++++++++++ .../components/AllMeasuresList.js | 136 -------------------- .../components/ComponentsList.js | 75 ----------- .../apps/component-measures/components/IconList.js | 35 +++++ .../apps/component-measures/components/IconTree.js | 35 +++++ .../apps/component-measures/components/IconUp.js | 36 ++++++ .../apps/component-measures/components/ListIcon.js | 35 ----- .../components/MeasureDetails.js | 69 ++++------ .../components/MeasureDetailsHeader.js | 56 ++++++++ .../components/MeasureDrilldown.js | 15 +-- .../components/MeasureDrilldownComponents.js | 77 +++++++++++ .../components/MeasureDrilldownEmpty.js | 30 +++++ .../components/MeasureDrilldownList.js | 109 ++++++++++++++++ .../components/MeasureDrilldownTree.js | 129 +++++++++++++++++++ .../component-measures/components/MeasureList.js | 123 ------------------ .../component-measures/components/MeasureTree.js | 141 --------------------- .../component-measures/components/NoResults.js | 30 ----- .../apps/component-measures/components/TreeIcon.js | 35 ----- .../apps/component-measures/components/UpIcon.js | 36 ------ .../src/main/js/apps/component-measures/styles.css | 53 ++++---- .../src/main/js/apps/component-measures/utils.js | 24 ++++ .../src/main/js/apps/overview/helpers/periods.js | 10 +- server/sonar-web/src/main/js/helpers/periods.js | 46 +++++++ 25 files changed, 805 insertions(+), 709 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/AllMeasures.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresDomain.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresList.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/ComponentsList.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/IconList.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/IconTree.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/IconUp.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/ListIcon.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownComponents.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownEmpty.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownList.js create mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownTree.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureList.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/MeasureTree.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/NoResults.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/TreeIcon.js delete mode 100644 server/sonar-web/src/main/js/apps/component-measures/components/UpIcon.js create mode 100644 server/sonar-web/src/main/js/helpers/periods.js (limited to 'server/sonar-web/src') diff --git a/server/sonar-web/src/main/js/apps/component-measures/app.js b/server/sonar-web/src/main/js/apps/component-measures/app.js index 4077b2f777d..babee01e50d 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/app.js +++ b/server/sonar-web/src/main/js/apps/component-measures/app.js @@ -23,10 +23,10 @@ import { Router, Route, IndexRoute, Redirect, IndexRedirect, useRouterHistory } import { createHistory } from 'history'; import ComponentMeasuresApp from './components/ComponentMeasuresApp'; -import AllMeasuresList from './components/AllMeasuresList'; +import AllMeasuresList from './components/AllMeasures'; import MeasureDetails from './components/MeasureDetails'; -import MeasureTree from './components/MeasureTree'; -import MeasureList from './components/MeasureList'; +import MeasureDrilldownTree from './components/MeasureDrilldownTree'; +import MeasureDrilldownList from './components/MeasureDrilldownList'; import './styles.css'; @@ -53,8 +53,8 @@ window.sonarqube.appStarted.then(options => { - - + + diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasures.js b/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasures.js new file mode 100644 index 00000000000..26c6ca254d2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasures.js @@ -0,0 +1,105 @@ +/* + * 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 Spinner from './Spinner'; +import AllMeasuresDomain from './AllMeasuresDomain'; +import { getLeakValue } from '../utils'; +import { getMeasuresAndMeta } from '../../../api/measures'; +import { getLeakPeriodLabel } from '../../../helpers/periods'; + +export default class AllMeasures extends React.Component { + state = { + fetching: true, + measures: [] + }; + + componentDidMount () { + this.mounted = true; + this.fetchMeasures(); + } + + componentWillUnmount () { + this.mounted = false; + } + + fetchMeasures () { + const { component } = this.context; + const { metrics } = this.props; + const metricKeys = metrics + .filter(metric => !metric.hidden) + .filter(metric => metric.type !== 'DATA' && metric.type !== 'DISTRIB') + .map(metric => metric.key); + + getMeasuresAndMeta(component.key, metricKeys, { additionalFields: 'periods' }).then(r => { + if (this.mounted) { + const measures = r.component.measures + .map(measure => { + const metric = metrics.find(metric => metric.key === measure.metric); + const leak = getLeakValue(measure); + return { ...measure, metric, leak }; + }) + .filter(measure => measure.value != null || measure.leak != null); + + this.setState({ + measures, + periods: r.periods, + fetching: false + }); + } + }); + } + + render () { + const { fetching, measures, periods } = this.state; + + if (fetching) { + return ; + } + + const { component } = this.context; + const domains = _.sortBy(_.pairs(_.groupBy(measures, measure => measure.metric.domain)).map(r => { + const [name, measures] = r; + const sortedMeasures = _.sortBy(measures, measure => measure.metric.name); + + return { name, measures: sortedMeasures }; + }), 'name'); + + const leakPeriodLabel = getLeakPeriodLabel(periods); + + return ( +
    + {domains.map((domain, index) => ( + + ))} +
+ ); + } +} + +AllMeasures.contextTypes = { + component: React.PropTypes.object +}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresDomain.js b/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresDomain.js new file mode 100644 index 00000000000..ba5c86459bf --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresDomain.js @@ -0,0 +1,64 @@ +/* + * 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 { Link } from 'react-router'; + +import { formatLeak } from '../utils'; +import { formatMeasure } from '../../../helpers/measures'; +import { translateWithParameters } from '../../../helpers/l10n'; + +export default function AllMeasuresDomain ({ domain, component, displayLeakHeader, leakPeriodLabel }) { + return ( +
  • +
    +

    {domain.name}

    + {displayLeakHeader && ( +
    + {translateWithParameters('overview.leak_period_x', leakPeriodLabel)} +
    + )} +
    + +
      + {domain.measures.map(measure => ( +
    • +
      + {measure.metric.name} +
      +
      + {measure.value != null && ( + + {formatMeasure(measure.value, measure.metric.type)} + + )} +
      +
      + {measure.leak != null && ( + + {formatLeak(measure.leak, measure.metric)} + + )} +
      +
    • + ))} +
    +
  • + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresList.js b/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresList.js deleted file mode 100644 index 12a43009b1b..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/AllMeasuresList.js +++ /dev/null @@ -1,136 +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 { Link } from 'react-router'; - -import Spinner from './Spinner'; -import { getLeakValue, formatLeak } from '../utils'; -import { getMeasuresAndMeta } from '../../../api/measures'; -import { formatMeasure } from '../../../helpers/measures'; -import { translateWithParameters } from '../../../helpers/l10n'; - -import { getPeriodLabel } from '../../overview/helpers/periods'; - -export default class ComponentMeasuresApp extends React.Component { - state = { - fetching: true, - measures: [] - }; - - componentDidMount () { - this.mounted = true; - this.fetchMeasures(); - } - - componentWillUnmount () { - this.mounted = false; - } - - fetchMeasures () { - const { component } = this.context; - const { metrics } = this.props; - const metricKeys = metrics - .filter(metric => !metric.hidden) - .filter(metric => metric.type !== 'DATA' && metric.type !== 'DISTRIB') - .map(metric => metric.key); - - getMeasuresAndMeta(component.key, metricKeys, { additionalFields: 'periods' }).then(r => { - if (this.mounted) { - const measures = r.component.measures - .map(measure => { - const metric = metrics.find(metric => metric.key === measure.metric); - const leak = getLeakValue(measure); - return { ...measure, metric, leak }; - }) - .filter(measure => measure.value != null || measure.leak != null); - - this.setState({ - measures, - periods: r.periods, - fetching: false - }); - } - }); - } - - render () { - const { fetching, measures, periods } = this.state; - - if (fetching) { - return ; - } - - const { component } = this.context; - const domains = _.sortBy(_.pairs(_.groupBy(measures, measure => measure.metric.domain)).map(r => { - const [name, measures] = r; - const sortedMeasures = _.sortBy(measures, measure => measure.metric.name); - - return { name, measures: sortedMeasures }; - }), 'name'); - - const leakLabel = getPeriodLabel(periods, 1); - - return ( -
      - {domains.map((domain, index) => ( -
    • -
      -

      {domain.name}

      - {index === 0 && ( -
      - {translateWithParameters('overview.leak_period_x', leakLabel)} -
      - )} -
      - -
        - {domain.measures.map(measure => ( -
      • -
        - {measure.metric.name} -
        -
        - {measure.value != null && ( - - {formatMeasure(measure.value, measure.metric.type)} - - )} -
        -
        - {measure.leak != null && ( - - {formatLeak(measure.leak, measure.metric)} - - )} -
        -
      • - ))} -
      -
    • - ))} -
    - ); - } -} - -ComponentMeasuresApp.contextTypes = { - component: React.PropTypes.object -}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/ComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures/components/ComponentsList.js deleted file mode 100644 index 9f0ebd78cbf..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/ComponentsList.js +++ /dev/null @@ -1,75 +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 UpIcon from './UpIcon'; -import QualifierIcon from '../../../components/shared/qualifier-icon'; -import { formatMeasure } from '../../../helpers/measures'; -import { formatLeak } from '../utils'; - -export default function ComponentsList ({ components, selected, parent, metric, onClick }) { - const handleClick = (component, e) => { - e.preventDefault(); - e.target.blur(); - onClick(component); - }; - - return ( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/IconList.js b/server/sonar-web/src/main/js/apps/component-measures/components/IconList.js new file mode 100644 index 00000000000..6725685c36b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/IconList.js @@ -0,0 +1,35 @@ +/* + * 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'; + +export default function ListIcon () { + /* eslint max-len: 0 */ + return ( + + + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/IconTree.js b/server/sonar-web/src/main/js/apps/component-measures/components/IconTree.js new file mode 100644 index 00000000000..1b9cb2ca79d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/IconTree.js @@ -0,0 +1,35 @@ +/* + * 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'; + +export default function IconTree () { + /* eslint max-len: 0 */ + return ( + + + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/IconUp.js b/server/sonar-web/src/main/js/apps/component-measures/components/IconUp.js new file mode 100644 index 00000000000..462d07bb17b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/IconUp.js @@ -0,0 +1,36 @@ +/* + * 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'; + +export default function IconUp () { + /* eslint max-len: 0 */ + return ( + + + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/ListIcon.js b/server/sonar-web/src/main/js/apps/component-measures/components/ListIcon.js deleted file mode 100644 index 6725685c36b..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/ListIcon.js +++ /dev/null @@ -1,35 +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'; - -export default function ListIcon () { - /* eslint max-len: 0 */ - return ( - - - - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js index 20e3cf6c53e..adeef588454 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetails.js @@ -20,14 +20,12 @@ import React from 'react'; import Spinner from './Spinner'; +import MeasureDetailsHeader from './MeasureDetailsHeader'; import MeasureDrilldown from './MeasureDrilldown'; -import { getLeakValue, formatLeak } from '../utils'; -import { getMeasuresAndMeta } from '../../../api/measures'; -import { formatMeasure } from '../../../helpers/measures'; -import { translateWithParameters } from '../../../helpers/l10n'; -import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -import { getPeriodLabel } from '../../overview/helpers/periods'; +import { enhanceWithLeak } from '../utils'; +import { getMeasuresAndMeta } from '../../../api/measures'; +import { getLeakPeriodLabel } from '../../../helpers/periods'; export default class MeasureDetails extends React.Component { state = {}; @@ -35,10 +33,12 @@ export default class MeasureDetails extends React.Component { componentWillMount () { const { metrics } = this.props; const { metricKey } = this.props.params; - const { router, component } = this.context; - const metric = metrics.find(metric => metric.key === metricKey); - if (!metric) { + this.metric = metrics.find(metric => metric.key === metricKey); + + if (!this.metric) { + const { router, component } = this.context; + router.replace({ pathname: '/', query: { id: component.key } @@ -66,14 +66,16 @@ export default class MeasureDetails extends React.Component { const { metricKey } = this.props.params; const { component } = this.context; - getMeasuresAndMeta(component.key, [metricKey], { additionalFields: 'periods' }).then(r => { + getMeasuresAndMeta( + component.key, + [metricKey], + { additionalFields: 'periods' } + ).then(r => { const measures = r.component.measures; if (this.mounted && measures.length === 1) { - const measure = { - ...measures[0], - leak: getLeakValue(measures[0]) - }; + const measure = enhanceWithLeak(measures[0]); + this.setState({ measure, periods: r.periods @@ -83,48 +85,25 @@ export default class MeasureDetails extends React.Component { } render () { - const { metrics, children } = this.props; - const { metricKey, tab } = this.props.params; - const metric = metrics.find(metric => metric.key === metricKey); const { measure, periods } = this.state; if (!measure) { return ; } - const finalTab = tab || 'tree'; - const leakLabel = getPeriodLabel(periods, 1); + const { tab } = this.props.params; + const leakPeriodLabel = getLeakPeriodLabel(periods); return (
    -

    - {metric.name} -

    - - {measure && ( - -
    - {measure.value != null && ( - - {formatMeasure(measure.value, metric.type)} - - )} - - {measure.leak != null && ( - - {formatLeak(measure.leak, metric)} - - )} -
    -
    - )} + {measure && ( - - {children} + + {this.props.children} )}
    diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js new file mode 100644 index 00000000000..93d0e8b58f3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDetailsHeader.js @@ -0,0 +1,56 @@ +/* + * 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 { formatLeak } from '../utils'; +import { formatMeasure } from '../../../helpers/measures'; +import { translateWithParameters } from '../../../helpers/l10n'; +import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; + +export default function MeasureDetailsHeader ({ measure, metric, leakPeriodLabel }) { + const leakPeriodTooltip = translateWithParameters('overview.leak_period_x', leakPeriodLabel); + + return ( +
    +

    + {metric.name} +

    + + +
    + {measure.value != null && ( +
    + {formatMeasure(measure.value, metric.type)} +
    + )} + + {measure.leak != null && ( +
    + {formatLeak(measure.leak, metric)} +
    + )} +
    +
    +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldown.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldown.js index 7d1ebec1867..a66d23ebcda 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldown.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldown.js @@ -20,8 +20,8 @@ import React from 'react'; import { Link } from 'react-router'; -import ListIcon from './ListIcon'; -import TreeIcon from './TreeIcon'; +import IconList from './IconList'; +import IconTree from './IconTree'; import { translate } from '../../../helpers/l10n'; export default class MeasureDrilldown extends React.Component { @@ -29,19 +29,16 @@ export default class MeasureDrilldown extends React.Component { const { metric, children } = this.props; const { component } = this.context; - const child = React.cloneElement(children, { - component, - metric - }); + const child = React.cloneElement(children, { component, metric }); return (
    -
      +
      • - + {translate('component_measures.tab.tree')}
      • @@ -49,7 +46,7 @@ export default class MeasureDrilldown extends React.Component { - + {translate('component_measures.tab.list')} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownComponents.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownComponents.js new file mode 100644 index 00000000000..a020e83f0db --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownComponents.js @@ -0,0 +1,77 @@ +/* + * 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 MeasureDrilldownEmpty from './MeasureDrilldownEmpty'; +import IconUp from './IconUp'; +import QualifierIcon from '../../../components/shared/qualifier-icon'; +import { formatMeasure } from '../../../helpers/measures'; +import { formatLeak } from '../utils'; + +export default function MeasureDrilldownComponents ({ components, selected, parent, metric, onClick }) { + const handleClick = (component, e) => { + e.preventDefault(); + e.target.blur(); + onClick(component); + }; + + return ( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownEmpty.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownEmpty.js new file mode 100644 index 00000000000..ede861f8382 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownEmpty.js @@ -0,0 +1,30 @@ +/* + * 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 { translate } from '../../../helpers/l10n'; + +export default function MeasureDrilldownEmpty () { + return ( +
        + {translate('no_results')} +
        + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownList.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownList.js new file mode 100644 index 00000000000..0a0e49601aa --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownList.js @@ -0,0 +1,109 @@ +/* + * 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 Spinner from './Spinner'; +import MeasureDrilldownComponents from './MeasureDrilldownComponents'; +import SourceViewer from '../../code/components/SourceViewer'; + +import { enhanceWithSingleMeasure } from '../utils'; +import { getFiles } from '../../../api/components'; + +export default class MeasureDrilldownList extends React.Component { + state = { + components: [], + selected: null, + fetching: true + }; + + componentDidMount () { + this.mounted = true; + this.fetchComponents(this.context.component); + } + + componentDidUpdate (nextProps, nextState, nextContext) { + if ((nextProps.metric !== this.props.metric) || + (nextContext.component !== this.context.component)) { + this.fetchComponents(nextContext.component); + } + } + + componentWillUnmount () { + this.mounted = false; + } + + fetchComponents (baseComponent) { + const { metric } = this.props; + const asc = metric.direction === 1; + + const options = { + s: 'metric,name', + metricSort: metric.key, + asc + }; + + this.setState({ fetching: true }); + + getFiles(baseComponent.key, [metric.key], options).then(files => { + if (this.mounted) { + const components = enhanceWithSingleMeasure(files); + + this.setState({ + components, + selected: null, + fetching: false + }); + } + }); + } + + handleFileClick (selected) { + this.setState({ selected }); + } + + render () { + const { metric } = this.props; + const { components, selected, fetching } = this.state; + + if (fetching) { + return ; + } + + return ( +
        + + + {selected && ( +
        + +
        + )} +
        + ); + } +} + +MeasureDrilldownList.contextTypes = { + component: React.PropTypes.object +}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownTree.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownTree.js new file mode 100644 index 00000000000..47ae38b67cb --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureDrilldownTree.js @@ -0,0 +1,129 @@ +/* + * 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 Spinner from './Spinner'; +import MeasureDrilldownComponents from './MeasureDrilldownComponents'; +import SourceViewer from '../../code/components/SourceViewer'; + +import { enhanceWithSingleMeasure } from '../utils'; +import { getChildren } from '../../../api/components'; + +export default class MeasureDrilldownTree extends React.Component { + state = { + components: [], + breadcrumbs: [], + selected: null, + fetching: true + }; + + componentDidMount () { + this.mounted = true; + this.fetchComponents(this.context.component); + } + + componentDidUpdate (nextProps, nextState, nextContext) { + if ((nextProps.metric !== this.props.metric) || + (nextContext.component !== this.context.component)) { + this.fetchComponents(nextContext.component); + } + } + + componentWillUnmount () { + this.mounted = false; + } + + fetchComponents (baseComponent) { + const { metric } = this.props; + const asc = metric.direction === 1; + + const options = { + s: 'metric,name', + metricSort: metric.key, + asc + }; + + this.setState({ fetching: true }); + + getChildren(baseComponent.key, [metric.key], options).then(children => { + if (this.mounted) { + const components = enhanceWithSingleMeasure(children); + + const indexInBreadcrumbs = this.state.breadcrumbs + .findIndex(component => component === baseComponent); + + const breadcrumbs = indexInBreadcrumbs !== -1 ? + this.state.breadcrumbs.slice(0, indexInBreadcrumbs + 1) : + [...this.state.breadcrumbs, baseComponent]; + + this.setState({ + baseComponent, + breadcrumbs, + components, + selected: null, + fetching: false + }); + } + }); + } + + handleFileClick (component) { + if (component.qualifier === 'FIL' || component.qualifier === 'UTS') { + this.handleFileOpen(component); + } else { + this.fetchComponents(component); + } + } + + handleFileOpen (selected) { + this.setState({ selected }); + } + + render () { + const { metric } = this.props; + const { components, selected, breadcrumbs, fetching } = this.state; + const parent = breadcrumbs.length > 1 ? breadcrumbs[breadcrumbs.length - 2] : null; + + if (fetching) { + return ; + } + + return ( +
        + + + {selected && ( +
        + +
        + )} +
        + ); + } +} + +MeasureDrilldownTree.contextTypes = { + component: React.PropTypes.object +}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureList.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureList.js deleted file mode 100644 index 322d7b5eb13..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureList.js +++ /dev/null @@ -1,123 +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 Spinner from './Spinner'; -import ComponentsList from './ComponentsList'; -import SourceViewer from '../../code/components/SourceViewer'; -import NoResults from './NoResults'; -import { getSingleMeasureValue, getSingleLeakValue } from '../utils'; -import { getFiles } from '../../../api/components'; - -export default class MeasurePlainList extends React.Component { - state = { - components: [], - selected: null, - fetching: true - }; - - componentDidMount () { - this.mounted = true; - this.fetchComponents(this.context.component); - } - - componentDidUpdate (nextProps, nextState, nextContext) { - if ((nextProps.metric !== this.props.metric) || - (nextContext.component !== this.context.component)) { - this.fetchComponents(nextContext.component); - } - } - - componentWillUnmount () { - this.mounted = false; - } - - fetchComponents (baseComponent) { - const { metric } = this.props; - const asc = metric.direction === 1; - - const options = { - s: 'metric,name', - metricSort: metric.key, - asc - }; - - this.setState({ fetching: true }); - - getFiles(baseComponent.key, [metric.key], options).then(children => { - if (this.mounted) { - const componentsWithMappedMeasure = children - .map(component => { - return { - ...component, - value: getSingleMeasureValue(component.measures), - leak: getSingleLeakValue(component.measures) - }; - }) - .filter(component => component.value != null || component.leak != null); - - this.setState({ - components: componentsWithMappedMeasure, - selected: null, - fetching: false - }); - } - }); - } - - handleFileClick (selected) { - this.setState({ selected }); - } - - render () { - const { metric } = this.props; - const { components, selected, fetching } = this.state; - - if (fetching) { - return ; - } - - if (!components.length) { - return ; - } - - return ( -
        -
        - -
        - - {selected && ( -
        - -
        - )} -
        - ); - } -} - -MeasurePlainList.contextTypes = { - component: React.PropTypes.object -}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureTree.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureTree.js deleted file mode 100644 index d39f0eda0bc..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureTree.js +++ /dev/null @@ -1,141 +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 Spinner from './Spinner'; -import ComponentsList from './ComponentsList'; -import NoResults from './NoResults'; -import SourceViewer from '../../code/components/SourceViewer'; -import { getSingleMeasureValue, getSingleLeakValue } from '../utils'; -import { getChildren } from '../../../api/components'; - -export default class MeasureTree extends React.Component { - state = { - components: [], - breadcrumbs: [], - selected: null, - fetching: true - }; - - componentDidMount () { - this.mounted = true; - this.fetchComponents(this.context.component); - } - - componentDidUpdate (nextProps, nextState, nextContext) { - if ((nextProps.metric !== this.props.metric) || - (nextContext.component !== this.context.component)) { - this.fetchComponents(nextContext.component); - } - } - - componentWillUnmount () { - this.mounted = false; - } - - fetchComponents (baseComponent) { - const { metric } = this.props; - const asc = metric.direction === 1; - - const options = { - s: 'metric,name', - metricSort: metric.key, - asc - }; - - this.setState({ fetching: true }); - - getChildren(baseComponent.key, [metric.key], options).then(children => { - if (this.mounted) { - const componentsWithMappedMeasure = children - .map(component => { - return { - ...component, - value: getSingleMeasureValue(component.measures), - leak: getSingleLeakValue(component.measures) - }; - }) - .filter(component => component.value != null || component.leak != null); - - const indexInBreadcrumbs = this.state.breadcrumbs.findIndex(component => component === baseComponent); - const breadcrumbs = indexInBreadcrumbs !== -1 ? - this.state.breadcrumbs.slice(0, indexInBreadcrumbs + 1) : - [...this.state.breadcrumbs, baseComponent]; - - this.setState({ - baseComponent, - breadcrumbs, - components: componentsWithMappedMeasure, - selected: null, - fetching: false - }); - } - }); - } - - handleFileClick (component) { - if (component.qualifier === 'FIL' || component.qualifier === 'UTS') { - this.handleFileOpen(component); - } else { - this.fetchComponents(component); - } - } - - handleFileOpen (selected) { - this.setState({ selected }); - } - - render () { - const { metric } = this.props; - const { components, selected, breadcrumbs, fetching } = this.state; - const parent = breadcrumbs.length > 1 ? breadcrumbs[breadcrumbs.length - 2] : null; - - if (fetching) { - return ; - } - - if (!components.length) { - return ; - } - - return ( -
        -
        - -
        - - {selected && ( -
        - -
        - )} -
        - ); - } -} - -MeasureTree.contextTypes = { - component: React.PropTypes.object -}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/NoResults.js b/server/sonar-web/src/main/js/apps/component-measures/components/NoResults.js deleted file mode 100644 index db8afedd0be..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/NoResults.js +++ /dev/null @@ -1,30 +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 { translate } from '../../../helpers/l10n'; - -export default function NoResults () { - return ( -
        - {translate('no_results')} -
        - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/TreeIcon.js b/server/sonar-web/src/main/js/apps/component-measures/components/TreeIcon.js deleted file mode 100644 index cd8d28d0313..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/TreeIcon.js +++ /dev/null @@ -1,35 +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'; - -export default function TreeIcon () { - /* eslint max-len: 0 */ - return ( - - - - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/UpIcon.js b/server/sonar-web/src/main/js/apps/component-measures/components/UpIcon.js deleted file mode 100644 index 69c2dd828a1..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/UpIcon.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'; - -export default function UpIcon () { - /* eslint max-len: 0 */ - return ( - - - - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/styles.css b/server/sonar-web/src/main/js/apps/component-measures/styles.css index 5e2a065cd2d..09e238d3e02 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/styles.css +++ b/server/sonar-web/src/main/js/apps/component-measures/styles.css @@ -1,16 +1,13 @@ -.component-measures-domains { +.measures-domains { width: 600px; margin: 20px auto; } -.component-measures-domains > li { -} - -.component-measures-domains > li + li { +.measures-domains > li + li { margin-top: 40px; } -.component-measures-domains-leak-header { +.measures-domains-leak-header { float: right; line-height: 22px; padding: 0 10px; @@ -18,43 +15,37 @@ background-color: #fbf3d5; } -.component-measures-domain-measures { -} - -.component-measures-domain-measures > li { +.domain-measures > li { display: flex; } -.component-measures-domain-measures > li:nth-child(odd) { +.domain-measures > li:nth-child(odd) { background-color: #f8f8f8; } -.component-measures-domain-measures-name, -.component-measures-domain-measures-value { +.domain-measures-name, +.domain-measures-value { padding: 7px 10px; box-sizing: border-box; } -.component-measures-domain-measures-name { +.domain-measures-name { width: calc(100% - 160px); } -.component-measures-domain-measures-value { +.domain-measures-value { width: 80px; text-align: right; } -.component-measures-leak-cell { +.domain-measures-leak { background-color: #fbf3d5; } -.component-measures-domain-measures > li:nth-child(odd) .component-measures-leak-cell { +.domain-measures > li:nth-child(odd) .domain-measures-leak { background-color: #f5eed0; } -.component-measures-domain-name { - margin-bottom: 8px; -} .measure-details { margin-top: 10px; @@ -95,34 +86,34 @@ margin-top: 20px; } -.measure-details-mode { +.measure-details-drilldown-mode { display: flex; padding-left: 10px; padding-right: 10px; border-bottom: 1px solid #e6e6e6; } -.measure-details-mode > li { +.measure-details-drilldown-mode > li { margin-bottom: -1px; } -.measure-details-mode > li + li { +.measure-details-drilldown-mode > li + li { margin-left: 2px; } -.measure-details-mode > li > a { +.measure-details-drilldown-mode > li > a { display: inline-block; padding: 5px 10px; border-bottom: 2px solid transparent; color: #444; } -.measure-details-mode > li > a:hover, -.measure-details-mode > li > a.active { +.measure-details-drilldown-mode > li > a:hover, +.measure-details-drilldown-mode > li > a.active { border-bottom-color: #4b9fd5; } -.measure-details-mode > li > a.active .measure-tab-icon path { +.measure-details-drilldown-mode > li > a.active .measure-tab-icon path { fill: #4b9fd5; } @@ -140,7 +131,7 @@ padding-bottom: 6px; } -.measure-details-components > ul > li > a { +.measure-details-components > li > a { display: flex; padding-top: 5px; padding-bottom: 5px; @@ -148,8 +139,8 @@ color: #444; } -.measure-details-components > ul > li > a:hover, -.measure-details-components > ul > li > a.selected { +.measure-details-components > li > a:hover, +.measure-details-components > li > a.selected { background-color: #cae3f2 !important; } @@ -207,5 +198,5 @@ } .measures-details-components-empty { - padding: 20px; + padding: 10px; } diff --git a/server/sonar-web/src/main/js/apps/component-measures/utils.js b/server/sonar-web/src/main/js/apps/component-measures/utils.js index 39d0f5ec2cc..b3eef46c626 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/utils.js +++ b/server/sonar-web/src/main/js/apps/component-measures/utils.js @@ -58,3 +58,27 @@ export function formatLeak (value, metric) { return formatMeasureVariation(value, metric.type); } } + +export function enhanceWithLeak (measures) { + function enhanceSingle (measure) { + return { ...measure, leak: getLeakValue(measure) }; + } + + if (Array.isArray(measures)) { + return measures.map(enhanceSingle); + } else { + return enhanceSingle(measures); + } +} + +export function enhanceWithSingleMeasure (components) { + return components + .map(component => { + return { + ...component, + value: getSingleMeasureValue(component.measures), + leak: getSingleLeakValue(component.measures) + }; + }) + .filter(component => component.value != null || component.leak != null); +} diff --git a/server/sonar-web/src/main/js/apps/overview/helpers/periods.js b/server/sonar-web/src/main/js/apps/overview/helpers/periods.js index 3e1e1d5d89f..80bb9b7a308 100644 --- a/server/sonar-web/src/main/js/apps/overview/helpers/periods.js +++ b/server/sonar-web/src/main/js/apps/overview/helpers/periods.js @@ -19,8 +19,8 @@ */ import _ from 'underscore'; import moment from 'moment'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { getPeriodLabel as getLabel } from '../../../helpers/periods'; export function getPeriodLabel (periods, periodIndex) { const period = _.findWhere(periods, { index: periodIndex }); @@ -29,13 +29,7 @@ export function getPeriodLabel (periods, periodIndex) { return null; } - const parameter = period.modeParam || period.parameter; - - if (period.mode === 'previous_version' && !parameter) { - return translate('overview.period.previous_version_only_date'); - } - - return translateWithParameters(`overview.period.${period.mode}`, parameter); + return getLabel(period); } diff --git a/server/sonar-web/src/main/js/helpers/periods.js b/server/sonar-web/src/main/js/helpers/periods.js new file mode 100644 index 00000000000..48006199d2a --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/periods.js @@ -0,0 +1,46 @@ +/* + * 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 { translate, translateWithParameters } from './l10n'; + +export function getLeakPeriod (periods) { + if (!Array.isArray(periods)) { + return null; + } + + return periods.find(period => period.index === 1); +} + +export function getPeriodLabel (period) { + if (!period) { + return null; + } + + const parameter = period.modeParam || period.parameter; + + if (period.mode === 'previous_version' && !parameter) { + return translate('overview.period.previous_version_only_date'); + } + + return translateWithParameters(`overview.period.${period.mode}`, parameter); +} + +export function getLeakPeriodLabel (periods) { + return getPeriodLabel(getLeakPeriod(periods)); +} -- cgit v1.2.3