From: Grégoire Aubert Date: Tue, 25 Jul 2017 11:37:00 +0000 (+0200) Subject: Move the previous measure page to temporary url X-Git-Tag: 6.6-RC1~659 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4c0bc4110c7c0e9083189c9830bffebab9879e1b;p=sonarqube.git Move the previous measure page to temporary url --- diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js index 5e3038d65f5..ebf096e40e3 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js @@ -121,13 +121,13 @@ export default class ComponentNavMenu extends React.PureComponent { ); } - renderComponentMeasuresLink() { + renderComponentMeasuresOldLink() { return (
  • - {translate('layout.measures')} + Old Measures
  • ); @@ -359,7 +359,7 @@ export default class ComponentNavMenu extends React.PureComponent { {this.renderDashboardLink()} {this.renderIssuesLink()} - {this.renderComponentMeasuresLink()} + {this.renderComponentMeasuresOldLink()} {this.renderCodeLink()} {this.renderActivityLink()} {this.renderAdministration()} diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.js.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.js.snap index 1772a834780..28da18be296 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.js.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.js.snap @@ -44,7 +44,7 @@ exports[`should work with extensions 1`] = ` style={Object {}} to={ Object { - "pathname": "/component_measures", + "pathname": "/component_measures_old", "query": Object { "id": "foo", }, @@ -243,7 +243,7 @@ exports[`should work with multiple extensions 1`] = ` style={Object {}} to={ Object { - "pathname": "/component_measures", + "pathname": "/component_measures_old", "query": Object { "id": "foo", }, diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.js b/server/sonar-web/src/main/js/app/utils/startReactApp.js index cda4a172b5e..52dc397468c 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.js +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.js @@ -45,7 +45,7 @@ import backgroundTasksRoutes from '../../apps/background-tasks/routes'; import codeRoutes from '../../apps/code/routes'; import codingRulesRoutes from '../../apps/coding-rules/routes'; import componentRoutes from '../../apps/component/routes'; -import componentMeasuresRoutes from '../../apps/component-measures/routes'; +import componentMeasuresRoutes from '../../apps/component-measures-old/routes'; import customMeasuresRoutes from '../../apps/custom-measures/routes'; import groupsRoutes from '../../apps/groups/routes'; import issuesRoutes from '../../apps/issues/routes'; @@ -170,7 +170,7 @@ const startReactApp = () => { getComponent={() => import('../components/ProjectContainer').then(i => i.default)}> - + diff --git a/server/sonar-web/src/main/js/apps/code/components/ComponentMeasure.js b/server/sonar-web/src/main/js/apps/code/components/ComponentMeasure.js index e455acf4c4d..7ad6e2067c1 100644 --- a/server/sonar-web/src/main/js/apps/code/components/ComponentMeasure.js +++ b/server/sonar-web/src/main/js/apps/code/components/ComponentMeasure.js @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import Measure from '../../component-measures/components/Measure'; +import Measure from '../../component-measures-old/components/Measure'; const ComponentMeasure = ({ component, metricKey, metricType }) => { const isProject = component.qualifier === 'TRK'; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/app/App.js b/server/sonar-web/src/main/js/apps/component-measures-old/app/App.js new file mode 100644 index 00000000000..fd7caef81a8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/app/App.js @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Helmet from 'react-helmet'; +import Spinner from './../components/Spinner'; +import { translate } from '../../../helpers/l10n'; +import '../styles.css'; + +export default class App extends React.PureComponent { + state = { componentSet: false }; + + componentDidMount() { + this.props.setComponent(this.props.component); + this.props.fetchMetrics(); + this.setState({ componentSet: true }); + } + + render() { + if (this.props.metrics == null || !this.state.componentSet) { + return ; + } + + return ( +
    + + {this.props.children} +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/app/AppContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/app/AppContainer.js new file mode 100644 index 00000000000..dca2e1eb935 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/app/AppContainer.js @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import App from './App'; +import { fetchMetrics, setComponent } from './actions'; +import { getComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer'; + +const mapStateToProps = (state, ownProps) => ({ + component: getComponent(state, ownProps.location.query.id), + metrics: getMeasuresAppAllMetrics(state) +}); + +const mapDispatchToProps = dispatch => { + return { + fetchMetrics: () => dispatch(fetchMetrics()), + setComponent: component => dispatch(setComponent(component)) + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(App); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/app/actions.js b/server/sonar-web/src/main/js/apps/component-measures-old/app/actions.js new file mode 100644 index 00000000000..7cfb8acbe6f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/app/actions.js @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { getMetrics } from '../../../api/metrics'; + +/* + * Actions + */ + +export const DISPLAY_HOME = 'measuresApp/app/DISPLAY_HOME'; +export const RECEIVE_METRICS = 'measuresApp/app/RECEIVE_METRICS'; +export const SET_COMPONENT = 'measuresApp/app/SET_COMPONENT'; + +/* + * Action Creators + */ + +export function displayHome() { + return { type: DISPLAY_HOME }; +} + +function receiveMetrics(metrics) { + return { type: RECEIVE_METRICS, metrics }; +} + +export function setComponent(component) { + return { type: SET_COMPONENT, component }; +} + +/* + * Workflow + */ + +export function fetchMetrics() { + return dispatch => { + getMetrics().then(metrics => { + dispatch(receiveMetrics(metrics)); + }); + }; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/app/reducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/app/reducer.js new file mode 100644 index 00000000000..165b79c524b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/app/reducer.js @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { RECEIVE_METRICS, SET_COMPONENT } from './actions'; + +const initialState = { + metrics: undefined +}; + +export default function appReducer(state = initialState, action = {}) { + switch (action.type) { + case RECEIVE_METRICS: + return { ...state, metrics: action.metrics }; + case SET_COMPONENT: + return { ...state, component: action.component }; + default: + return state; + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/IconBubbles.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconBubbles.js new file mode 100644 index 00000000000..130adcc0c15 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconBubbles.js @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 IconBubbles() { + /* eslint max-len: 0 */ + return ( + + + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/IconList.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconList.js new file mode 100644 index 00000000000..df6d69e7f3b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconList.js @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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-old/components/IconTree.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconTree.js new file mode 100644 index 00000000000..9270286f6a8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconTree.js @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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-old/components/IconTreemap.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconTreemap.js new file mode 100644 index 00000000000..aef8aabc7ff --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/IconTreemap.js @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 IconTreemap() { + return ( + + + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/LeakPeriodLegend.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/LeakPeriodLegend.js new file mode 100644 index 00000000000..22483f15b54 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/LeakPeriodLegend.js @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 moment from 'moment'; +import Tooltip from '../../../components/controls/Tooltip'; +import { getPeriodLabel, getPeriodDate } from '../../../helpers/periods'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +export default function LeakPeriodLegend({ component, period }) { + if (component.qualifier === 'APP') { + return ( +
    + {translate('issues.leak_period')} +
    + ); + } + + const label = ( +
    + {translateWithParameters('overview.leak_period_x', getPeriodLabel(period))} +
    + ); + + if (period.mode === 'days') { + return label; + } + + const date = getPeriodDate(period); + const fromNow = moment(date).fromNow(); + const tooltip = fromNow + ', ' + moment(date).format('LL'); + return ( + + {label} + + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/Measure.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/Measure.js new file mode 100644 index 00000000000..ba59123b3b7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/Measure.js @@ -0,0 +1,77 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 PropTypes from 'prop-types'; +import Rating from '../../../components/ui/Rating'; +import Level from '../../../components/ui/Level'; +import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; +import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; +import { formatLeak, getRatingTooltip } from '../utils'; + +export default class Measure extends React.PureComponent { + static propTypes = { + className: PropTypes.string, + measure: PropTypes.object, + metric: PropTypes.object, + decimals: PropTypes.number + }; + + renderRating(measure, metric) { + const value = isDiffMetric(metric.key) ? measure.leak : measure.value; + const tooltip = getRatingTooltip(metric.key, value); + const rating = ; + + if (tooltip) { + return ( + + + + {rating} + + + + ); + } + + return rating; + } + + render() { + const { measure, metric, decimals, className } = this.props; + const finalMetric = metric || measure.metric; + + if (finalMetric.type === 'RATING') { + return this.renderRating(measure, finalMetric); + } + + if (finalMetric.type === 'LEVEL') { + return ; + } + + const formattedValue = isDiffMetric(finalMetric.key) + ? formatLeak(measure.leak, finalMetric, { decimals }) + : formatMeasure(measure.value, finalMetric.type, { decimals }); + return ( + + {formattedValue != null ? formattedValue : '–'} + + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/Spinner.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/Spinner.js new file mode 100644 index 00000000000..3f899ac3b4f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/Spinner.js @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Spinner() { + return ; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/bubbleChart/BubbleChart.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/bubbleChart/BubbleChart.js new file mode 100644 index 00000000000..4729500df36 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/bubbleChart/BubbleChart.js @@ -0,0 +1,190 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 OriginalBubbleChart from '../../../../components/charts/BubbleChart'; +import bubbles from '../../config/bubbles'; +import { getComponentLeaves } from '../../../../api/components'; +import { formatMeasure } from '../../../../helpers/measures'; +import Workspace from '../../../../components/workspace/main'; +import { getComponentUrl } from '../../../../helpers/urls'; +import { getLocalizedMetricName, translateWithParameters } from '../../../../helpers/l10n'; + +const HEIGHT = 500; +const BUBBLES_LIMIT = 500; + +function getMeasure(component, metric) { + return Number(component.measures[metric]) || 0; +} + +export default class BubbleChart extends React.PureComponent { + state = { + fetching: 0, + files: [] + }; + + componentWillMount() { + this.updateMetrics(this.props); + } + + componentDidMount() { + this.mounted = true; + this.fetchFiles(); + } + + componentWillUpdate(nextProps) { + this.updateMetrics(nextProps); + } + + componentDidUpdate(nextProps) { + if (nextProps.domainName !== this.props.domainName) { + this.fetchFiles(); + } + } + + componentWillUnmount() { + this.mounted = false; + } + + updateMetrics(props) { + const { metrics, domainName } = props; + const conf = bubbles[domainName]; + this.xMetric = metrics.find(m => m.key === conf.x); + this.yMetric = metrics.find(m => m.key === conf.y); + this.sizeMetric = metrics.find(m => m.key === conf.size); + } + + fetchFiles() { + const { component } = this.props; + const metrics = [this.xMetric.key, this.yMetric.key, this.sizeMetric.key]; + const options = { + s: 'metric', + metricSort: this.sizeMetric.key, + asc: false, + ps: BUBBLES_LIMIT + }; + + if (this.mounted) { + this.setState({ fetching: this.state.fetching + 1 }); + } + + getComponentLeaves(component.key, metrics, options).then(r => { + const files = r.components.map(file => { + const measures = {}; + + file.measures.forEach(measure => { + measures[measure.metric] = measure.value; + }); + return { ...file, measures }; + }); + + if (this.mounted) { + this.setState({ + files, + fetching: this.state.fetching - 1, + total: files.length + }); + } + }); + } + + getTooltip(component) { + const x = formatMeasure(getMeasure(component, this.xMetric.key), this.xMetric.type); + const y = formatMeasure(getMeasure(component, this.yMetric.key), this.yMetric.type); + const size = formatMeasure(getMeasure(component, this.sizeMetric.key), this.sizeMetric.type); + const inner = [ + component.name, + `${this.xMetric.name}: ${x}`, + `${this.yMetric.name}: ${y}`, + `${this.sizeMetric.name}: ${size}` + ].join('
    '); + + return `
    ${inner}
    `; + } + + handleBubbleClick(component) { + if (['FIL', 'UTS'].includes(component.qualifier)) { + Workspace.openComponent({ key: component.key }); + } else { + window.location = getComponentUrl(component.refKey || component.key); + } + } + + renderBubbleChart() { + const items = this.state.files.map(file => { + return { + x: getMeasure(file, this.xMetric.key), + y: getMeasure(file, this.yMetric.key), + size: getMeasure(file, this.sizeMetric.key), + link: file, + tooltip: this.getTooltip(file) + }; + }); + + const formatXTick = tick => formatMeasure(tick, this.xMetric.type); + const formatYTick = tick => formatMeasure(tick, this.yMetric.type); + + return ( + + ); + } + + render() { + const { fetching } = this.state; + + if (fetching) { + return ( +
    +
    + +
    +
    + ); + } + + return ( +
    +
    + {this.renderBubbleChart()} +
    + +
    + {getLocalizedMetricName(this.xMetric)} +
    +
    + {getLocalizedMetricName(this.yMetric)} +
    +
    + {translateWithParameters( + 'component_measures.legend.size_x', + getLocalizedMetricName(this.sizeMetric) + )} +
    +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/components/bubbleChart/MeasureBubbleChartContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/components/bubbleChart/MeasureBubbleChartContainer.js new file mode 100644 index 00000000000..bc9741bed87 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/components/bubbleChart/MeasureBubbleChartContainer.js @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import MeasureBubbleChart from './BubbleChart'; +import { getMeasuresAppAllMetrics, getMeasuresAppComponent } from '../../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + component: getMeasuresAppComponent(state), + metrics: getMeasuresAppAllMetrics(state) + }; +}; + +const mapDispatchToProps = () => { + return {}; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(MeasureBubbleChart); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/config/bubbles.js b/server/sonar-web/src/main/js/apps/component-measures-old/config/bubbles.js new file mode 100644 index 00000000000..28407f56dc5 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/config/bubbles.js @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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. + */ +const bubblesConfig = { + Reliability: { x: 'ncloc', y: 'reliability_remediation_effort', size: 'bugs' }, + Security: { x: 'ncloc', y: 'security_remediation_effort', size: 'vulnerabilities' }, + Maintainability: { x: 'ncloc', y: 'sqale_index', size: 'code_smells' }, + Coverage: { x: 'complexity', y: 'coverage', size: 'uncovered_lines' }, + Duplications: { x: 'ncloc', y: 'duplicated_lines', size: 'duplicated_blocks' } +}; + +export default bubblesConfig; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/config/complementary.js b/server/sonar-web/src/main/js/apps/component-measures-old/config/complementary.js new file mode 100644 index 00000000000..46340a2cd23 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/config/complementary.js @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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. + */ +export default { + coverage: ['uncovered_lines', 'uncovered_conditions'], + line_coverage: ['uncovered_lines'], + branch_coverage: ['uncovered_conditions'], + uncovered_lines: ['line_coverage'], + uncovered_conditions: ['branch_coverage'], + + new_coverage: ['new_uncovered_lines', 'new_uncovered_conditions'], + new_line_coverage: ['new_uncovered_lines'], + new_branch_coverage: ['new_uncovered_conditions'], + new_uncovered_lines: ['new_line_coverage'], + new_uncovered_conditions: ['new_branch_coverage'], + + duplicated_lines_density: ['duplicated_lines'], + new_duplicated_lines_density: ['new_duplicated_lines'], + duplicated_lines: ['duplicated_lines_density'], + new_duplicated_lines: ['new_duplicated_lines_density'] +}; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/config/domains.js b/server/sonar-web/src/main/js/apps/component-measures-old/config/domains.js new file mode 100644 index 00000000000..6ac6a6975c2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/config/domains.js @@ -0,0 +1,142 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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. + */ +export const domains = { + Reliability: { + main: ['bugs', 'new_bugs', 'reliability_rating'], + order: [ + 'bugs', + 'new_bugs', + 'reliability_rating', + 'reliability_remediation_effort', + 'new_reliability_remediation_effort' + ] + }, + + Security: { + main: ['vulnerabilities', 'new_vulnerabilities', 'security_rating'], + order: [ + 'vulnerabilities', + 'new_vulnerabilities', + 'security_rating', + 'security_remediation_effort', + 'new_security_remediation_effort' + ] + }, + + Maintainability: { + main: ['code_smells', 'new_code_smells', 'sqale_rating'], + order: [ + 'code_smells', + 'new_code_smells', + 'sqale_rating', + 'sqale_index', + 'new_technical_debt', + 'sqale_debt_ratio', + 'new_sqale_debt_ratio', + 'effort_to_reach_maintainability_rating_a' + ] + }, + + Coverage: { + main: ['coverage', 'new_coverage', 'tests'], + order: [ + 'coverage', + 'new_coverage', + 'line_coverage', + 'new_line_coverage', + 'branch_coverage', + 'new_branch_coverage', + 'uncovered_lines', + 'new_uncovered_lines', + 'uncovered_conditions', + 'new_uncovered_conditions', + 'new_lines_to_cover', + + 'lines_to_cover', + + 'tests', + 'test_success', + 'test_errors', + 'test_failures', + 'skipped_tests', + 'test_success_density', + 'test_execution_time' + ] + }, + + Duplications: { + main: ['duplicated_lines_density', 'new_duplicated_lines_density'], + order: [ + 'duplicated_lines_density', + 'new_duplicated_lines_density', + 'duplicated_blocks', + 'new_duplicated_blocks', + 'duplicated_lines', + 'new_duplicated_lines', + 'duplicated_files' + ] + }, + + Size: { + main: ['ncloc'], + order: [ + 'ncloc', + 'lines', + 'new_lines', + 'statements', + 'functions', + 'classes', + 'files', + 'directories' + ] + }, + + Complexity: { + main: ['complexity'], + order: ['complexity', 'function_complexity', 'file_complexity', 'class_complexity'] + }, + + Releasability: { + main: ['alert_status', 'releasability_rating'], + order: ['alert_status'] + }, + + Issues: { + main: ['violations', 'new_violations'], + order: [ + 'violations', + 'new_violations', + 'blocker_violations', + 'new_blocker_violations', + 'critical_violations', + 'new_critical_violations', + 'major_violations', + 'new_major_violations', + 'minor_violations', + 'new_minor_violations', + 'info_violations', + 'new_info_violations', + 'open_issues', + 'reopened_issues', + 'confirmed_issues', + 'false_positive_issues' + ] + } +}; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetails.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetails.js new file mode 100644 index 00000000000..8188f3f9c8a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetails.js @@ -0,0 +1,132 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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, IndexLink } from 'react-router'; +import Spinner from './../components/Spinner'; +import MeasureDetailsHeader from './MeasureDetailsHeader'; +import MeasureDrilldown from './drilldown/MeasureDrilldown'; +import MetricNotFound from './MetricNotFound'; +import { getPeriod, getPeriodDate } from '../../../helpers/periods'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +export default class MeasureDetails extends React.PureComponent { + mounted: boolean; + + state = { + loading: true + }; + + componentDidMount() { + this.mounted = true; + this.loadData(); + } + + componentDidUpdate(prevProps) { + if (prevProps.params.metricKey !== this.props.params.metricKey) { + this.loadData(); + } + } + + componentWillUnmount() { + this.mounted = false; + } + + metricExists(): boolean { + const { metrics } = this.props; + const { metricKey } = this.props.params; + const metric = metrics.find(metric => metric.key === metricKey); + return !!metric; + } + + loadData() { + if (this.metricExists()) { + this.setState({ loading: true }); + const periodIndex = this.props.location.query.period || 1; + const onLoaded = () => this.mounted && this.setState({ loading: false }); + this.props + .fetchMeasure(this.props.params.metricKey, Number(periodIndex)) + .then(onLoaded, onLoaded); + } + } + + render() { + if (!this.metricExists()) { + return ; + } + + if (this.state.loading) { + return ; + } + + const { component, metric, secondaryMeasure, measure, periods, children } = this.props; + + if (!measure) { + return ; + } + + const { tab } = this.props.params; + const periodIndex = this.props.location.query.period || 1; + const period = getPeriod(periods, Number(periodIndex)); + const periodDate = getPeriodDate(period); + + return ( +
    +
    + + {translate('component_measures.all_measures')} + + {!!metric.domain && + + {' / '} + + {translateWithParameters('component_measures.domain_measures', metric.domain)} + + } +
    + + + + {measure && + + {children} + } +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetailsContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetailsContainer.js new file mode 100644 index 00000000000..7ae39057181 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetailsContainer.js @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import MeasureDetails from './MeasureDetails'; +import { fetchMeasure } from './actions'; +import { + getMeasuresAppAllMetrics, + getMeasuresAppDetailsMetric, + getMeasuresAppDetailsMeasure, + getMeasuresAppDetailsSecondaryMeasure, + getMeasuresAppDetailsPeriods, + getMeasuresAppComponent +} from '../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + component: getMeasuresAppComponent(state), + metrics: getMeasuresAppAllMetrics(state), + metric: getMeasuresAppDetailsMetric(state), + measure: getMeasuresAppDetailsMeasure(state), + secondaryMeasure: getMeasuresAppDetailsSecondaryMeasure(state), + periods: getMeasuresAppDetailsPeriods(state) + }; +}; + +const mapDispatchToProps = { fetchMeasure }; + +export default connect(mapStateToProps, mapDispatchToProps)(MeasureDetails); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetailsHeader.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetailsHeader.js new file mode 100644 index 00000000000..f2281c24eba --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/MeasureDetailsHeader.js @@ -0,0 +1,93 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Measure from './../components/Measure'; +import LanguageDistribution from '../../../components/charts/LanguageDistribution'; +import LeakPeriodLegend from '../components/LeakPeriodLegend'; +import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; +import HistoryIcon from '../../../components/icons-components/HistoryIcon'; +import Tooltip from '../../../components/controls/Tooltip'; +import { ComplexityDistribution } from '../../../components/shared/complexity-distribution'; +import { isDiffMetric } from '../../../helpers/measures'; +import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; +import { getComponentMeasureHistory } from '../../../helpers/urls'; +import { getLocalizedMetricName, translate } from '../../../helpers/l10n'; + +export default function MeasureDetailsHeader({ + component, + measure, + metric, + secondaryMeasure, + leakPeriod +}) { + const isDiff = isDiffMetric(metric.key); + return ( +
    +

    + + {getLocalizedMetricName(metric)} + {!isDiff && + + + + + } +

    + + {isDiff && +
    + +
    } + + +
    + {isDiff + ?
    + +
    + :
    + +
    } + + {secondaryMeasure && + secondaryMeasure.metric === 'ncloc_language_distribution' && +
    + +
    } + + {secondaryMeasure && + secondaryMeasure.metric === 'function_complexity_distribution' && +
    + +
    } + + {secondaryMeasure && + secondaryMeasure.metric === 'file_complexity_distribution' && +
    + +
    } +
    +
    +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/MetricNotFound.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/MetricNotFound.js new file mode 100644 index 00000000000..57b5fee5844 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/MetricNotFound.js @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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. + */ +// @flow +import React from 'react'; +import { translate } from '../../../helpers/l10n'; + +export default function MetricNotFound() { + return ( +
    +
    + {translate('component_measures.not_found')} +
    +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/actions.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/actions.js new file mode 100644 index 00000000000..55579349c01 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/actions.js @@ -0,0 +1,76 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { getMeasuresAndMeta } from '../../../api/measures'; +import { enhanceWithLeak } from '../utils'; +import { getMeasuresAppComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer'; + +/* + * Actions + */ + +export const REQUEST_MEASURE = 'measuresApp/details/REQUEST_MEASURE'; +export const RECEIVE_MEASURE = 'measuresApp/details/RECEIVE_MEASURE'; + +/* + * Action Creators + */ + +function requestMeasure(metric) { + return { type: REQUEST_MEASURE, metric }; +} + +function receiveMeasure(measure, secondaryMeasure, periods) { + return { type: RECEIVE_MEASURE, measure, secondaryMeasure, periods }; +} + +/* + * Workflow + */ + +export function fetchMeasure(metricKey, periodIndex = 1) { + return (dispatch, getState) => { + const state = getState(); + const component = getMeasuresAppComponent(state); + const metrics = getMeasuresAppAllMetrics(state); + const metricsToRequest = [metricKey]; + + if (metricKey === 'ncloc') { + metricsToRequest.push('ncloc_language_distribution'); + } + if (metricKey === 'function_complexity') { + metricsToRequest.push('function_complexity_distribution'); + } + if (metricKey === 'file_complexity') { + metricsToRequest.push('file_complexity_distribution'); + } + + const metric = metrics.find(m => m.key === metricKey); + dispatch(requestMeasure(metric)); + + return getMeasuresAndMeta(component.key, metricsToRequest, { + additionalFields: 'periods' + }).then(r => { + const measures = enhanceWithLeak(r.component.measures, periodIndex); + const measure = measures.find(m => m.metric === metricKey); + const secondaryMeasure = measures.find(m => m.metric !== metricKey); + dispatch(receiveMeasure(measure, secondaryMeasure, r.periods)); + }); + }; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/Breadcrumb.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/Breadcrumb.js new file mode 100644 index 00000000000..aa038d9d004 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/Breadcrumb.js @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 QualifierIcon from '../../../../components/shared/QualifierIcon'; +import { formatLeak } from '../../utils'; +import { formatMeasure, isDiffMetric } from '../../../../helpers/measures'; + +const Breadcrumb = ({ component, metric, onBrowse }) => { + const handleClick = e => { + e.preventDefault(); + e.target.blur(); + onBrowse(component); + }; + + let inner; + if (onBrowse) { + inner = ( + + {component.name} + + ); + } else { + inner = ( + + {component.name} + + ); + } + + const value = isDiffMetric(metric.key) + ? formatLeak(component.leak, metric) + : formatMeasure(component.value, metric.type); + + return ( + + +   + {inner} + {value != null && + + {' (' + value + ')'} + } + + ); +}; + +export default Breadcrumb; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/Breadcrumbs.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/Breadcrumbs.js new file mode 100644 index 00000000000..227fad25782 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/Breadcrumbs.js @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Breadcrumb from './Breadcrumb'; + +const Breadcrumbs = ({ breadcrumbs, metric, onBrowse }) => +
      + {breadcrumbs.map((component, index) => +
    • + +
    • + )} +
    ; + +export default Breadcrumbs; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentCell.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentCell.js new file mode 100644 index 00000000000..6d9ae770a8a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentCell.js @@ -0,0 +1,94 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 classNames from 'classnames'; +import QualifierIcon from '../../../../components/shared/QualifierIcon'; +import { splitPath } from '../../../../helpers/path'; +import { getComponentUrl } from '../../../../helpers/urls'; + +const ComponentCell = ({ component, isSelected, onClick }) => { + const linkClassName = classNames('link-no-underline', { + selected: isSelected + }); + + const handleClick = e => { + const isLeftClickEvent = e.button === 0; + const isModifiedEvent = !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey); + + if (isLeftClickEvent && !isModifiedEvent) { + e.preventDefault(); + onClick(); + } + }; + + let head = ''; + let tail = component.name; + + if (['DIR', 'FIL', 'UTS'].includes(component.qualifier)) { + const parts = splitPath(component.path); + head = parts.head; + tail = parts.tail; + } + + const inner = ( + + +   + {head.length > 0 && + + {head}/ + } + {tail} + + ); + + return ( + +
    + {component.refId == null || component.qualifier === 'DEV_PRJ' + ? + {inner} + + : + + + + + {inner} + } +
    + + ); +}; + +export default ComponentCell; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentsList.js new file mode 100644 index 00000000000..0faf5f66dfb --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentsList.js @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 ComponentsListRow from './ComponentsListRow'; +import EmptyComponentsList from './EmptyComponentsList'; +import complementary from '../../config/complementary'; +import { getLocalizedMetricName } from '../../../../helpers/l10n'; + +const ComponentsList = ({ components, metrics, selected, metric, onClick }) => { + if (!components.length) { + return ; + } + + const otherMetrics = (complementary[metric.key] || []).map(metric => { + return metrics.find(m => m.key === metric); + }); + + return ( + + {otherMetrics.length > 0 && + + + + + {otherMetrics.map(metric => + + )} + + } + + + {components.map(component => + + )} + +
      + + {getLocalizedMetricName(metric)} + + + + {getLocalizedMetricName(metric)} + +
    + ); +}; + +export default ComponentsList; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentsListRow.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentsListRow.js new file mode 100644 index 00000000000..8e01925a987 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ComponentsListRow.js @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 ComponentCell from './ComponentCell'; +import MeasureCell from './MeasureCell'; + +const replaceMeasure = (component, measure) => { + return { + ...component, + value: measure.value, + leak: measure.leak + }; +}; + +const ComponentsListRow = ({ component, otherMetrics, isSelected, metric, onClick }) => { + const handleClick = () => { + onClick(component); + }; + + const otherMeasures = otherMetrics.map(metric => { + const measure = component.measures.find(measure => measure.metric === metric.key); + return { ...measure, metric }; + }); + + return ( + + + + + + {otherMeasures.map(measure => + + )} + + ); +}; + +export default ComponentsListRow; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/EmptyComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/EmptyComponentsList.js new file mode 100644 index 00000000000..be032c05ce0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/EmptyComponentsList.js @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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'; + +const EmptyComponentsList = () => { + return ( +
    + {translate('no_results')} +
    + ); +}; + +export default EmptyComponentsList; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListHeader.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListHeader.js new file mode 100644 index 00000000000..b929bac5d9a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListHeader.js @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Breadcrumbs from './Breadcrumbs'; +import { translateWithParameters } from '../../../../helpers/l10n'; + +const ListHeader = props => { + const { metric, breadcrumbs, onBrowse } = props; + const { selectedIndex, componentsCount, onSelectPrevious, onSelectNext } = props; + const hasPrevious = selectedIndex > 0; + const hasNext = selectedIndex < componentsCount - 1; + const blur = fn => { + return e => { + e.target.blur(); + fn(); + }; + }; + + return ( +
    + {breadcrumbs != null && + breadcrumbs.length > 1 && +
    + +
    } + + {selectedIndex != null && + selectedIndex !== -1 && +
    + + {translateWithParameters( + 'component_measures.x_of_y', + selectedIndex + 1, + componentsCount + )} + + +
    + {hasPrevious && } + {hasNext && } +
    +
    } +
    + ); +}; + +export default ListHeader; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListView.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListView.js new file mode 100644 index 00000000000..88d28d8f5f9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListView.js @@ -0,0 +1,172 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 PropTypes from 'prop-types'; +import classNames from 'classnames'; +import moment from 'moment'; +import ComponentsList from './ComponentsList'; +import ListHeader from './ListHeader'; +import Spinner from '../../components/Spinner'; +import SourceViewer from '../../../../components/SourceViewer/SourceViewer'; +import ListFooter from '../../../../components/controls/ListFooter'; + +export default class ListView extends React.PureComponent { + static contextTypes = { + router: PropTypes.object.isRequired + }; + + componentDidMount() { + const { component, metric } = this.props; + if (component.qualifier === 'DEV') { + const { router } = this.context; + router.replace({ pathname: `metric/${metric.key}/tree`, query: { id: component.key } }); + } + this.handleChangeBaseComponent(component); + } + + componentDidUpdate(nextProps) { + if (nextProps.metric !== this.props.metric) { + this.handleChangeBaseComponent(this.props.component); + } + + if (this.props.selected) { + this.scrollToViewer(); + } else if (this.scrollTop) { + this.scrollToStoredPosition(); + } + } + + scrollToViewer() { + const { container } = this.refs; + const top = container.getBoundingClientRect().top + window.scrollY - 95 - 10; + + // scroll only to top + if (window.scrollY > top) { + window.scrollTo(0, top); + } + } + + scrollToStoredPosition() { + window.scrollTo(0, this.scrollTop); + this.scrollTop = null; + } + + storeScrollPosition() { + this.scrollTop = window.scrollY; + } + + handleChangeBaseComponent(baseComponent) { + const { metric, onFetchList } = this.props; + const periodIndex = this.props.location.query.period || 1; + onFetchList(baseComponent, metric, Number(periodIndex)); + } + + handleFetchMore() { + const periodIndex = this.props.location.query.period || 1; + this.props.onFetchMore(Number(periodIndex)); + } + + changeSelected(selected) { + this.props.onSelect(selected); + } + + handleClick(selected) { + this.storeScrollPosition(); + this.props.onSelect(selected); + } + + handleBreadcrumbClick() { + this.props.onSelect(undefined); + } + + render() { + const { + component, + components, + metrics, + metric, + leakPeriod, + selected, + total, + fetching + } = this.props; + const { onSelectNext, onSelectPrevious } = this.props; + + const breadcrumbs = [component]; + if (selected) { + breadcrumbs.push(selected); + } + const selectedIndex = components.indexOf(selected); + const sourceViewerPeriod = metric.key.indexOf('new_') === 0 && !!leakPeriod ? leakPeriod : null; + const sourceViewerPeriodDate = + sourceViewerPeriod != null ? moment(sourceViewerPeriod.date).toDate() : null; + + const filterLine = + sourceViewerPeriodDate != null + ? line => { + if (line.scmDate) { + const scmDate = moment(line.scmDate).toDate(); + return scmDate >= sourceViewerPeriodDate; + } else { + return false; + } + } + : undefined; + + return ( +
    + + + {!selected && +
    + {!fetching || components.length !== 0 + ?
    + + +
    + : } +
    } + + {!!selected && +
    + +
    } +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListViewContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListViewContainer.js new file mode 100644 index 00000000000..bf6b3fc106a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/ListViewContainer.js @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import ListView from './ListView'; +import { + fetchList, + fetchMore, + selectComponent, + selectNext, + selectPrevious +} from '../../store/listViewActions'; +import { + getMeasuresAppListComponents, + getMeasuresAppListSelected, + getMeasuresAppListTotal, + getMeasuresAppListPageIndex, + getMeasuresAppAllMetrics, + getMeasuresAppDetailsMetric, + isMeasuresAppFetching, + getMeasuresAppComponent +} from '../../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + components: getMeasuresAppListComponents(state), + selected: getMeasuresAppListSelected(state), + total: getMeasuresAppListTotal(state), + pageIndex: getMeasuresAppListPageIndex(state), + component: getMeasuresAppComponent(state), + metrics: getMeasuresAppAllMetrics(state), + metric: getMeasuresAppDetailsMetric(state), + fetching: isMeasuresAppFetching(state) + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onFetchList: (baseComponent, metric, periodIndex) => + dispatch(fetchList(baseComponent, metric, periodIndex)), + onFetchMore: periodIndex => dispatch(fetchMore(periodIndex)), + onSelect: component => dispatch(selectComponent(component)), + onSelectNext: component => dispatch(selectNext(component)), + onSelectPrevious: component => dispatch(selectPrevious(component)) + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(ListView); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/MeasureCell.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/MeasureCell.js new file mode 100644 index 00000000000..ee236adbb74 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/MeasureCell.js @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Measure from '../../components/Measure'; + +const MeasureCell = ({ component, metric }) => { + return ( + + + + + + ); +}; + +export default MeasureCell; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/MeasureDrilldown.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/MeasureDrilldown.js new file mode 100644 index 00000000000..ad956bda6d9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/MeasureDrilldown.js @@ -0,0 +1,92 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 IconList from './../../components/IconList'; +import IconTree from './../../components/IconTree'; +import IconBubbles from './../../components/IconBubbles'; +import IconTreemap from './../../components/IconTreemap'; +import { hasBubbleChart, hasTreemap } from '../../utils'; +import { translate } from '../../../../helpers/l10n'; + +export default function MeasureDrilldown(props) { + const { children, component, metric, ...other } = props; + + const child = React.cloneElement(children, { ...other }); + + return ( +
    +
      + {component.qualifier !== 'DEV' && +
    • + + + {translate('component_measures.tab.list')} + +
    • } + +
    • + + + {translate('component_measures.tab.tree')} + +
    • + + {hasBubbleChart(metric.key) && +
    • + + + {translate('component_measures.tab.bubbles')} + +
    • } + + {hasTreemap(metric) && +
    • + + + {translate('component_measures.tab.treemap')} + +
    • } +
    + + {child} +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/TreeView.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/TreeView.js new file mode 100644 index 00000000000..0bbfe14681e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/TreeView.js @@ -0,0 +1,164 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 moment from 'moment'; +import ComponentsList from './ComponentsList'; +import ListHeader from './ListHeader'; +import Spinner from '../../components/Spinner'; +import SourceViewer from '../../../../components/SourceViewer/SourceViewer'; +import ListFooter from '../../../../components/controls/ListFooter'; + +export default class TreeView extends React.PureComponent { + componentDidMount() { + this.handleChangeBaseComponent(this.props.component); + } + + componentDidUpdate(nextProps) { + if (nextProps.metric !== this.props.metric) { + this.handleChangeBaseComponent(this.props.component); + } + + if (this.props.selected) { + this.scrollToViewer(); + } else if (this.scrollTop) { + this.scrollToStoredPosition(); + } + } + + scrollToViewer() { + const { container } = this.refs; + const top = container.getBoundingClientRect().top + window.scrollY - 95 - 10; + + // scroll only to top + if (window.scrollY > top) { + window.scrollTo(0, top); + } + } + + scrollToStoredPosition() { + window.scrollTo(0, this.scrollTop); + this.scrollTop = null; + } + + storeScrollPosition() { + this.scrollTop = window.scrollY; + } + + handleChangeBaseComponent(baseComponent) { + const { metric, onStart } = this.props; + const periodIndex = this.props.location.query.period || 1; + onStart(baseComponent, metric, Number(periodIndex)); + } + + handleFetchMore() { + this.props.onFetchMore(); + } + + changeSelected(selected) { + this.props.onSelect(selected); + } + + canDrilldown(component) { + return !['FIL', 'UTS'].includes(component.qualifier); + } + + handleClick(selected) { + if (this.canDrilldown(selected)) { + this.props.onDrilldown(selected); + } else { + this.storeScrollPosition(); + this.props.onSelect(selected); + } + } + + handleBreadcrumbClick(component) { + this.props.onUseBreadcrumbs(component, this.props.metric); + } + + render() { + const { + components, + metrics, + breadcrumbs, + metric, + leakPeriod, + selected, + total, + fetching + } = this.props; + const { onSelectNext, onSelectPrevious } = this.props; + + const selectedIndex = components.indexOf(selected); + const sourceViewerPeriod = metric.key.indexOf('new_') === 0 && !!leakPeriod ? leakPeriod : null; + const sourceViewerPeriodDate = + sourceViewerPeriod != null ? moment(sourceViewerPeriod.date).toDate() : null; + + const filterLine = + sourceViewerPeriodDate != null + ? line => { + if (line.scmDate) { + const scmDate = moment(line.scmDate).toDate(); + return scmDate >= sourceViewerPeriodDate; + } else { + return false; + } + } + : undefined; + + return ( +
    + + + {!selected && +
    + {!fetching || components.length !== 0 + ?
    + + +
    + : } +
    } + + {!!selected && +
    + +
    } +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/TreeViewContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/TreeViewContainer.js new file mode 100644 index 00000000000..a7ae418251f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/drilldown/TreeViewContainer.js @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import TreeView from './TreeView'; +import { + start, + drilldown, + useBreadcrumbs, + fetchMore, + selectComponent, + selectNext, + selectPrevious +} from '../../store/treeViewActions'; +import { + getMeasuresAppTreeComponents, + getMeasuresAppTreeBreadcrumbs, + getMeasuresAppTreeSelected, + getMeasuresAppTreeTotal, + getMeasuresAppTreePageIndex, + getMeasuresAppAllMetrics, + getMeasuresAppDetailsMetric, + isMeasuresAppFetching, + getMeasuresAppComponent +} from '../../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + components: getMeasuresAppTreeComponents(state), + breadcrumbs: getMeasuresAppTreeBreadcrumbs(state), + selected: getMeasuresAppTreeSelected(state), + total: getMeasuresAppTreeTotal(state), + pageIndex: getMeasuresAppTreePageIndex(state), + component: getMeasuresAppComponent(state), + metrics: getMeasuresAppAllMetrics(state), + metric: getMeasuresAppDetailsMetric(state), + fetching: isMeasuresAppFetching(state) + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onStart: (rootComponent, metric, periodIndex) => + dispatch(start(rootComponent, metric, periodIndex)), + onDrilldown: component => dispatch(drilldown(component)), + onUseBreadcrumbs: component => dispatch(useBreadcrumbs(component)), + onFetchMore: () => dispatch(fetchMore()), + onSelect: component => dispatch(selectComponent(component)), + onSelectNext: component => dispatch(selectNext(component)), + onSelectPrevious: component => dispatch(selectPrevious(component)) + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(TreeView); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/reducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/reducer.js new file mode 100644 index 00000000000..ea68685093f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/reducer.js @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { DISPLAY_HOME } from '../app/actions'; +import { REQUEST_MEASURE, RECEIVE_MEASURE } from './actions'; + +const initialState = { + metric: undefined, + secondaryMeasure: undefined, + measure: undefined, + periods: undefined +}; + +export default function appReducer(state = initialState, action = {}) { + switch (action.type) { + case DISPLAY_HOME: + return initialState; + case REQUEST_MEASURE: + return { ...state, metric: action.metric }; + case RECEIVE_MEASURE: + return { + ...state, + measure: action.measure, + secondaryMeasure: action.secondaryMeasure, + periods: action.periods + }; + default: + return state; + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/treemap/MeasureTreemap.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/treemap/MeasureTreemap.js new file mode 100644 index 00000000000..2516b8d9d02 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/treemap/MeasureTreemap.js @@ -0,0 +1,223 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { scaleLinear, scaleOrdinal } from 'd3-scale'; +import Spinner from './../../components/Spinner'; +import { getLeakValue } from '../../utils'; +import { Treemap } from '../../../../components/charts/treemap'; +import { getChildren } from '../../../../api/components'; +import { formatMeasure } from '../../../../helpers/measures'; +import { + translate, + translateWithParameters, + getLocalizedMetricName +} from '../../../../helpers/l10n'; +import { getComponentUrl } from '../../../../helpers/urls'; +import Workspace from '../../../../components/workspace/main'; + +const HEIGHT = 500; + +export default class MeasureTreemap extends React.PureComponent { + state = { + fetching: true, + components: [], + breadcrumbs: [] + }; + + componentDidMount() { + const { component } = this.props; + + this.mounted = true; + this.fetchComponents(component.key); + } + + componentDidUpdate(nextProps) { + if (nextProps.metric !== this.props.metric) { + this.fetchComponents(this.props.component.key); + } + } + + componentWillUnmount() { + this.mounted = false; + } + + fetchComponents(componentKey) { + const { metric } = this.props; + const metrics = ['ncloc', metric.key]; + const options = { + s: 'metric', + metricSort: 'ncloc', + asc: false + }; + + return getChildren(componentKey, metrics, options).then(r => { + const components = r.components.map(component => { + const measures = {}; + const key = component.refKey || component.key; + + component.measures.forEach(measure => { + const shouldUseLeak = measure.metric.indexOf('new_') === 0; + measures[measure.metric] = shouldUseLeak ? getLeakValue(measure) : measure.value; + }); + return { ...component, measures, key }; + }); + + this.setState({ + components, + fetching: false + }); + }); + } + + getTooltip(component) { + const { metric } = this.props; + + let inner = [ + component.name, + `${translate('metric.ncloc.name')}: ${formatMeasure(component.measures['ncloc'], 'INT')}` + ]; + + const colorMeasure = component.measures[metric.key]; + const formatted = colorMeasure != null ? formatMeasure(colorMeasure, metric.type) : '—'; + inner.push(`${getLocalizedMetricName(metric)}: ${formatted}`); + inner = inner.join('
    '); + return `
    ${inner}
    `; + } + getPercentColorScale(metric) { + const color = scaleLinear().domain([0, 25, 50, 75, 100]); + color.range( + metric.direction === 1 + ? ['#d4333f', '#ed7d20', '#eabe06', '#b0d513', '#00aa00'] + : ['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f'] + ); + return color; + } + getRatingColorScale() { + return scaleLinear() + .domain([1, 2, 3, 4, 5]) + .range(['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f']); + } + getLevelColorScale() { + return scaleOrdinal() + .domain(['ERROR', 'WARN', 'OK', 'NONE']) + .range(['#d4333f', '#ed7d20', '#00aa00', '#b4b4b4']); + } + getScale() { + const { metric } = this.props; + if (metric.type === 'LEVEL') { + return this.getLevelColorScale(); + } + if (metric.type === 'RATING') { + return this.getRatingColorScale(); + } + return this.getPercentColorScale(metric); + } + handleRectangleClick(node) { + const isFile = node.qualifier === 'FIL' || node.qualifier === 'UTS'; + if (isFile) { + Workspace.openComponent({ key: node.key }); + return; + } + this.fetchComponents(node.key).then(() => { + let nextBreadcrumbs = [...this.state.breadcrumbs]; + const index = this.state.breadcrumbs.findIndex(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() { + const { component } = this.props; + this.fetchComponents(component.key).then(() => { + this.setState({ breadcrumbs: [] }); + }); + } + renderTreemap() { + const { metric } = this.props; + const colorScale = this.getScale(); + const items = this.state.components + .filter(component => component.measures['ncloc']) + .map(component => { + const colorMeasure = component.measures[metric.key]; + return { + id: component.id, + key: component.key, + name: component.name, + qualifier: component.qualifier, + size: component.measures['ncloc'], + color: colorMeasure != null ? colorScale(colorMeasure) : '#777', + tooltip: this.getTooltip(component), + label: component.name, + link: getComponentUrl(component.key) + }; + }); + return ( + true} + onRectangleClick={this.handleRectangleClick.bind(this)} + onReset={this.handleReset.bind(this)} + /> + ); + } + render() { + const { metric } = this.props; + const { fetching } = this.state; + if (fetching) { + return ( +
    +
    + +
    +
    + ); + } + return ( +
    +
      +
    • + {translateWithParameters( + 'component_measures.legend.color_x', + getLocalizedMetricName(metric) + )} +
    • +
    • + {translateWithParameters( + 'component_measures.legend.size_x', + translate('metric.ncloc.name') + )} +
    • +
    + {this.renderTreemap()} +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/details/treemap/MeasureTreemapContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/details/treemap/MeasureTreemapContainer.js new file mode 100644 index 00000000000..5a3e26d98d4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/details/treemap/MeasureTreemapContainer.js @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import MeasureTreemap from './MeasureTreemap'; +import { + getMeasuresAppDetailsMetric, + getMeasuresAppComponent +} from '../../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + component: getMeasuresAppComponent(state), + metric: getMeasuresAppDetailsMetric(state) + }; +}; + +const mapDispatchToProps = () => { + return {}; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(MeasureTreemap); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasures.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasures.js new file mode 100644 index 00000000000..ab69f4baab3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasures.js @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 AllMeasuresDomain from './AllMeasuresDomain'; +import { getLeakPeriodLabel } from '../../../helpers/periods'; + +export default function AllMeasures(props) { + const { component, domains, periods } = props; + const leakPeriodLabel = getLeakPeriodLabel(periods); + + return ( +
      + {domains.map(domain => + + )} +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasuresContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasuresContainer.js new file mode 100644 index 00000000000..5ec9cc79ab8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasuresContainer.js @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import AllMeasures from './AllMeasures'; +import { + getMeasuresAppHomeDomains, + getMeasuresAppHomePeriods, + getMeasuresAppComponent +} from '../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + component: getMeasuresAppComponent(state), + domains: getMeasuresAppHomeDomains(state), + periods: getMeasuresAppHomePeriods(state) + }; +}; + +export default connect(mapStateToProps)(AllMeasures); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasuresDomain.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasuresDomain.js new file mode 100644 index 00000000000..1111a362a9c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/AllMeasuresDomain.js @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 PropTypes from 'prop-types'; +import HomeMeasuresList from './HomeMeasuresList'; +import { getLocalizedMetricDomain } from '../../../helpers/l10n'; + +export default function AllMeasuresDomain(props) { + const { domain, component, displayHeader } = props; + + return ( +
  • + {displayHeader && +
    +

    + {getLocalizedMetricDomain(domain.name)} +

    +
    } + + +
  • + ); +} + +AllMeasuresDomain.defaultProps = { + displayHeader: true +}; + +AllMeasuresDomain.propTypes = { + displayHeader: PropTypes.bool +}; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/DomainMeasures.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/DomainMeasures.js new file mode 100644 index 00000000000..22343bc704e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/DomainMeasures.js @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 HomeMeasuresList from './HomeMeasuresList'; +import MeasureBubbleChartContainer from '../components/bubbleChart/MeasureBubbleChartContainer'; +import { hasBubbleChart } from '../utils'; + +export default function DomainMeasures(props) { + const { component, domains } = props; + const { domainName } = props.params; + const domain = domains.find(d => d.name === domainName); + + return ( +
    + + + {hasBubbleChart(domainName) && } +
    + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/DomainMeasuresContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/DomainMeasuresContainer.js new file mode 100644 index 00000000000..c442bfca57c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/DomainMeasuresContainer.js @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import DomainMeasures from './DomainMeasures'; +import { + getMeasuresAppHomeDomains, + getMeasuresAppHomePeriods, + getMeasuresAppComponent +} from '../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + component: getMeasuresAppComponent(state), + domains: getMeasuresAppHomeDomains(state), + periods: getMeasuresAppHomePeriods(state) + }; +}; + +export default connect(mapStateToProps)(DomainMeasures); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/Home.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/Home.js new file mode 100644 index 00000000000..43ca784ae04 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/Home.js @@ -0,0 +1,82 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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, IndexLink } from 'react-router'; +import LeakPeriodLegend from '../components/LeakPeriodLegend'; +import { getLeakPeriod } from '../../../helpers/periods'; +import { translate, getLocalizedMetricDomain } from '../../../helpers/l10n'; + +export default class Home extends React.PureComponent { + componentDidMount() { + document.querySelector('html').classList.add('dashboard-page'); + this.props.onDisplay(); + this.props.fetchMeasures(); + } + + componentWillUnmount() { + document.querySelector('html').classList.remove('dashboard-page'); + } + + render() { + const { component, domains, periods } = this.props; + + if (domains == null) { + return null; + } + + const leakPeriod = getLeakPeriod(periods); + + return ( +
    +
    + + + {leakPeriod != null && } +
    + +
    + {this.props.children} +
    +
    + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/HomeContainer.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/HomeContainer.js new file mode 100644 index 00000000000..0605a3aec58 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/HomeContainer.js @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { connect } from 'react-redux'; +import Home from './Home'; +import { fetchMeasures } from './actions'; +import { displayHome } from '../app/actions'; +import { + getMeasuresAppHomeDomains, + getMeasuresAppHomePeriods, + getMeasuresAppComponent +} from '../../../store/rootReducer'; + +const mapStateToProps = state => { + return { + component: getMeasuresAppComponent(state), + domains: getMeasuresAppHomeDomains(state), + periods: getMeasuresAppHomePeriods(state) + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onDisplay: () => dispatch(displayHome()), + fetchMeasures: () => dispatch(fetchMeasures()) + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Home); diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/HomeMeasuresList.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/HomeMeasuresList.js new file mode 100644 index 00000000000..7d700666a8f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/HomeMeasuresList.js @@ -0,0 +1,81 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { partition, sortBy } from 'lodash'; +import MeasuresList from './MeasuresList'; +import { domains } from '../config/domains'; +import { getLocalizedMetricName } from '../../../helpers/l10n'; + +function sortMeasures(measures, order) { + const [known, unknown] = partition(measures, measure => order.includes(measure.metric.key)); + return [ + ...sortBy(known, measure => order.indexOf(measure.metric.key)), + ...sortBy(unknown, measure => getLocalizedMetricName(measure.metric)) + ]; +} + +function filterIssuesMeasures(measures) { + const BANNED_MEASURES = [ + 'blocker_violations', + 'new_blocker_violations', + 'critical_violations', + 'new_critical_violations', + 'major_violations', + 'new_major_violations', + 'minor_violations', + 'new_minor_violations', + 'info_violations', + 'new_info_violations' + ]; + return measures.filter(measure => !BANNED_MEASURES.includes(measure.metric.key)); +} + +const HomeMeasuresList = ({ domain, component }) => { + const { measures, name } = domain; + const config = domains[name] || {}; + + const filteredMeasures = filterIssuesMeasures(measures); + + const configMain = config.main || []; + const [mainMeasures, otherMeasures] = partition(filteredMeasures, measure => + configMain.includes(measure.metric.key) + ); + + const configOrder = config.order || []; + const sortedMainMeasures = sortMeasures(mainMeasures, configOrder); + const sortedOtherMeasures = sortMeasures(otherMeasures, configOrder); + + return ( +
    + {sortedMainMeasures.length > 0 && + } + + {sortedOtherMeasures.length > 0 && + } +
    + ); +}; + +export default HomeMeasuresList; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/MeasureListValue.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/MeasureListValue.js new file mode 100644 index 00000000000..da121fc6995 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/MeasureListValue.js @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 Measure from '../components/Measure'; +import { isDiffMetric } from '../../../helpers/measures'; + +const MeasureListValue = ({ measure }) => { + const { metric } = measure; + + if (isDiffMetric(metric.key)) { + return ( +
    + +
    + ); + } + + return ( +
    + +
    + ); +}; + +export default MeasureListValue; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/MeasuresList.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/MeasuresList.js new file mode 100644 index 00000000000..d400cf4f292 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/MeasuresList.js @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 MeasureListValue from './MeasureListValue'; +import { getLocalizedMetricName } from '../../../helpers/l10n'; +import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; + +const MeasuresList = ({ measures, component, className = 'domain-measures' }) => { + return ( +
      + {measures.map(measure => +
    • + +
      + + + {getLocalizedMetricName(measure.metric)} + +
      + + + +
    • + )} +
    + ); +}; + +export default MeasuresList; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/actions.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/actions.js new file mode 100644 index 00000000000..6ae4585b20b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/actions.js @@ -0,0 +1,83 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { startFetching, stopFetching } from '../store/statusActions'; +import { getMeasuresAndMeta } from '../../../api/measures'; +import { getLeakValue } from '../utils'; +import { getMeasuresAppComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer'; + +export const RECEIVE_MEASURES = 'measuresApp/home/RECEIVE_MEASURES'; + +export function receiveMeasures(measures, periods) { + return { type: RECEIVE_MEASURES, measures, periods }; +} + +function banQualityGate(component, measures) { + let newMeasures = [...measures]; + + if (!['VW', 'SVW', 'APP'].includes(component.qualifier)) { + newMeasures = newMeasures.filter(measure => measure.metric !== 'alert_status'); + } + + if (component.qualifier === 'APP') { + newMeasures = newMeasures.filter( + measure => + measure.metric !== 'releasability_rating' && measure.metric !== 'releasability_effort' + ); + } + + return newMeasures; +} + +export function fetchMeasures() { + return (dispatch, getState) => { + dispatch(startFetching()); + + const state = getState(); + const component = getMeasuresAppComponent(state); + const metrics = getMeasuresAppAllMetrics(state); + + 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 => { + const measures = banQualityGate(component, r.component.measures) + .map(measure => { + const metric = metrics.find(metric => metric.key === measure.metric); + const leak = getLeakValue(measure); + return { ...measure, metric, leak }; + }) + .filter(measure => { + const hasValue = measure.value != null; + const hasLeakValue = measure.leak != null; + return hasValue || hasLeakValue; + }); + + const newBugs = measures.find(measure => measure.metric.key === 'new_bugs'); + + const applicationPeriods = newBugs ? [{ index: 1 }] : []; + const periods = component.qualifier === 'APP' ? applicationPeriods : r.periods; + + dispatch(receiveMeasures(measures, periods)); + dispatch(stopFetching()); + }); + }; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/home/reducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/home/reducer.js new file mode 100644 index 00000000000..e75222924f6 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/home/reducer.js @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { groupBy, partition, sortBy, toPairs } from 'lodash'; +import { RECEIVE_MEASURES } from './actions'; +import { getLocalizedMetricName } from '../../../helpers/l10n'; + +const initialState = { + measures: undefined, + domains: undefined, + periods: undefined +}; + +function groupByDomains(measures) { + const KNOWN_DOMAINS = [ + 'Releasability', + 'Reliability', + 'Security', + 'Maintainability', + 'Coverage', + 'Duplications', + 'Size', + 'Complexity' + ]; + + const domains = sortBy( + toPairs(groupBy(measures, measure => measure.metric.domain)).map(r => { + const [name, measures] = r; + const sortedMeasures = sortBy(measures, measure => getLocalizedMetricName(measure.metric)); + + return { name, measures: sortedMeasures }; + }), + 'name' + ); + const [knownDomains, unknownDomains] = partition(domains, domain => + KNOWN_DOMAINS.includes(domain.name) + ); + return [ + ...sortBy(knownDomains, domain => KNOWN_DOMAINS.indexOf(domain.name)), + ...sortBy(unknownDomains, domain => domain.name) + ]; +} + +export default function(state = initialState, action = {}) { + switch (action.type) { + case RECEIVE_MEASURES: + return { + ...state, + measures: action.measures, + domains: groupByDomains(action.measures), + periods: action.periods + }; + default: + return state; + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/hooks.js b/server/sonar-web/src/main/js/apps/component-measures-old/hooks.js new file mode 100644 index 00000000000..001948f1b59 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/hooks.js @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { isDiffMetric } from '../../helpers/measures'; + +export function checkHistoryExistence(nextState, replace) { + const { metricKey } = nextState.params; + + if (isDiffMetric(metricKey)) { + replace({ + pathname: metricKey, + query: nextState.location.query + }); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/routes.js b/server/sonar-web/src/main/js/apps/component-measures-old/routes.js new file mode 100644 index 00000000000..a57af5a366f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/routes.js @@ -0,0 +1,102 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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. + */ +const routes = [ + { + getComponent(_, callback) { + import('./app/AppContainer').then(i => callback(null, i.default)); + }, + childRoutes: [ + { + getComponent(_, callback) { + import('./home/HomeContainer').then(i => callback(null, i.default)); + }, + childRoutes: [ + { + getIndexRoute(_, callback) { + import('./home/AllMeasuresContainer').then(i => + callback(null, { component: i.default }) + ); + } + }, + { + path: 'domain/:domainName', + getComponent(_, callback) { + import('./home/DomainMeasuresContainer').then(i => callback(null, i.default)); + } + } + ] + }, + { + path: 'metric/:metricKey', + getComponent(_, callback) { + import('./details/MeasureDetailsContainer').then(i => callback(null, i.default)); + }, + childRoutes: [ + { + indexRoute: { + onEnter(nextState, replace) { + const { params, location } = nextState; + replace({ + pathname: `/component_measures_old/metric/${params.metricKey}/list`, + query: location.query + }); + } + } + }, + { + path: 'list', + getComponent(_, callback) { + import('./details/drilldown/ListViewContainer').then(i => callback(null, i.default)); + } + }, + { + path: 'tree', + getComponent(_, callback) { + import('./details/drilldown/TreeViewContainer').then(i => callback(null, i.default)); + } + }, + { + path: 'history', + onEnter(nextState, replace) { + replace({ + pathname: '/project/activity', + query: { + id: nextState.location.query.id, + graph: 'custom', + custom_metrics: nextState.params.metricKey + } + }); + } + }, + { + path: 'treemap', + getComponent(_, callback) { + import('./details/treemap/MeasureTreemapContainer').then(i => + callback(null, i.default) + ); + } + } + ] + } + ] + } +]; + +export default routes; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/listViewActions.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/listViewActions.js new file mode 100644 index 00000000000..2bbd93dfa28 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/listViewActions.js @@ -0,0 +1,148 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { getComponentTree } from '../../../api/components'; +import { enhanceWithMeasure } from '../utils'; +import { startFetching, stopFetching } from './statusActions'; +import complementary from '../config/complementary'; +import { getMeasuresAppList } from '../../../store/rootReducer'; + +export const UPDATE_STORE = 'measuresApp/drilldown/list/UPDATE_STORE'; + +function updateStore(state) { + return { type: UPDATE_STORE, state }; +} + +function getComplementary(metric) { + const comp = complementary[metric] || []; + return [metric, ...comp]; +} + +function makeRequest(baseComponent, metric, options, periodIndex = 1) { + const asc = metric.direction === 1; + const ps = 100; + const finalOptions = { asc, ps, metricSortFilter: 'withMeasuresOnly' }; + + if (metric.key.indexOf('new_') === 0) { + Object.assign(options, { + s: 'metricPeriod,name', + metricSort: metric.key, + metricPeriodSort: periodIndex + }); + } else { + Object.assign(options, { + s: 'metric,name', + metricSort: metric.key + }); + } + + Object.assign(finalOptions, options); + return getComponentTree('leaves', baseComponent.key, getComplementary(metric.key), finalOptions); +} + +function fetchLeaves(baseComponent, metric, pageIndex = 1, periodIndex = 1) { + const options = { p: pageIndex }; + + return makeRequest(baseComponent, metric, options, periodIndex).then(r => { + const nextComponents = enhanceWithMeasure(r.components, metric.key, periodIndex); + + return { + components: nextComponents, + pageIndex: r.paging.pageIndex, + total: r.paging.total + }; + }); +} + +/** + * Fetch the first page of components for a given base component + * @param baseComponent + * @param metric + * @param periodIndex + */ +export function fetchList(baseComponent, metric, periodIndex = 1) { + return (dispatch, getState) => { + const list = getMeasuresAppList(getState()); + if (list.baseComponent === baseComponent && list.metric === metric) { + return Promise.resolve(); + } + + dispatch(startFetching()); + return fetchLeaves(baseComponent, metric, 1, periodIndex).then(r => { + dispatch( + updateStore({ + ...r, + baseComponent, + metric + }) + ); + dispatch(stopFetching()); + }); + }; +} + +export function fetchMore(periodIndex) { + return (dispatch, getState) => { + const { baseComponent, metric, pageIndex, components } = getMeasuresAppList(getState()); + dispatch(startFetching()); + return fetchLeaves(baseComponent, metric, pageIndex + 1, periodIndex).then(r => { + const nextComponents = [...components, ...r.components]; + dispatch(updateStore({ ...r, components: nextComponents })); + dispatch(stopFetching()); + }); + }; +} + +/** + * Select specified component from the list + * @param component A component to select + */ +export function selectComponent(component) { + return dispatch => { + dispatch(updateStore({ selected: component })); + }; +} + +/** + * Select next element from the list of components + */ +export function selectNext() { + return (dispatch, getState) => { + const { components, selected } = getMeasuresAppList(getState()); + const selectedIndex = components.indexOf(selected); + if (selectedIndex < components.length - 1) { + const nextSelected = components[selectedIndex + 1]; + dispatch(selectComponent(nextSelected)); + } + }; +} + +/** + * Select previous element from the list of components + */ +export function selectPrevious() { + return (dispatch, getState) => { + const { components, selected } = getMeasuresAppList(getState()); + const selectedIndex = components.indexOf(selected); + if (selectedIndex > 0) { + const nextSelected = components[selectedIndex - 1]; + dispatch(selectComponent(nextSelected)); + } + }; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/listViewReducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/listViewReducer.js new file mode 100644 index 00000000000..ee8f9aeaef8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/listViewReducer.js @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { DISPLAY_HOME } from './../app/actions'; +import { UPDATE_STORE } from './listViewActions'; + +const initialState = { + components: [], + total: 0 +}; + +export default function drilldownReducer(state = initialState, action = {}) { + switch (action.type) { + case DISPLAY_HOME: + return initialState; + case UPDATE_STORE: + return { ...state, ...action.state }; + default: + return state; + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/rootReducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/rootReducer.js new file mode 100644 index 00000000000..079a7e45693 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/rootReducer.js @@ -0,0 +1,75 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { combineReducers } from 'redux'; +import appReducer from './../app/reducer'; +import statusReducer from './statusReducer'; +import homeReducer from '../home/reducer'; +import detailsReducer from '../details/reducer'; +import listViewReducer from './listViewReducer'; +import treeViewReducer from './treeViewReducer'; + +export default combineReducers({ + app: appReducer, + home: homeReducer, + details: detailsReducer, + list: listViewReducer, + tree: treeViewReducer, + status: statusReducer +}); + +export const getComponent = state => state.app.component; + +export const getAllMetrics = state => state.app.metrics; + +export const getDetailsMetric = state => state.details.metric; + +export const getDetailsMeasure = state => state.details.measure; + +export const getDetailsSecondaryMeasure = state => state.details.secondaryMeasure; + +export const getDetailsPeriods = state => state.details.periods; + +export const isFetching = state => state.status.fetching; + +export const getList = state => state.list; + +export const getListComponents = state => state.list.components; + +export const getListSelected = state => state.list.selected; + +export const getListTotal = state => state.list.total; + +export const getListPageIndex = state => state.list.pageIndex; + +export const getTree = state => state.tree; + +export const getTreeComponents = state => state.tree.components; + +export const getTreeBreadcrumbs = state => state.tree.breadcrumbs; + +export const getTreeSelected = state => state.tree.selected; + +export const getTreeTotal = state => state.tree.total; + +export const getTreePageIndex = state => state.tree.pageIndex; + +export const getHomeDomains = state => state.home.domains; + +export const getHomePeriods = state => state.home.periods; diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/statusActions.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/statusActions.js new file mode 100644 index 00000000000..d07feba64d7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/statusActions.js @@ -0,0 +1,29 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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. + */ +export const START_FETCHING = 'measuresApp/status/START_FETCHING'; +export const STOP_FETCHING = 'measuresApp/status/STOP_FETCHING'; + +export function startFetching() { + return { type: START_FETCHING }; +} + +export function stopFetching() { + return { type: STOP_FETCHING }; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/statusReducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/statusReducer.js new file mode 100644 index 00000000000..1a993be900a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/statusReducer.js @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { START_FETCHING, STOP_FETCHING } from './statusActions'; + +const initialState = { + fetching: false +}; + +export default function drilldownReducer(state = initialState, action = {}) { + switch (action.type) { + case START_FETCHING: + return { ...state, fetching: true }; + case STOP_FETCHING: + return { ...state, fetching: false }; + default: + return state; + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/treeViewActions.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/treeViewActions.js new file mode 100644 index 00000000000..34fffe1b8cd --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/treeViewActions.js @@ -0,0 +1,277 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { initial } from 'lodash'; +import { getComponentTree } from '../../../api/components'; +import { enhanceWithMeasure } from '../utils'; +import { startFetching, stopFetching } from './statusActions'; +import complementary from '../config/complementary'; +import { getMeasuresAppTree } from '../../../store/rootReducer'; + +/* + * Actions + */ + +export const UPDATE_STORE = 'measuresApp/drilldown/tree/UPDATE_STORE'; +export const INIT = 'measuresApp/drilldown/tree/INIT'; + +/* + * Action Creators + */ + +/** + * Internal + * Update store + * @param state + * @returns {{type: string, state: *}} + */ +function updateStore(state) { + return { type: UPDATE_STORE, state }; +} + +/** + * Init tree view drilldown for the given root component and given metric + * @param rootComponent + * @param metric + * @param periodIndex + * @returns {{type: string, rootComponent: *, metric: *}} + */ +function init(rootComponent, metric, periodIndex = 1) { + return { type: INIT, rootComponent, metric, periodIndex }; +} + +/* + * Workflow + */ + +function getComplementary(metric) { + const comp = complementary[metric] || []; + return [metric, ...comp]; +} + +function makeRequest(rootComponent, baseComponent, metric, options, periodIndex = 1) { + const asc = metric.direction === 1; + const ps = 100; + const finalOptions = { asc, ps, metricSortFilter: 'withMeasuresOnly' }; + + if (metric.key.indexOf('new_') === 0) { + Object.assign(options, { + s: 'metricPeriod,name', + metricSort: metric.key, + metricPeriodSort: periodIndex + }); + } else { + Object.assign(options, { + s: 'metric,name', + metricSort: metric.key + }); + } + + if (rootComponent.qualifier === 'DEV' && baseComponent.qualifier !== 'DEV') { + Object.assign(options, { developerId: rootComponent.id }); + } + + Object.assign(finalOptions, options); + + const finalKey = baseComponent.refKey || baseComponent.key; + + return getComponentTree('children', finalKey, getComplementary(metric.key), finalOptions); +} + +function fetchComponents(rootComponent, baseComponent, metric, pageIndex = 1, periodIndex = 1) { + const options = { p: pageIndex }; + + return makeRequest(rootComponent, baseComponent, metric, options, periodIndex).then(r => { + const nextComponents = enhanceWithMeasure(r.components, metric.key, periodIndex); + + return { + baseComponent, + components: nextComponents, + pageIndex: r.paging.pageIndex, + total: r.paging.total + }; + }); +} + +/** + * Fetch the first page of components for a given base component + * @param baseComponent + */ +function fetchList(baseComponent) { + return (dispatch, getState) => { + const { metric, periodIndex, rootComponent } = getMeasuresAppTree(getState()); + + dispatch(startFetching()); + return fetchComponents(rootComponent, baseComponent, metric, 1, periodIndex).then(r => { + dispatch( + updateStore({ + ...r, + baseComponent, + breadcrumbs: [baseComponent] + }) + ); + dispatch(stopFetching()); + }); + }; +} + +/** + * Init tree view with root component and metric. + * Fetch the first page of components if needed. + * @param rootComponent + * @param metric + * @param periodIndex + * @returns {function()} + */ +export function start(rootComponent, metric, periodIndex = 1) { + return (dispatch, getState) => { + const tree = getMeasuresAppTree(getState()); + if (rootComponent === tree.rootComponent && metric === tree.metric) { + return Promise.resolve(); + } + + dispatch(init(rootComponent, metric, periodIndex)); + dispatch(fetchList(rootComponent)); + }; +} + +/** + * Drilldown to the component + * @param component + */ +export function drilldown(component) { + return (dispatch, getState) => { + const { metric, rootComponent, breadcrumbs, periodIndex } = getMeasuresAppTree(getState()); + dispatch(startFetching()); + return fetchComponents(rootComponent, component, metric, 1, periodIndex).then(r => { + dispatch( + updateStore({ + ...r, + breadcrumbs: [...breadcrumbs, component], + selected: undefined + }) + ); + dispatch(stopFetching()); + }); + }; +} + +/** + * Go up using breadcrumbs + * @param component + */ +export function useBreadcrumbs(component) { + return (dispatch, getState) => { + const { metric, rootComponent, breadcrumbs, periodIndex } = getMeasuresAppTree(getState()); + const index = breadcrumbs.indexOf(component); + dispatch(startFetching()); + return fetchComponents(rootComponent, component, metric, 1, periodIndex).then(r => { + dispatch( + updateStore({ + ...r, + breadcrumbs: breadcrumbs.slice(0, index + 1), + selected: undefined + }) + ); + dispatch(stopFetching()); + }); + }; +} + +export function fetchMore() { + return (dispatch, getState) => { + const { + rootComponent, + baseComponent, + metric, + pageIndex, + components, + periodIndex + } = getMeasuresAppTree(getState()); + dispatch(startFetching()); + return fetchComponents( + rootComponent, + baseComponent, + metric, + pageIndex + 1, + periodIndex + ).then(r => { + const nextComponents = [...components, ...r.components]; + dispatch(updateStore({ ...r, components: nextComponents })); + dispatch(stopFetching()); + }); + }; +} + +/** + * Select given component from the list + * @param component + */ +export function selectComponent(component) { + return (dispatch, getState) => { + const { breadcrumbs } = getMeasuresAppTree(getState()); + const nextBreadcrumbs = [...breadcrumbs, component]; + dispatch( + updateStore({ + selected: component, + breadcrumbs: nextBreadcrumbs + }) + ); + }; +} + +/** + * Select next element from the list of components + */ +export function selectNext() { + return (dispatch, getState) => { + const { components, selected, breadcrumbs } = getMeasuresAppTree(getState()); + const selectedIndex = components.indexOf(selected); + if (selectedIndex < components.length - 1) { + const nextSelected = components[selectedIndex + 1]; + const nextBreadcrumbs = [...initial(breadcrumbs), nextSelected]; + dispatch( + updateStore({ + selected: nextSelected, + breadcrumbs: nextBreadcrumbs + }) + ); + } + }; +} + +/** + * Select previous element from the list of components + */ +export function selectPrevious() { + return (dispatch, getState) => { + const { components, selected, breadcrumbs } = getMeasuresAppTree(getState()); + const selectedIndex = components.indexOf(selected); + if (selectedIndex > 0) { + const nextSelected = components[selectedIndex - 1]; + const nextBreadcrumbs = [...initial(breadcrumbs), nextSelected]; + dispatch( + updateStore({ + selected: nextSelected, + breadcrumbs: nextBreadcrumbs + }) + ); + } + }; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/store/treeViewReducer.js b/server/sonar-web/src/main/js/apps/component-measures-old/store/treeViewReducer.js new file mode 100644 index 00000000000..71050fdad57 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/store/treeViewReducer.js @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 { pick } from 'lodash'; +import { DISPLAY_HOME } from './../app/actions'; +import { UPDATE_STORE, INIT } from './treeViewActions'; + +const initialState = { + components: [], + breadcrumbs: [], + total: 0 +}; + +export default function drilldownReducer(state = initialState, action = {}) { + switch (action.type) { + case DISPLAY_HOME: + return initialState; + case UPDATE_STORE: + return { ...state, ...action.state }; + case INIT: + return { ...state, ...pick(action, ['rootComponent', 'metric', 'periodIndex']) }; + default: + return state; + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/styles.css b/server/sonar-web/src/main/js/apps/component-measures-old/styles.css new file mode 100644 index 00000000000..b72fcf31384 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/styles.css @@ -0,0 +1,404 @@ +.home-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 20px; +} + +.measures-domains { +} + +.measures-domains > li { + margin-bottom: 20px; +} + +.measures-domains > li > div { + border: 1px solid #e6e6e6; + background-color: #fff; +} + +.measures-domains-leak-header { + line-height: 22px; + padding: 0 10px; + border: 1px solid #eae3c7; + background-color: #fbf3d5; + white-space: nowrap; +} + +.main-domain-measures { + display: flex; + flex-wrap: wrap; + justify-content: space-around; + float: left; + width: 480px; + margin-right: 60px; +} + +.main-domain-measures > li { + padding: 12px 0; +} + +.main-domain-measures > li > a { + display: flex; + flex-direction: column-reverse; + width: 160px; + border: none; + text-align: center; +} + +.main-domain-measures .domain-measures-value { + height: 40px; + box-sizing: border-box; + color: #444; + font-size: 30px; + font-weight: 300; +} + +.main-domain-measures .domain-measures-value .rating, +.measure-details-value .rating { + vertical-align: top; + width: 40px; + height: 40px; + line-height: 40px; + border-radius: 40px; + font-size: 24px; +} + +.main-domain-measures .domain-measures-name { + margin-top: 8px; +} + +.main-domain-measures .domain-measures-name > span:last-child { + border-bottom: 1px solid #cae3f2; +} + +.main-domain-measures .domain-measures-leak { + margin: 0 20px; + border: 1px solid #eae3c7; + background-color: #fbf3d5; +} + +.domain-measures { + overflow: hidden; + line-height: 1.4; +} + +.domain-measures > li > a { + display: flex; + justify-content: space-between; + border: none; +} + +.domain-measures > li:nth-child(odd) > a { + background-color: #f8f8f8; +} + +.domain-measures > li > a:hover { + background-color: #ecf6fe !important; +} + +.domain-measures .domain-measures-name, +.domain-measures .domain-measures-value { + padding: 7px 10px; + box-sizing: border-box; +} + +.domain-measures .domain-measures-name { + width: calc(100% - 160px); + line-height: 24px; +} + +.domain-measures .domain-measures-name > span { + border-bottom: 1px solid #cae3f2; +} + +.domain-measures .domain-measures-value { + min-width: 80px; + color: #444; + text-align: right; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.domain-measures .domain-measures-leak { + background-color: #fbf3d5; + transition: background-color 0.3s ease; +} + +.domain-measures .domain-measures > li:nth-child(odd) .domain-measures-leak { + background-color: #f5eed0; +} + +.measure-details { + margin-top: 10px; +} + +.measure-details-header { + position: relative; + margin-top: 10px; + margin-bottom: 30px; +} + +.measure-details-metric, +.measure-details-value { +} + +.measure-details-metric { + display: inline-block; + margin-bottom: 10px; +} + +.measure-details-metric > a:not(.button) { + border: none; + color: #444; +} + +.measure-details-metric > a:not(.button):hover { + color: #236a97; +} + +.measure-details-value { + font-size: 24px; +} + +.measure-details-value-absolute { + display: inline-block; + vertical-align: middle; + padding: 5px 0; + font-weight: 300; +} + +.measure-details-value-leak { + display: inline-block; + vertical-align: middle; + padding: 4px 10px; + border: 1px solid #eae3c7; + background-color: #fbf3d5; + font-weight: 300; +} + +.measure-details-value-absolute + .measure-details-value-leak { + margin-left: 20px; +} + +.measure-details-secondary { + display: inline-block; + vertical-align: middle; + width: 260px; + margin-left: 20px; +} + +.measure-details-drilldown { + margin-top: 20px; +} + +.measure-details-drilldown-mode { + display: flex; + margin-bottom: 10px; + border-bottom: 1px solid #e6e6e6; +} + +.measure-details-drilldown-mode > li { + margin-bottom: -1px; +} + +.measure-details-drilldown-mode > li + li { + margin-left: 2px; +} + +.measure-details-drilldown-mode > li > a { + display: inline-block; + padding: 5px 10px; + border-bottom: 2px solid transparent; + color: #444; +} + +.measure-details-drilldown-mode > li > a:hover, +.measure-details-drilldown-mode > li > a.active { + border-bottom-color: #4b9fd5; +} + +.measure-details-drilldown-mode > li > a.active .measure-tab-icon path { + fill: #4b9fd5; +} + +.measure-details-plain-list { +} + +.measure-details-components { + width: 300px; + padding: 10px; + box-sizing: border-box; +} + +.measure-details-components > li > a { + display: flex; + padding-top: 5px; + padding-bottom: 5px; + border: none; + color: #444; +} + +.measure-details-components > li > a:hover, +.measure-details-components > li > a.selected { + background-color: #cae3f2 !important; +} + +.measure-details-component-name, +.measure-details-component-value { + padding-right: 10px; + box-sizing: border-box; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.measure-details-component-name { + width: calc(100% - 60px); + padding-left: 10px; +} + +.measure-details-component-value { + width: 60px; + text-align: right; +} + +.measure-details-viewer { + min-height: 100vh; +} + +.measure-details-viewer-header { + margin-bottom: 10px; + line-height: 24px; +} + +.measure-details-viewer-header .button-group { + vertical-align: top; +} + +.measure-details-header-container { + display: inline-block; + line-height: 16px; + padding-right: 10px; +} + +.measure-tab-icon { + display: inline-block; + width: 14px; + height: 14px; + margin-right: 6px; +} + +.measure-tab-icon path { + fill: #aeaeae; + transition: fill 0.3s ease; +} + +.measure-details-components-up-icon path { + fill: #aeaeae; +} + +.measure-details-history { + padding: 10px 0; +} + +.measure-details-bubble-chart { + position: relative; + margin: 40px 0 10px; + padding: 30px 0 30px 60px; + border: 1px solid #e6e6e6; + background-color: #fff; +} + +.measure-details-bubble-chart-axis { + position: absolute; + color: #777; + font-size: 12px; +} + +.measure-details-bubble-chart-axis.x { + left: 50%; + bottom: 10px; + width: 500px; + margin-left: -250px; + text-align: center; +} + +.measure-details-bubble-chart-axis.y { + top: 50%; + left: -20px; + transform: rotate(-90deg); +} + +.measure-details-bubble-chart-axis.size { + left: 50%; + top: 10px; + width: 500px; + margin-left: -250px; + text-align: center; +} + +.measure-details-treemap { + margin: 20px 0; +} + +.measure-details-treemap-legend { + margin-bottom: 10px; +} + +.component-measures-breadcrumbs { + display: flex; + flex-wrap: wrap; +} + +.component-measures-breadcrumbs > li { + padding: 5px 5px 3px; +} + +.component-measures-breadcrumbs > li:first-child { + padding-left: 0; +} + +.component-measures-breadcrumbs > li::after { + position: relative; + top: -1px; + padding-left: 10px; + color: #777; + font-size: 11px; + content: ">"; +} + +.component-measures-breadcrumbs > li:last-child::after { + display: none; +} + +.home-measures-list { + border: 1px solid #e6e6e6; + background-color: #fff; +} + +.nav-pills > ul { + display: flex; + flex-wrap: wrap; +} + +.nav-pills > ul > li > a { + display: inline-block; + vertical-align: middle; + padding: 3px 10px; + border: 1px solid transparent; + border-radius: 24px; + color: #236a97; + transition: none; +} + +.nav-pills > ul > li > a:hover { + border-color: #236a97; +} + +.nav-pills > ul > li.active > a, +.nav-pills > ul > li > a.active { + background-color: #236a97; + color: #fff; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures-old/utils.js b/server/sonar-web/src/main/js/apps/component-measures-old/utils.js new file mode 100644 index 00000000000..20595c7ab18 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component-measures-old/utils.js @@ -0,0 +1,121 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info 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 bubbles from './config/bubbles'; +import { + formatMeasure, + formatMeasureVariation, + getRatingTooltip as nextGetRatingTooltip, + isDiffMetric +} from '../../helpers/measures'; + +export function getLeakValue(measure, periodIndex = 1) { + if (!measure) { + return null; + } + + const period = measure.periods + ? measure.periods.find(period => period.index === periodIndex) + : null; + + return period ? period.value : null; +} + +export function getSingleMeasureValue(measures) { + if (!measures || !measures.length) { + return null; + } + + return measures[0].value; +} + +export function getSingleLeakValue(measures, periodIndex = 1) { + if (!measures || !measures.length) { + return null; + } + + const measure = measures[0]; + + const period = measure.periods + ? measure.periods.find(period => period.index === periodIndex) + : null; + + return period ? period.value : null; +} + +export function formatLeak(value, metric, options) { + if (isDiffMetric(metric.key)) { + return formatMeasure(value, metric.type, options); + } else { + return formatMeasureVariation(value, metric.type, options); + } +} + +export function enhanceWithLeak(measures, periodIndex = 1) { + function enhanceSingle(measure) { + return { ...measure, leak: getLeakValue(measure, periodIndex) }; + } + + if (Array.isArray(measures)) { + return measures.map(enhanceSingle); + } else { + return enhanceSingle(measures); + } +} + +export function enhanceWithSingleMeasure(components, periodIndex = 1) { + return components.map(component => { + return { + ...component, + value: getSingleMeasureValue(component.measures), + leak: getSingleLeakValue(component.measures, periodIndex) + }; + }); +} + +export function enhanceWithMeasure(components, metric, periodIndex = 1) { + return components.map(component => { + const measuresWithLeak = enhanceWithLeak(component.measures, periodIndex); + const measure = measuresWithLeak.find(measure => measure.metric === metric); + const value = measure ? measure.value : null; + const leak = measure ? measure.leak : null; + return { ...component, value, leak, measures: measuresWithLeak }; + }); +} + +export function hasBubbleChart(domainName) { + return !!bubbles[domainName]; +} + +export function hasTreemap(metric) { + return ['PERCENT', 'RATING', 'LEVEL'].indexOf(metric.type) !== -1; +} + +export function filterOutEmptyMeasures(components) { + return components.filter(component => component.value !== null || component.leak !== null); +} + +export function getRatingTooltip(metricKey, value) { + const finalMetricKey = metricKey.indexOf('new_') === 0 ? metricKey.substr(4) : metricKey; + const KNOWN_RATINGS = ['sqale_rating', 'reliability_rating', 'security_rating']; + if (KNOWN_RATINGS.includes(finalMetricKey)) { + return nextGetRatingTooltip(finalMetricKey, value); + } + return null; +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/app/App.js b/server/sonar-web/src/main/js/apps/component-measures/app/App.js deleted file mode 100644 index fd7caef81a8..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/app/App.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Helmet from 'react-helmet'; -import Spinner from './../components/Spinner'; -import { translate } from '../../../helpers/l10n'; -import '../styles.css'; - -export default class App extends React.PureComponent { - state = { componentSet: false }; - - componentDidMount() { - this.props.setComponent(this.props.component); - this.props.fetchMetrics(); - this.setState({ componentSet: true }); - } - - render() { - if (this.props.metrics == null || !this.state.componentSet) { - return ; - } - - return ( -
    - - {this.props.children} -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/app/AppContainer.js b/server/sonar-web/src/main/js/apps/component-measures/app/AppContainer.js deleted file mode 100644 index dca2e1eb935..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/app/AppContainer.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import App from './App'; -import { fetchMetrics, setComponent } from './actions'; -import { getComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer'; - -const mapStateToProps = (state, ownProps) => ({ - component: getComponent(state, ownProps.location.query.id), - metrics: getMeasuresAppAllMetrics(state) -}); - -const mapDispatchToProps = dispatch => { - return { - fetchMetrics: () => dispatch(fetchMetrics()), - setComponent: component => dispatch(setComponent(component)) - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(App); diff --git a/server/sonar-web/src/main/js/apps/component-measures/app/actions.js b/server/sonar-web/src/main/js/apps/component-measures/app/actions.js deleted file mode 100644 index 7cfb8acbe6f..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/app/actions.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { getMetrics } from '../../../api/metrics'; - -/* - * Actions - */ - -export const DISPLAY_HOME = 'measuresApp/app/DISPLAY_HOME'; -export const RECEIVE_METRICS = 'measuresApp/app/RECEIVE_METRICS'; -export const SET_COMPONENT = 'measuresApp/app/SET_COMPONENT'; - -/* - * Action Creators - */ - -export function displayHome() { - return { type: DISPLAY_HOME }; -} - -function receiveMetrics(metrics) { - return { type: RECEIVE_METRICS, metrics }; -} - -export function setComponent(component) { - return { type: SET_COMPONENT, component }; -} - -/* - * Workflow - */ - -export function fetchMetrics() { - return dispatch => { - getMetrics().then(metrics => { - dispatch(receiveMetrics(metrics)); - }); - }; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/app/reducer.js b/server/sonar-web/src/main/js/apps/component-measures/app/reducer.js deleted file mode 100644 index 165b79c524b..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/app/reducer.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { RECEIVE_METRICS, SET_COMPONENT } from './actions'; - -const initialState = { - metrics: undefined -}; - -export default function appReducer(state = initialState, action = {}) { - switch (action.type) { - case RECEIVE_METRICS: - return { ...state, metrics: action.metrics }; - case SET_COMPONENT: - return { ...state, component: action.component }; - default: - return state; - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/IconBubbles.js b/server/sonar-web/src/main/js/apps/component-measures/components/IconBubbles.js deleted file mode 100644 index 130adcc0c15..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/IconBubbles.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 IconBubbles() { - /* eslint max-len: 0 */ - 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 deleted file mode 100644 index df6d69e7f3b..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/IconList.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 deleted file mode 100644 index 9270286f6a8..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/IconTree.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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/IconTreemap.js b/server/sonar-web/src/main/js/apps/component-measures/components/IconTreemap.js deleted file mode 100644 index aef8aabc7ff..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/IconTreemap.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 IconTreemap() { - return ( - - - - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js b/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js deleted file mode 100644 index 22483f15b54..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/LeakPeriodLegend.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 moment from 'moment'; -import Tooltip from '../../../components/controls/Tooltip'; -import { getPeriodLabel, getPeriodDate } from '../../../helpers/periods'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; - -export default function LeakPeriodLegend({ component, period }) { - if (component.qualifier === 'APP') { - return ( -
    - {translate('issues.leak_period')} -
    - ); - } - - const label = ( -
    - {translateWithParameters('overview.leak_period_x', getPeriodLabel(period))} -
    - ); - - if (period.mode === 'days') { - return label; - } - - const date = getPeriodDate(period); - const fromNow = moment(date).fromNow(); - const tooltip = fromNow + ', ' + moment(date).format('LL'); - return ( - - {label} - - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js b/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js deleted file mode 100644 index ba59123b3b7..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 PropTypes from 'prop-types'; -import Rating from '../../../components/ui/Rating'; -import Level from '../../../components/ui/Level'; -import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; -import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -import { formatLeak, getRatingTooltip } from '../utils'; - -export default class Measure extends React.PureComponent { - static propTypes = { - className: PropTypes.string, - measure: PropTypes.object, - metric: PropTypes.object, - decimals: PropTypes.number - }; - - renderRating(measure, metric) { - const value = isDiffMetric(metric.key) ? measure.leak : measure.value; - const tooltip = getRatingTooltip(metric.key, value); - const rating = ; - - if (tooltip) { - return ( - - - - {rating} - - - - ); - } - - return rating; - } - - render() { - const { measure, metric, decimals, className } = this.props; - const finalMetric = metric || measure.metric; - - if (finalMetric.type === 'RATING') { - return this.renderRating(measure, finalMetric); - } - - if (finalMetric.type === 'LEVEL') { - return ; - } - - const formattedValue = isDiffMetric(finalMetric.key) - ? formatLeak(measure.leak, finalMetric, { decimals }) - : formatMeasure(measure.value, finalMetric.type, { decimals }); - return ( - - {formattedValue != null ? formattedValue : '–'} - - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/Spinner.js b/server/sonar-web/src/main/js/apps/component-measures/components/Spinner.js deleted file mode 100644 index 3f899ac3b4f..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/Spinner.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Spinner() { - return ; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js b/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js deleted file mode 100644 index 4729500df36..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js +++ /dev/null @@ -1,190 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 OriginalBubbleChart from '../../../../components/charts/BubbleChart'; -import bubbles from '../../config/bubbles'; -import { getComponentLeaves } from '../../../../api/components'; -import { formatMeasure } from '../../../../helpers/measures'; -import Workspace from '../../../../components/workspace/main'; -import { getComponentUrl } from '../../../../helpers/urls'; -import { getLocalizedMetricName, translateWithParameters } from '../../../../helpers/l10n'; - -const HEIGHT = 500; -const BUBBLES_LIMIT = 500; - -function getMeasure(component, metric) { - return Number(component.measures[metric]) || 0; -} - -export default class BubbleChart extends React.PureComponent { - state = { - fetching: 0, - files: [] - }; - - componentWillMount() { - this.updateMetrics(this.props); - } - - componentDidMount() { - this.mounted = true; - this.fetchFiles(); - } - - componentWillUpdate(nextProps) { - this.updateMetrics(nextProps); - } - - componentDidUpdate(nextProps) { - if (nextProps.domainName !== this.props.domainName) { - this.fetchFiles(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - updateMetrics(props) { - const { metrics, domainName } = props; - const conf = bubbles[domainName]; - this.xMetric = metrics.find(m => m.key === conf.x); - this.yMetric = metrics.find(m => m.key === conf.y); - this.sizeMetric = metrics.find(m => m.key === conf.size); - } - - fetchFiles() { - const { component } = this.props; - const metrics = [this.xMetric.key, this.yMetric.key, this.sizeMetric.key]; - const options = { - s: 'metric', - metricSort: this.sizeMetric.key, - asc: false, - ps: BUBBLES_LIMIT - }; - - if (this.mounted) { - this.setState({ fetching: this.state.fetching + 1 }); - } - - getComponentLeaves(component.key, metrics, options).then(r => { - const files = r.components.map(file => { - const measures = {}; - - file.measures.forEach(measure => { - measures[measure.metric] = measure.value; - }); - return { ...file, measures }; - }); - - if (this.mounted) { - this.setState({ - files, - fetching: this.state.fetching - 1, - total: files.length - }); - } - }); - } - - getTooltip(component) { - const x = formatMeasure(getMeasure(component, this.xMetric.key), this.xMetric.type); - const y = formatMeasure(getMeasure(component, this.yMetric.key), this.yMetric.type); - const size = formatMeasure(getMeasure(component, this.sizeMetric.key), this.sizeMetric.type); - const inner = [ - component.name, - `${this.xMetric.name}: ${x}`, - `${this.yMetric.name}: ${y}`, - `${this.sizeMetric.name}: ${size}` - ].join('
    '); - - return `
    ${inner}
    `; - } - - handleBubbleClick(component) { - if (['FIL', 'UTS'].includes(component.qualifier)) { - Workspace.openComponent({ key: component.key }); - } else { - window.location = getComponentUrl(component.refKey || component.key); - } - } - - renderBubbleChart() { - const items = this.state.files.map(file => { - return { - x: getMeasure(file, this.xMetric.key), - y: getMeasure(file, this.yMetric.key), - size: getMeasure(file, this.sizeMetric.key), - link: file, - tooltip: this.getTooltip(file) - }; - }); - - const formatXTick = tick => formatMeasure(tick, this.xMetric.type); - const formatYTick = tick => formatMeasure(tick, this.yMetric.type); - - return ( - - ); - } - - render() { - const { fetching } = this.state; - - if (fetching) { - return ( -
    -
    - -
    -
    - ); - } - - return ( -
    -
    - {this.renderBubbleChart()} -
    - -
    - {getLocalizedMetricName(this.xMetric)} -
    -
    - {getLocalizedMetricName(this.yMetric)} -
    -
    - {translateWithParameters( - 'component_measures.legend.size_x', - getLocalizedMetricName(this.sizeMetric) - )} -
    -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/MeasureBubbleChartContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/MeasureBubbleChartContainer.js deleted file mode 100644 index bc9741bed87..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/MeasureBubbleChartContainer.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import MeasureBubbleChart from './BubbleChart'; -import { getMeasuresAppAllMetrics, getMeasuresAppComponent } from '../../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - component: getMeasuresAppComponent(state), - metrics: getMeasuresAppAllMetrics(state) - }; -}; - -const mapDispatchToProps = () => { - return {}; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(MeasureBubbleChart); diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.js b/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.js deleted file mode 100644 index 28407f56dc5..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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. - */ -const bubblesConfig = { - Reliability: { x: 'ncloc', y: 'reliability_remediation_effort', size: 'bugs' }, - Security: { x: 'ncloc', y: 'security_remediation_effort', size: 'vulnerabilities' }, - Maintainability: { x: 'ncloc', y: 'sqale_index', size: 'code_smells' }, - Coverage: { x: 'complexity', y: 'coverage', size: 'uncovered_lines' }, - Duplications: { x: 'ncloc', y: 'duplicated_lines', size: 'duplicated_blocks' } -}; - -export default bubblesConfig; diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/complementary.js b/server/sonar-web/src/main/js/apps/component-measures/config/complementary.js deleted file mode 100644 index 46340a2cd23..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/config/complementary.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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. - */ -export default { - coverage: ['uncovered_lines', 'uncovered_conditions'], - line_coverage: ['uncovered_lines'], - branch_coverage: ['uncovered_conditions'], - uncovered_lines: ['line_coverage'], - uncovered_conditions: ['branch_coverage'], - - new_coverage: ['new_uncovered_lines', 'new_uncovered_conditions'], - new_line_coverage: ['new_uncovered_lines'], - new_branch_coverage: ['new_uncovered_conditions'], - new_uncovered_lines: ['new_line_coverage'], - new_uncovered_conditions: ['new_branch_coverage'], - - duplicated_lines_density: ['duplicated_lines'], - new_duplicated_lines_density: ['new_duplicated_lines'], - duplicated_lines: ['duplicated_lines_density'], - new_duplicated_lines: ['new_duplicated_lines_density'] -}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/domains.js b/server/sonar-web/src/main/js/apps/component-measures/config/domains.js deleted file mode 100644 index 6ac6a6975c2..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/config/domains.js +++ /dev/null @@ -1,142 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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. - */ -export const domains = { - Reliability: { - main: ['bugs', 'new_bugs', 'reliability_rating'], - order: [ - 'bugs', - 'new_bugs', - 'reliability_rating', - 'reliability_remediation_effort', - 'new_reliability_remediation_effort' - ] - }, - - Security: { - main: ['vulnerabilities', 'new_vulnerabilities', 'security_rating'], - order: [ - 'vulnerabilities', - 'new_vulnerabilities', - 'security_rating', - 'security_remediation_effort', - 'new_security_remediation_effort' - ] - }, - - Maintainability: { - main: ['code_smells', 'new_code_smells', 'sqale_rating'], - order: [ - 'code_smells', - 'new_code_smells', - 'sqale_rating', - 'sqale_index', - 'new_technical_debt', - 'sqale_debt_ratio', - 'new_sqale_debt_ratio', - 'effort_to_reach_maintainability_rating_a' - ] - }, - - Coverage: { - main: ['coverage', 'new_coverage', 'tests'], - order: [ - 'coverage', - 'new_coverage', - 'line_coverage', - 'new_line_coverage', - 'branch_coverage', - 'new_branch_coverage', - 'uncovered_lines', - 'new_uncovered_lines', - 'uncovered_conditions', - 'new_uncovered_conditions', - 'new_lines_to_cover', - - 'lines_to_cover', - - 'tests', - 'test_success', - 'test_errors', - 'test_failures', - 'skipped_tests', - 'test_success_density', - 'test_execution_time' - ] - }, - - Duplications: { - main: ['duplicated_lines_density', 'new_duplicated_lines_density'], - order: [ - 'duplicated_lines_density', - 'new_duplicated_lines_density', - 'duplicated_blocks', - 'new_duplicated_blocks', - 'duplicated_lines', - 'new_duplicated_lines', - 'duplicated_files' - ] - }, - - Size: { - main: ['ncloc'], - order: [ - 'ncloc', - 'lines', - 'new_lines', - 'statements', - 'functions', - 'classes', - 'files', - 'directories' - ] - }, - - Complexity: { - main: ['complexity'], - order: ['complexity', 'function_complexity', 'file_complexity', 'class_complexity'] - }, - - Releasability: { - main: ['alert_status', 'releasability_rating'], - order: ['alert_status'] - }, - - Issues: { - main: ['violations', 'new_violations'], - order: [ - 'violations', - 'new_violations', - 'blocker_violations', - 'new_blocker_violations', - 'critical_violations', - 'new_critical_violations', - 'major_violations', - 'new_major_violations', - 'minor_violations', - 'new_minor_violations', - 'info_violations', - 'new_info_violations', - 'open_issues', - 'reopened_issues', - 'confirmed_issues', - 'false_positive_issues' - ] - } -}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js b/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js deleted file mode 100644 index ab1c9386456..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js +++ /dev/null @@ -1,132 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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, IndexLink } from 'react-router'; -import Spinner from './../components/Spinner'; -import MeasureDetailsHeader from './MeasureDetailsHeader'; -import MeasureDrilldown from './drilldown/MeasureDrilldown'; -import MetricNotFound from './MetricNotFound'; -import { getPeriod, getPeriodDate } from '../../../helpers/periods'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; - -export default class MeasureDetails extends React.PureComponent { - mounted: boolean; - - state = { - loading: true - }; - - componentDidMount() { - this.mounted = true; - this.loadData(); - } - - componentDidUpdate(prevProps) { - if (prevProps.params.metricKey !== this.props.params.metricKey) { - this.loadData(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - metricExists(): boolean { - const { metrics } = this.props; - const { metricKey } = this.props.params; - const metric = metrics.find(metric => metric.key === metricKey); - return !!metric; - } - - loadData() { - if (this.metricExists()) { - this.setState({ loading: true }); - const periodIndex = this.props.location.query.period || 1; - const onLoaded = () => this.mounted && this.setState({ loading: false }); - this.props - .fetchMeasure(this.props.params.metricKey, Number(periodIndex)) - .then(onLoaded, onLoaded); - } - } - - render() { - if (!this.metricExists()) { - return ; - } - - if (this.state.loading) { - return ; - } - - const { component, metric, secondaryMeasure, measure, periods, children } = this.props; - - if (!measure) { - return ; - } - - const { tab } = this.props.params; - const periodIndex = this.props.location.query.period || 1; - const period = getPeriod(periods, Number(periodIndex)); - const periodDate = getPeriodDate(period); - - return ( -
    -
    - - {translate('component_measures.all_measures')} - - {!!metric.domain && - - {' / '} - - {translateWithParameters('component_measures.domain_measures', metric.domain)} - - } -
    - - - - {measure && - - {children} - } -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetailsContainer.js b/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetailsContainer.js deleted file mode 100644 index 7ae39057181..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetailsContainer.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import MeasureDetails from './MeasureDetails'; -import { fetchMeasure } from './actions'; -import { - getMeasuresAppAllMetrics, - getMeasuresAppDetailsMetric, - getMeasuresAppDetailsMeasure, - getMeasuresAppDetailsSecondaryMeasure, - getMeasuresAppDetailsPeriods, - getMeasuresAppComponent -} from '../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - component: getMeasuresAppComponent(state), - metrics: getMeasuresAppAllMetrics(state), - metric: getMeasuresAppDetailsMetric(state), - measure: getMeasuresAppDetailsMeasure(state), - secondaryMeasure: getMeasuresAppDetailsSecondaryMeasure(state), - periods: getMeasuresAppDetailsPeriods(state) - }; -}; - -const mapDispatchToProps = { fetchMeasure }; - -export default connect(mapStateToProps, mapDispatchToProps)(MeasureDetails); diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetailsHeader.js b/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetailsHeader.js deleted file mode 100644 index f2281c24eba..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetailsHeader.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Measure from './../components/Measure'; -import LanguageDistribution from '../../../components/charts/LanguageDistribution'; -import LeakPeriodLegend from '../components/LeakPeriodLegend'; -import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; -import HistoryIcon from '../../../components/icons-components/HistoryIcon'; -import Tooltip from '../../../components/controls/Tooltip'; -import { ComplexityDistribution } from '../../../components/shared/complexity-distribution'; -import { isDiffMetric } from '../../../helpers/measures'; -import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; -import { getComponentMeasureHistory } from '../../../helpers/urls'; -import { getLocalizedMetricName, translate } from '../../../helpers/l10n'; - -export default function MeasureDetailsHeader({ - component, - measure, - metric, - secondaryMeasure, - leakPeriod -}) { - const isDiff = isDiffMetric(metric.key); - return ( -
    -

    - - {getLocalizedMetricName(metric)} - {!isDiff && - - - - - } -

    - - {isDiff && -
    - -
    } - - -
    - {isDiff - ?
    - -
    - :
    - -
    } - - {secondaryMeasure && - secondaryMeasure.metric === 'ncloc_language_distribution' && -
    - -
    } - - {secondaryMeasure && - secondaryMeasure.metric === 'function_complexity_distribution' && -
    - -
    } - - {secondaryMeasure && - secondaryMeasure.metric === 'file_complexity_distribution' && -
    - -
    } -
    -
    -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js b/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js deleted file mode 100644 index 57b5fee5844..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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. - */ -// @flow -import React from 'react'; -import { translate } from '../../../helpers/l10n'; - -export default function MetricNotFound() { - return ( -
    -
    - {translate('component_measures.not_found')} -
    -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/actions.js b/server/sonar-web/src/main/js/apps/component-measures/details/actions.js deleted file mode 100644 index 55579349c01..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/actions.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { getMeasuresAndMeta } from '../../../api/measures'; -import { enhanceWithLeak } from '../utils'; -import { getMeasuresAppComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer'; - -/* - * Actions - */ - -export const REQUEST_MEASURE = 'measuresApp/details/REQUEST_MEASURE'; -export const RECEIVE_MEASURE = 'measuresApp/details/RECEIVE_MEASURE'; - -/* - * Action Creators - */ - -function requestMeasure(metric) { - return { type: REQUEST_MEASURE, metric }; -} - -function receiveMeasure(measure, secondaryMeasure, periods) { - return { type: RECEIVE_MEASURE, measure, secondaryMeasure, periods }; -} - -/* - * Workflow - */ - -export function fetchMeasure(metricKey, periodIndex = 1) { - return (dispatch, getState) => { - const state = getState(); - const component = getMeasuresAppComponent(state); - const metrics = getMeasuresAppAllMetrics(state); - const metricsToRequest = [metricKey]; - - if (metricKey === 'ncloc') { - metricsToRequest.push('ncloc_language_distribution'); - } - if (metricKey === 'function_complexity') { - metricsToRequest.push('function_complexity_distribution'); - } - if (metricKey === 'file_complexity') { - metricsToRequest.push('file_complexity_distribution'); - } - - const metric = metrics.find(m => m.key === metricKey); - dispatch(requestMeasure(metric)); - - return getMeasuresAndMeta(component.key, metricsToRequest, { - additionalFields: 'periods' - }).then(r => { - const measures = enhanceWithLeak(r.component.measures, periodIndex); - const measure = measures.find(m => m.metric === metricKey); - const secondaryMeasure = measures.find(m => m.metric !== metricKey); - dispatch(receiveMeasure(measure, secondaryMeasure, r.periods)); - }); - }; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/Breadcrumb.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/Breadcrumb.js deleted file mode 100644 index aa038d9d004..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/Breadcrumb.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 QualifierIcon from '../../../../components/shared/QualifierIcon'; -import { formatLeak } from '../../utils'; -import { formatMeasure, isDiffMetric } from '../../../../helpers/measures'; - -const Breadcrumb = ({ component, metric, onBrowse }) => { - const handleClick = e => { - e.preventDefault(); - e.target.blur(); - onBrowse(component); - }; - - let inner; - if (onBrowse) { - inner = ( - - {component.name} - - ); - } else { - inner = ( - - {component.name} - - ); - } - - const value = isDiffMetric(metric.key) - ? formatLeak(component.leak, metric) - : formatMeasure(component.value, metric.type); - - return ( - - -   - {inner} - {value != null && - - {' (' + value + ')'} - } - - ); -}; - -export default Breadcrumb; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/Breadcrumbs.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/Breadcrumbs.js deleted file mode 100644 index 227fad25782..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/Breadcrumbs.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Breadcrumb from './Breadcrumb'; - -const Breadcrumbs = ({ breadcrumbs, metric, onBrowse }) => -
      - {breadcrumbs.map((component, index) => -
    • - -
    • - )} -
    ; - -export default Breadcrumbs; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentCell.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentCell.js deleted file mode 100644 index 6d9ae770a8a..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentCell.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 classNames from 'classnames'; -import QualifierIcon from '../../../../components/shared/QualifierIcon'; -import { splitPath } from '../../../../helpers/path'; -import { getComponentUrl } from '../../../../helpers/urls'; - -const ComponentCell = ({ component, isSelected, onClick }) => { - const linkClassName = classNames('link-no-underline', { - selected: isSelected - }); - - const handleClick = e => { - const isLeftClickEvent = e.button === 0; - const isModifiedEvent = !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey); - - if (isLeftClickEvent && !isModifiedEvent) { - e.preventDefault(); - onClick(); - } - }; - - let head = ''; - let tail = component.name; - - if (['DIR', 'FIL', 'UTS'].includes(component.qualifier)) { - const parts = splitPath(component.path); - head = parts.head; - tail = parts.tail; - } - - const inner = ( - - -   - {head.length > 0 && - - {head}/ - } - {tail} - - ); - - return ( - -
    - {component.refId == null || component.qualifier === 'DEV_PRJ' - ? - {inner} - - : - - - - - {inner} - } -
    - - ); -}; - -export default ComponentCell; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentsList.js deleted file mode 100644 index 0faf5f66dfb..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentsList.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 ComponentsListRow from './ComponentsListRow'; -import EmptyComponentsList from './EmptyComponentsList'; -import complementary from '../../config/complementary'; -import { getLocalizedMetricName } from '../../../../helpers/l10n'; - -const ComponentsList = ({ components, metrics, selected, metric, onClick }) => { - if (!components.length) { - return ; - } - - const otherMetrics = (complementary[metric.key] || []).map(metric => { - return metrics.find(m => m.key === metric); - }); - - return ( - - {otherMetrics.length > 0 && - - - - - {otherMetrics.map(metric => - - )} - - } - - - {components.map(component => - - )} - -
      - - {getLocalizedMetricName(metric)} - - - - {getLocalizedMetricName(metric)} - -
    - ); -}; - -export default ComponentsList; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentsListRow.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentsListRow.js deleted file mode 100644 index 8e01925a987..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ComponentsListRow.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 ComponentCell from './ComponentCell'; -import MeasureCell from './MeasureCell'; - -const replaceMeasure = (component, measure) => { - return { - ...component, - value: measure.value, - leak: measure.leak - }; -}; - -const ComponentsListRow = ({ component, otherMetrics, isSelected, metric, onClick }) => { - const handleClick = () => { - onClick(component); - }; - - const otherMeasures = otherMetrics.map(metric => { - const measure = component.measures.find(measure => measure.metric === metric.key); - return { ...measure, metric }; - }); - - return ( - - - - - - {otherMeasures.map(measure => - - )} - - ); -}; - -export default ComponentsListRow; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/EmptyComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/EmptyComponentsList.js deleted file mode 100644 index be032c05ce0..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/EmptyComponentsList.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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'; - -const EmptyComponentsList = () => { - return ( -
    - {translate('no_results')} -
    - ); -}; - -export default EmptyComponentsList; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListHeader.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListHeader.js deleted file mode 100644 index b929bac5d9a..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListHeader.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Breadcrumbs from './Breadcrumbs'; -import { translateWithParameters } from '../../../../helpers/l10n'; - -const ListHeader = props => { - const { metric, breadcrumbs, onBrowse } = props; - const { selectedIndex, componentsCount, onSelectPrevious, onSelectNext } = props; - const hasPrevious = selectedIndex > 0; - const hasNext = selectedIndex < componentsCount - 1; - const blur = fn => { - return e => { - e.target.blur(); - fn(); - }; - }; - - return ( -
    - {breadcrumbs != null && - breadcrumbs.length > 1 && -
    - -
    } - - {selectedIndex != null && - selectedIndex !== -1 && -
    - - {translateWithParameters( - 'component_measures.x_of_y', - selectedIndex + 1, - componentsCount - )} - - -
    - {hasPrevious && } - {hasNext && } -
    -
    } -
    - ); -}; - -export default ListHeader; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js deleted file mode 100644 index 88d28d8f5f9..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js +++ /dev/null @@ -1,172 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 PropTypes from 'prop-types'; -import classNames from 'classnames'; -import moment from 'moment'; -import ComponentsList from './ComponentsList'; -import ListHeader from './ListHeader'; -import Spinner from '../../components/Spinner'; -import SourceViewer from '../../../../components/SourceViewer/SourceViewer'; -import ListFooter from '../../../../components/controls/ListFooter'; - -export default class ListView extends React.PureComponent { - static contextTypes = { - router: PropTypes.object.isRequired - }; - - componentDidMount() { - const { component, metric } = this.props; - if (component.qualifier === 'DEV') { - const { router } = this.context; - router.replace({ pathname: `metric/${metric.key}/tree`, query: { id: component.key } }); - } - this.handleChangeBaseComponent(component); - } - - componentDidUpdate(nextProps) { - if (nextProps.metric !== this.props.metric) { - this.handleChangeBaseComponent(this.props.component); - } - - if (this.props.selected) { - this.scrollToViewer(); - } else if (this.scrollTop) { - this.scrollToStoredPosition(); - } - } - - scrollToViewer() { - const { container } = this.refs; - const top = container.getBoundingClientRect().top + window.scrollY - 95 - 10; - - // scroll only to top - if (window.scrollY > top) { - window.scrollTo(0, top); - } - } - - scrollToStoredPosition() { - window.scrollTo(0, this.scrollTop); - this.scrollTop = null; - } - - storeScrollPosition() { - this.scrollTop = window.scrollY; - } - - handleChangeBaseComponent(baseComponent) { - const { metric, onFetchList } = this.props; - const periodIndex = this.props.location.query.period || 1; - onFetchList(baseComponent, metric, Number(periodIndex)); - } - - handleFetchMore() { - const periodIndex = this.props.location.query.period || 1; - this.props.onFetchMore(Number(periodIndex)); - } - - changeSelected(selected) { - this.props.onSelect(selected); - } - - handleClick(selected) { - this.storeScrollPosition(); - this.props.onSelect(selected); - } - - handleBreadcrumbClick() { - this.props.onSelect(undefined); - } - - render() { - const { - component, - components, - metrics, - metric, - leakPeriod, - selected, - total, - fetching - } = this.props; - const { onSelectNext, onSelectPrevious } = this.props; - - const breadcrumbs = [component]; - if (selected) { - breadcrumbs.push(selected); - } - const selectedIndex = components.indexOf(selected); - const sourceViewerPeriod = metric.key.indexOf('new_') === 0 && !!leakPeriod ? leakPeriod : null; - const sourceViewerPeriodDate = - sourceViewerPeriod != null ? moment(sourceViewerPeriod.date).toDate() : null; - - const filterLine = - sourceViewerPeriodDate != null - ? line => { - if (line.scmDate) { - const scmDate = moment(line.scmDate).toDate(); - return scmDate >= sourceViewerPeriodDate; - } else { - return false; - } - } - : undefined; - - return ( -
    - - - {!selected && -
    - {!fetching || components.length !== 0 - ?
    - - -
    - : } -
    } - - {!!selected && -
    - -
    } -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListViewContainer.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListViewContainer.js deleted file mode 100644 index bf6b3fc106a..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListViewContainer.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import ListView from './ListView'; -import { - fetchList, - fetchMore, - selectComponent, - selectNext, - selectPrevious -} from '../../store/listViewActions'; -import { - getMeasuresAppListComponents, - getMeasuresAppListSelected, - getMeasuresAppListTotal, - getMeasuresAppListPageIndex, - getMeasuresAppAllMetrics, - getMeasuresAppDetailsMetric, - isMeasuresAppFetching, - getMeasuresAppComponent -} from '../../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - components: getMeasuresAppListComponents(state), - selected: getMeasuresAppListSelected(state), - total: getMeasuresAppListTotal(state), - pageIndex: getMeasuresAppListPageIndex(state), - component: getMeasuresAppComponent(state), - metrics: getMeasuresAppAllMetrics(state), - metric: getMeasuresAppDetailsMetric(state), - fetching: isMeasuresAppFetching(state) - }; -}; - -const mapDispatchToProps = dispatch => { - return { - onFetchList: (baseComponent, metric, periodIndex) => - dispatch(fetchList(baseComponent, metric, periodIndex)), - onFetchMore: periodIndex => dispatch(fetchMore(periodIndex)), - onSelect: component => dispatch(selectComponent(component)), - onSelectNext: component => dispatch(selectNext(component)), - onSelectPrevious: component => dispatch(selectPrevious(component)) - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(ListView); diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureCell.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureCell.js deleted file mode 100644 index ee236adbb74..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureCell.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Measure from '../../components/Measure'; - -const MeasureCell = ({ component, metric }) => { - return ( - - - - - - ); -}; - -export default MeasureCell; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js deleted file mode 100644 index f54768defb7..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 IconList from './../../components/IconList'; -import IconTree from './../../components/IconTree'; -import IconBubbles from './../../components/IconBubbles'; -import IconTreemap from './../../components/IconTreemap'; -import { hasBubbleChart, hasTreemap } from '../../utils'; -import { translate } from '../../../../helpers/l10n'; - -export default function MeasureDrilldown(props) { - const { children, component, metric, ...other } = props; - - const child = React.cloneElement(children, { ...other }); - - return ( -
    -
      - {component.qualifier !== 'DEV' && -
    • - - - {translate('component_measures.tab.list')} - -
    • } - -
    • - - - {translate('component_measures.tab.tree')} - -
    • - - {hasBubbleChart(metric.key) && -
    • - - - {translate('component_measures.tab.bubbles')} - -
    • } - - {hasTreemap(metric) && -
    • - - - {translate('component_measures.tab.treemap')} - -
    • } -
    - - {child} -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js deleted file mode 100644 index 0bbfe14681e..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js +++ /dev/null @@ -1,164 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 moment from 'moment'; -import ComponentsList from './ComponentsList'; -import ListHeader from './ListHeader'; -import Spinner from '../../components/Spinner'; -import SourceViewer from '../../../../components/SourceViewer/SourceViewer'; -import ListFooter from '../../../../components/controls/ListFooter'; - -export default class TreeView extends React.PureComponent { - componentDidMount() { - this.handleChangeBaseComponent(this.props.component); - } - - componentDidUpdate(nextProps) { - if (nextProps.metric !== this.props.metric) { - this.handleChangeBaseComponent(this.props.component); - } - - if (this.props.selected) { - this.scrollToViewer(); - } else if (this.scrollTop) { - this.scrollToStoredPosition(); - } - } - - scrollToViewer() { - const { container } = this.refs; - const top = container.getBoundingClientRect().top + window.scrollY - 95 - 10; - - // scroll only to top - if (window.scrollY > top) { - window.scrollTo(0, top); - } - } - - scrollToStoredPosition() { - window.scrollTo(0, this.scrollTop); - this.scrollTop = null; - } - - storeScrollPosition() { - this.scrollTop = window.scrollY; - } - - handleChangeBaseComponent(baseComponent) { - const { metric, onStart } = this.props; - const periodIndex = this.props.location.query.period || 1; - onStart(baseComponent, metric, Number(periodIndex)); - } - - handleFetchMore() { - this.props.onFetchMore(); - } - - changeSelected(selected) { - this.props.onSelect(selected); - } - - canDrilldown(component) { - return !['FIL', 'UTS'].includes(component.qualifier); - } - - handleClick(selected) { - if (this.canDrilldown(selected)) { - this.props.onDrilldown(selected); - } else { - this.storeScrollPosition(); - this.props.onSelect(selected); - } - } - - handleBreadcrumbClick(component) { - this.props.onUseBreadcrumbs(component, this.props.metric); - } - - render() { - const { - components, - metrics, - breadcrumbs, - metric, - leakPeriod, - selected, - total, - fetching - } = this.props; - const { onSelectNext, onSelectPrevious } = this.props; - - const selectedIndex = components.indexOf(selected); - const sourceViewerPeriod = metric.key.indexOf('new_') === 0 && !!leakPeriod ? leakPeriod : null; - const sourceViewerPeriodDate = - sourceViewerPeriod != null ? moment(sourceViewerPeriod.date).toDate() : null; - - const filterLine = - sourceViewerPeriodDate != null - ? line => { - if (line.scmDate) { - const scmDate = moment(line.scmDate).toDate(); - return scmDate >= sourceViewerPeriodDate; - } else { - return false; - } - } - : undefined; - - return ( -
    - - - {!selected && -
    - {!fetching || components.length !== 0 - ?
    - - -
    - : } -
    } - - {!!selected && -
    - -
    } -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeViewContainer.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeViewContainer.js deleted file mode 100644 index a7ae418251f..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeViewContainer.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import TreeView from './TreeView'; -import { - start, - drilldown, - useBreadcrumbs, - fetchMore, - selectComponent, - selectNext, - selectPrevious -} from '../../store/treeViewActions'; -import { - getMeasuresAppTreeComponents, - getMeasuresAppTreeBreadcrumbs, - getMeasuresAppTreeSelected, - getMeasuresAppTreeTotal, - getMeasuresAppTreePageIndex, - getMeasuresAppAllMetrics, - getMeasuresAppDetailsMetric, - isMeasuresAppFetching, - getMeasuresAppComponent -} from '../../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - components: getMeasuresAppTreeComponents(state), - breadcrumbs: getMeasuresAppTreeBreadcrumbs(state), - selected: getMeasuresAppTreeSelected(state), - total: getMeasuresAppTreeTotal(state), - pageIndex: getMeasuresAppTreePageIndex(state), - component: getMeasuresAppComponent(state), - metrics: getMeasuresAppAllMetrics(state), - metric: getMeasuresAppDetailsMetric(state), - fetching: isMeasuresAppFetching(state) - }; -}; - -const mapDispatchToProps = dispatch => { - return { - onStart: (rootComponent, metric, periodIndex) => - dispatch(start(rootComponent, metric, periodIndex)), - onDrilldown: component => dispatch(drilldown(component)), - onUseBreadcrumbs: component => dispatch(useBreadcrumbs(component)), - onFetchMore: () => dispatch(fetchMore()), - onSelect: component => dispatch(selectComponent(component)), - onSelectNext: component => dispatch(selectNext(component)), - onSelectPrevious: component => dispatch(selectPrevious(component)) - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(TreeView); diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/reducer.js b/server/sonar-web/src/main/js/apps/component-measures/details/reducer.js deleted file mode 100644 index ea68685093f..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/reducer.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { DISPLAY_HOME } from '../app/actions'; -import { REQUEST_MEASURE, RECEIVE_MEASURE } from './actions'; - -const initialState = { - metric: undefined, - secondaryMeasure: undefined, - measure: undefined, - periods: undefined -}; - -export default function appReducer(state = initialState, action = {}) { - switch (action.type) { - case DISPLAY_HOME: - return initialState; - case REQUEST_MEASURE: - return { ...state, metric: action.metric }; - case RECEIVE_MEASURE: - return { - ...state, - measure: action.measure, - secondaryMeasure: action.secondaryMeasure, - periods: action.periods - }; - default: - return state; - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js b/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js deleted file mode 100644 index 2516b8d9d02..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js +++ /dev/null @@ -1,223 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { scaleLinear, scaleOrdinal } from 'd3-scale'; -import Spinner from './../../components/Spinner'; -import { getLeakValue } from '../../utils'; -import { Treemap } from '../../../../components/charts/treemap'; -import { getChildren } from '../../../../api/components'; -import { formatMeasure } from '../../../../helpers/measures'; -import { - translate, - translateWithParameters, - getLocalizedMetricName -} from '../../../../helpers/l10n'; -import { getComponentUrl } from '../../../../helpers/urls'; -import Workspace from '../../../../components/workspace/main'; - -const HEIGHT = 500; - -export default class MeasureTreemap extends React.PureComponent { - state = { - fetching: true, - components: [], - breadcrumbs: [] - }; - - componentDidMount() { - const { component } = this.props; - - this.mounted = true; - this.fetchComponents(component.key); - } - - componentDidUpdate(nextProps) { - if (nextProps.metric !== this.props.metric) { - this.fetchComponents(this.props.component.key); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchComponents(componentKey) { - const { metric } = this.props; - const metrics = ['ncloc', metric.key]; - const options = { - s: 'metric', - metricSort: 'ncloc', - asc: false - }; - - return getChildren(componentKey, metrics, options).then(r => { - const components = r.components.map(component => { - const measures = {}; - const key = component.refKey || component.key; - - component.measures.forEach(measure => { - const shouldUseLeak = measure.metric.indexOf('new_') === 0; - measures[measure.metric] = shouldUseLeak ? getLeakValue(measure) : measure.value; - }); - return { ...component, measures, key }; - }); - - this.setState({ - components, - fetching: false - }); - }); - } - - getTooltip(component) { - const { metric } = this.props; - - let inner = [ - component.name, - `${translate('metric.ncloc.name')}: ${formatMeasure(component.measures['ncloc'], 'INT')}` - ]; - - const colorMeasure = component.measures[metric.key]; - const formatted = colorMeasure != null ? formatMeasure(colorMeasure, metric.type) : '—'; - inner.push(`${getLocalizedMetricName(metric)}: ${formatted}`); - inner = inner.join('
    '); - return `
    ${inner}
    `; - } - getPercentColorScale(metric) { - const color = scaleLinear().domain([0, 25, 50, 75, 100]); - color.range( - metric.direction === 1 - ? ['#d4333f', '#ed7d20', '#eabe06', '#b0d513', '#00aa00'] - : ['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f'] - ); - return color; - } - getRatingColorScale() { - return scaleLinear() - .domain([1, 2, 3, 4, 5]) - .range(['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f']); - } - getLevelColorScale() { - return scaleOrdinal() - .domain(['ERROR', 'WARN', 'OK', 'NONE']) - .range(['#d4333f', '#ed7d20', '#00aa00', '#b4b4b4']); - } - getScale() { - const { metric } = this.props; - if (metric.type === 'LEVEL') { - return this.getLevelColorScale(); - } - if (metric.type === 'RATING') { - return this.getRatingColorScale(); - } - return this.getPercentColorScale(metric); - } - handleRectangleClick(node) { - const isFile = node.qualifier === 'FIL' || node.qualifier === 'UTS'; - if (isFile) { - Workspace.openComponent({ key: node.key }); - return; - } - this.fetchComponents(node.key).then(() => { - let nextBreadcrumbs = [...this.state.breadcrumbs]; - const index = this.state.breadcrumbs.findIndex(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() { - const { component } = this.props; - this.fetchComponents(component.key).then(() => { - this.setState({ breadcrumbs: [] }); - }); - } - renderTreemap() { - const { metric } = this.props; - const colorScale = this.getScale(); - const items = this.state.components - .filter(component => component.measures['ncloc']) - .map(component => { - const colorMeasure = component.measures[metric.key]; - return { - id: component.id, - key: component.key, - name: component.name, - qualifier: component.qualifier, - size: component.measures['ncloc'], - color: colorMeasure != null ? colorScale(colorMeasure) : '#777', - tooltip: this.getTooltip(component), - label: component.name, - link: getComponentUrl(component.key) - }; - }); - return ( - true} - onRectangleClick={this.handleRectangleClick.bind(this)} - onReset={this.handleReset.bind(this)} - /> - ); - } - render() { - const { metric } = this.props; - const { fetching } = this.state; - if (fetching) { - return ( -
    -
    - -
    -
    - ); - } - return ( -
    -
      -
    • - {translateWithParameters( - 'component_measures.legend.color_x', - getLocalizedMetricName(metric) - )} -
    • -
    • - {translateWithParameters( - 'component_measures.legend.size_x', - translate('metric.ncloc.name') - )} -
    • -
    - {this.renderTreemap()} -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemapContainer.js b/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemapContainer.js deleted file mode 100644 index 5a3e26d98d4..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemapContainer.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import MeasureTreemap from './MeasureTreemap'; -import { - getMeasuresAppDetailsMetric, - getMeasuresAppComponent -} from '../../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - component: getMeasuresAppComponent(state), - metric: getMeasuresAppDetailsMetric(state) - }; -}; - -const mapDispatchToProps = () => { - return {}; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(MeasureTreemap); diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js deleted file mode 100644 index ab69f4baab3..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 AllMeasuresDomain from './AllMeasuresDomain'; -import { getLeakPeriodLabel } from '../../../helpers/periods'; - -export default function AllMeasures(props) { - const { component, domains, periods } = props; - const leakPeriodLabel = getLeakPeriodLabel(periods); - - return ( -
      - {domains.map(domain => - - )} -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresContainer.js b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresContainer.js deleted file mode 100644 index 5ec9cc79ab8..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresContainer.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import AllMeasures from './AllMeasures'; -import { - getMeasuresAppHomeDomains, - getMeasuresAppHomePeriods, - getMeasuresAppComponent -} from '../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - component: getMeasuresAppComponent(state), - domains: getMeasuresAppHomeDomains(state), - periods: getMeasuresAppHomePeriods(state) - }; -}; - -export default connect(mapStateToProps)(AllMeasures); diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js deleted file mode 100644 index 1111a362a9c..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 PropTypes from 'prop-types'; -import HomeMeasuresList from './HomeMeasuresList'; -import { getLocalizedMetricDomain } from '../../../helpers/l10n'; - -export default function AllMeasuresDomain(props) { - const { domain, component, displayHeader } = props; - - return ( -
  • - {displayHeader && -
    -

    - {getLocalizedMetricDomain(domain.name)} -

    -
    } - - -
  • - ); -} - -AllMeasuresDomain.defaultProps = { - displayHeader: true -}; - -AllMeasuresDomain.propTypes = { - displayHeader: PropTypes.bool -}; diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js b/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js deleted file mode 100644 index 22343bc704e..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 HomeMeasuresList from './HomeMeasuresList'; -import MeasureBubbleChartContainer from '../components/bubbleChart/MeasureBubbleChartContainer'; -import { hasBubbleChart } from '../utils'; - -export default function DomainMeasures(props) { - const { component, domains } = props; - const { domainName } = props.params; - const domain = domains.find(d => d.name === domainName); - - return ( -
    - - - {hasBubbleChart(domainName) && } -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasuresContainer.js b/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasuresContainer.js deleted file mode 100644 index c442bfca57c..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasuresContainer.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import DomainMeasures from './DomainMeasures'; -import { - getMeasuresAppHomeDomains, - getMeasuresAppHomePeriods, - getMeasuresAppComponent -} from '../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - component: getMeasuresAppComponent(state), - domains: getMeasuresAppHomeDomains(state), - periods: getMeasuresAppHomePeriods(state) - }; -}; - -export default connect(mapStateToProps)(DomainMeasures); diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/Home.js b/server/sonar-web/src/main/js/apps/component-measures/home/Home.js deleted file mode 100644 index b81be299a02..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/Home.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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, IndexLink } from 'react-router'; -import LeakPeriodLegend from '../components/LeakPeriodLegend'; -import { getLeakPeriod } from '../../../helpers/periods'; -import { translate, getLocalizedMetricDomain } from '../../../helpers/l10n'; - -export default class Home extends React.PureComponent { - componentDidMount() { - document.querySelector('html').classList.add('dashboard-page'); - this.props.onDisplay(); - this.props.fetchMeasures(); - } - - componentWillUnmount() { - document.querySelector('html').classList.remove('dashboard-page'); - } - - render() { - const { component, domains, periods } = this.props; - - if (domains == null) { - return null; - } - - const leakPeriod = getLeakPeriod(periods); - - return ( -
    -
    - - - {leakPeriod != null && } -
    - -
    - {this.props.children} -
    -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/HomeContainer.js b/server/sonar-web/src/main/js/apps/component-measures/home/HomeContainer.js deleted file mode 100644 index 0605a3aec58..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/HomeContainer.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { connect } from 'react-redux'; -import Home from './Home'; -import { fetchMeasures } from './actions'; -import { displayHome } from '../app/actions'; -import { - getMeasuresAppHomeDomains, - getMeasuresAppHomePeriods, - getMeasuresAppComponent -} from '../../../store/rootReducer'; - -const mapStateToProps = state => { - return { - component: getMeasuresAppComponent(state), - domains: getMeasuresAppHomeDomains(state), - periods: getMeasuresAppHomePeriods(state) - }; -}; - -const mapDispatchToProps = dispatch => { - return { - onDisplay: () => dispatch(displayHome()), - fetchMeasures: () => dispatch(fetchMeasures()) - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(Home); diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/HomeMeasuresList.js b/server/sonar-web/src/main/js/apps/component-measures/home/HomeMeasuresList.js deleted file mode 100644 index 7d700666a8f..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/HomeMeasuresList.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { partition, sortBy } from 'lodash'; -import MeasuresList from './MeasuresList'; -import { domains } from '../config/domains'; -import { getLocalizedMetricName } from '../../../helpers/l10n'; - -function sortMeasures(measures, order) { - const [known, unknown] = partition(measures, measure => order.includes(measure.metric.key)); - return [ - ...sortBy(known, measure => order.indexOf(measure.metric.key)), - ...sortBy(unknown, measure => getLocalizedMetricName(measure.metric)) - ]; -} - -function filterIssuesMeasures(measures) { - const BANNED_MEASURES = [ - 'blocker_violations', - 'new_blocker_violations', - 'critical_violations', - 'new_critical_violations', - 'major_violations', - 'new_major_violations', - 'minor_violations', - 'new_minor_violations', - 'info_violations', - 'new_info_violations' - ]; - return measures.filter(measure => !BANNED_MEASURES.includes(measure.metric.key)); -} - -const HomeMeasuresList = ({ domain, component }) => { - const { measures, name } = domain; - const config = domains[name] || {}; - - const filteredMeasures = filterIssuesMeasures(measures); - - const configMain = config.main || []; - const [mainMeasures, otherMeasures] = partition(filteredMeasures, measure => - configMain.includes(measure.metric.key) - ); - - const configOrder = config.order || []; - const sortedMainMeasures = sortMeasures(mainMeasures, configOrder); - const sortedOtherMeasures = sortMeasures(otherMeasures, configOrder); - - return ( -
    - {sortedMainMeasures.length > 0 && - } - - {sortedOtherMeasures.length > 0 && - } -
    - ); -}; - -export default HomeMeasuresList; diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/MeasureListValue.js b/server/sonar-web/src/main/js/apps/component-measures/home/MeasureListValue.js deleted file mode 100644 index da121fc6995..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/MeasureListValue.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 Measure from '../components/Measure'; -import { isDiffMetric } from '../../../helpers/measures'; - -const MeasureListValue = ({ measure }) => { - const { metric } = measure; - - if (isDiffMetric(metric.key)) { - return ( -
    - -
    - ); - } - - return ( -
    - -
    - ); -}; - -export default MeasureListValue; diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/MeasuresList.js b/server/sonar-web/src/main/js/apps/component-measures/home/MeasuresList.js deleted file mode 100644 index 3ba27f5785b..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/MeasuresList.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 MeasureListValue from './MeasureListValue'; -import { getLocalizedMetricName } from '../../../helpers/l10n'; -import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; - -const MeasuresList = ({ measures, component, className = 'domain-measures' }) => { - return ( -
      - {measures.map(measure => -
    • - -
      - - - {getLocalizedMetricName(measure.metric)} - -
      - - - -
    • - )} -
    - ); -}; - -export default MeasuresList; diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/actions.js b/server/sonar-web/src/main/js/apps/component-measures/home/actions.js deleted file mode 100644 index 6ae4585b20b..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/actions.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { startFetching, stopFetching } from '../store/statusActions'; -import { getMeasuresAndMeta } from '../../../api/measures'; -import { getLeakValue } from '../utils'; -import { getMeasuresAppComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer'; - -export const RECEIVE_MEASURES = 'measuresApp/home/RECEIVE_MEASURES'; - -export function receiveMeasures(measures, periods) { - return { type: RECEIVE_MEASURES, measures, periods }; -} - -function banQualityGate(component, measures) { - let newMeasures = [...measures]; - - if (!['VW', 'SVW', 'APP'].includes(component.qualifier)) { - newMeasures = newMeasures.filter(measure => measure.metric !== 'alert_status'); - } - - if (component.qualifier === 'APP') { - newMeasures = newMeasures.filter( - measure => - measure.metric !== 'releasability_rating' && measure.metric !== 'releasability_effort' - ); - } - - return newMeasures; -} - -export function fetchMeasures() { - return (dispatch, getState) => { - dispatch(startFetching()); - - const state = getState(); - const component = getMeasuresAppComponent(state); - const metrics = getMeasuresAppAllMetrics(state); - - 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 => { - const measures = banQualityGate(component, r.component.measures) - .map(measure => { - const metric = metrics.find(metric => metric.key === measure.metric); - const leak = getLeakValue(measure); - return { ...measure, metric, leak }; - }) - .filter(measure => { - const hasValue = measure.value != null; - const hasLeakValue = measure.leak != null; - return hasValue || hasLeakValue; - }); - - const newBugs = measures.find(measure => measure.metric.key === 'new_bugs'); - - const applicationPeriods = newBugs ? [{ index: 1 }] : []; - const periods = component.qualifier === 'APP' ? applicationPeriods : r.periods; - - dispatch(receiveMeasures(measures, periods)); - dispatch(stopFetching()); - }); - }; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/reducer.js b/server/sonar-web/src/main/js/apps/component-measures/home/reducer.js deleted file mode 100644 index e75222924f6..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/home/reducer.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { groupBy, partition, sortBy, toPairs } from 'lodash'; -import { RECEIVE_MEASURES } from './actions'; -import { getLocalizedMetricName } from '../../../helpers/l10n'; - -const initialState = { - measures: undefined, - domains: undefined, - periods: undefined -}; - -function groupByDomains(measures) { - const KNOWN_DOMAINS = [ - 'Releasability', - 'Reliability', - 'Security', - 'Maintainability', - 'Coverage', - 'Duplications', - 'Size', - 'Complexity' - ]; - - const domains = sortBy( - toPairs(groupBy(measures, measure => measure.metric.domain)).map(r => { - const [name, measures] = r; - const sortedMeasures = sortBy(measures, measure => getLocalizedMetricName(measure.metric)); - - return { name, measures: sortedMeasures }; - }), - 'name' - ); - const [knownDomains, unknownDomains] = partition(domains, domain => - KNOWN_DOMAINS.includes(domain.name) - ); - return [ - ...sortBy(knownDomains, domain => KNOWN_DOMAINS.indexOf(domain.name)), - ...sortBy(unknownDomains, domain => domain.name) - ]; -} - -export default function(state = initialState, action = {}) { - switch (action.type) { - case RECEIVE_MEASURES: - return { - ...state, - measures: action.measures, - domains: groupByDomains(action.measures), - periods: action.periods - }; - default: - return state; - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/hooks.js b/server/sonar-web/src/main/js/apps/component-measures/hooks.js deleted file mode 100644 index 001948f1b59..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/hooks.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { isDiffMetric } from '../../helpers/measures'; - -export function checkHistoryExistence(nextState, replace) { - const { metricKey } = nextState.params; - - if (isDiffMetric(metricKey)) { - replace({ - pathname: metricKey, - query: nextState.location.query - }); - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/routes.js b/server/sonar-web/src/main/js/apps/component-measures/routes.js deleted file mode 100644 index 0c4f83db5e1..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/routes.js +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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. - */ -const routes = [ - { - getComponent(_, callback) { - import('./app/AppContainer').then(i => callback(null, i.default)); - }, - childRoutes: [ - { - getComponent(_, callback) { - import('./home/HomeContainer').then(i => callback(null, i.default)); - }, - childRoutes: [ - { - getIndexRoute(_, callback) { - import('./home/AllMeasuresContainer').then(i => - callback(null, { component: i.default }) - ); - } - }, - { - path: 'domain/:domainName', - getComponent(_, callback) { - import('./home/DomainMeasuresContainer').then(i => callback(null, i.default)); - } - } - ] - }, - { - path: 'metric/:metricKey', - getComponent(_, callback) { - import('./details/MeasureDetailsContainer').then(i => callback(null, i.default)); - }, - childRoutes: [ - { - indexRoute: { - onEnter(nextState, replace) { - const { params, location } = nextState; - replace({ - pathname: `/component_measures/metric/${params.metricKey}/list`, - query: location.query - }); - } - } - }, - { - path: 'list', - getComponent(_, callback) { - import('./details/drilldown/ListViewContainer').then(i => callback(null, i.default)); - } - }, - { - path: 'tree', - getComponent(_, callback) { - import('./details/drilldown/TreeViewContainer').then(i => callback(null, i.default)); - } - }, - { - path: 'history', - onEnter(nextState, replace) { - replace({ - pathname: '/project/activity', - query: { - id: nextState.location.query.id, - graph: 'custom', - custom_metrics: nextState.params.metricKey - } - }); - } - }, - { - path: 'treemap', - getComponent(_, callback) { - import('./details/treemap/MeasureTreemapContainer').then(i => - callback(null, i.default) - ); - } - } - ] - } - ] - } -]; - -export default routes; diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/listViewActions.js b/server/sonar-web/src/main/js/apps/component-measures/store/listViewActions.js deleted file mode 100644 index 2bbd93dfa28..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/listViewActions.js +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { getComponentTree } from '../../../api/components'; -import { enhanceWithMeasure } from '../utils'; -import { startFetching, stopFetching } from './statusActions'; -import complementary from '../config/complementary'; -import { getMeasuresAppList } from '../../../store/rootReducer'; - -export const UPDATE_STORE = 'measuresApp/drilldown/list/UPDATE_STORE'; - -function updateStore(state) { - return { type: UPDATE_STORE, state }; -} - -function getComplementary(metric) { - const comp = complementary[metric] || []; - return [metric, ...comp]; -} - -function makeRequest(baseComponent, metric, options, periodIndex = 1) { - const asc = metric.direction === 1; - const ps = 100; - const finalOptions = { asc, ps, metricSortFilter: 'withMeasuresOnly' }; - - if (metric.key.indexOf('new_') === 0) { - Object.assign(options, { - s: 'metricPeriod,name', - metricSort: metric.key, - metricPeriodSort: periodIndex - }); - } else { - Object.assign(options, { - s: 'metric,name', - metricSort: metric.key - }); - } - - Object.assign(finalOptions, options); - return getComponentTree('leaves', baseComponent.key, getComplementary(metric.key), finalOptions); -} - -function fetchLeaves(baseComponent, metric, pageIndex = 1, periodIndex = 1) { - const options = { p: pageIndex }; - - return makeRequest(baseComponent, metric, options, periodIndex).then(r => { - const nextComponents = enhanceWithMeasure(r.components, metric.key, periodIndex); - - return { - components: nextComponents, - pageIndex: r.paging.pageIndex, - total: r.paging.total - }; - }); -} - -/** - * Fetch the first page of components for a given base component - * @param baseComponent - * @param metric - * @param periodIndex - */ -export function fetchList(baseComponent, metric, periodIndex = 1) { - return (dispatch, getState) => { - const list = getMeasuresAppList(getState()); - if (list.baseComponent === baseComponent && list.metric === metric) { - return Promise.resolve(); - } - - dispatch(startFetching()); - return fetchLeaves(baseComponent, metric, 1, periodIndex).then(r => { - dispatch( - updateStore({ - ...r, - baseComponent, - metric - }) - ); - dispatch(stopFetching()); - }); - }; -} - -export function fetchMore(periodIndex) { - return (dispatch, getState) => { - const { baseComponent, metric, pageIndex, components } = getMeasuresAppList(getState()); - dispatch(startFetching()); - return fetchLeaves(baseComponent, metric, pageIndex + 1, periodIndex).then(r => { - const nextComponents = [...components, ...r.components]; - dispatch(updateStore({ ...r, components: nextComponents })); - dispatch(stopFetching()); - }); - }; -} - -/** - * Select specified component from the list - * @param component A component to select - */ -export function selectComponent(component) { - return dispatch => { - dispatch(updateStore({ selected: component })); - }; -} - -/** - * Select next element from the list of components - */ -export function selectNext() { - return (dispatch, getState) => { - const { components, selected } = getMeasuresAppList(getState()); - const selectedIndex = components.indexOf(selected); - if (selectedIndex < components.length - 1) { - const nextSelected = components[selectedIndex + 1]; - dispatch(selectComponent(nextSelected)); - } - }; -} - -/** - * Select previous element from the list of components - */ -export function selectPrevious() { - return (dispatch, getState) => { - const { components, selected } = getMeasuresAppList(getState()); - const selectedIndex = components.indexOf(selected); - if (selectedIndex > 0) { - const nextSelected = components[selectedIndex - 1]; - dispatch(selectComponent(nextSelected)); - } - }; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/listViewReducer.js b/server/sonar-web/src/main/js/apps/component-measures/store/listViewReducer.js deleted file mode 100644 index ee8f9aeaef8..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/listViewReducer.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { DISPLAY_HOME } from './../app/actions'; -import { UPDATE_STORE } from './listViewActions'; - -const initialState = { - components: [], - total: 0 -}; - -export default function drilldownReducer(state = initialState, action = {}) { - switch (action.type) { - case DISPLAY_HOME: - return initialState; - case UPDATE_STORE: - return { ...state, ...action.state }; - default: - return state; - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/rootReducer.js b/server/sonar-web/src/main/js/apps/component-measures/store/rootReducer.js deleted file mode 100644 index 079a7e45693..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/rootReducer.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { combineReducers } from 'redux'; -import appReducer from './../app/reducer'; -import statusReducer from './statusReducer'; -import homeReducer from '../home/reducer'; -import detailsReducer from '../details/reducer'; -import listViewReducer from './listViewReducer'; -import treeViewReducer from './treeViewReducer'; - -export default combineReducers({ - app: appReducer, - home: homeReducer, - details: detailsReducer, - list: listViewReducer, - tree: treeViewReducer, - status: statusReducer -}); - -export const getComponent = state => state.app.component; - -export const getAllMetrics = state => state.app.metrics; - -export const getDetailsMetric = state => state.details.metric; - -export const getDetailsMeasure = state => state.details.measure; - -export const getDetailsSecondaryMeasure = state => state.details.secondaryMeasure; - -export const getDetailsPeriods = state => state.details.periods; - -export const isFetching = state => state.status.fetching; - -export const getList = state => state.list; - -export const getListComponents = state => state.list.components; - -export const getListSelected = state => state.list.selected; - -export const getListTotal = state => state.list.total; - -export const getListPageIndex = state => state.list.pageIndex; - -export const getTree = state => state.tree; - -export const getTreeComponents = state => state.tree.components; - -export const getTreeBreadcrumbs = state => state.tree.breadcrumbs; - -export const getTreeSelected = state => state.tree.selected; - -export const getTreeTotal = state => state.tree.total; - -export const getTreePageIndex = state => state.tree.pageIndex; - -export const getHomeDomains = state => state.home.domains; - -export const getHomePeriods = state => state.home.periods; diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/statusActions.js b/server/sonar-web/src/main/js/apps/component-measures/store/statusActions.js deleted file mode 100644 index d07feba64d7..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/statusActions.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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. - */ -export const START_FETCHING = 'measuresApp/status/START_FETCHING'; -export const STOP_FETCHING = 'measuresApp/status/STOP_FETCHING'; - -export function startFetching() { - return { type: START_FETCHING }; -} - -export function stopFetching() { - return { type: STOP_FETCHING }; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/statusReducer.js b/server/sonar-web/src/main/js/apps/component-measures/store/statusReducer.js deleted file mode 100644 index 1a993be900a..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/statusReducer.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { START_FETCHING, STOP_FETCHING } from './statusActions'; - -const initialState = { - fetching: false -}; - -export default function drilldownReducer(state = initialState, action = {}) { - switch (action.type) { - case START_FETCHING: - return { ...state, fetching: true }; - case STOP_FETCHING: - return { ...state, fetching: false }; - default: - return state; - } -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/treeViewActions.js b/server/sonar-web/src/main/js/apps/component-measures/store/treeViewActions.js deleted file mode 100644 index 34fffe1b8cd..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/treeViewActions.js +++ /dev/null @@ -1,277 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { initial } from 'lodash'; -import { getComponentTree } from '../../../api/components'; -import { enhanceWithMeasure } from '../utils'; -import { startFetching, stopFetching } from './statusActions'; -import complementary from '../config/complementary'; -import { getMeasuresAppTree } from '../../../store/rootReducer'; - -/* - * Actions - */ - -export const UPDATE_STORE = 'measuresApp/drilldown/tree/UPDATE_STORE'; -export const INIT = 'measuresApp/drilldown/tree/INIT'; - -/* - * Action Creators - */ - -/** - * Internal - * Update store - * @param state - * @returns {{type: string, state: *}} - */ -function updateStore(state) { - return { type: UPDATE_STORE, state }; -} - -/** - * Init tree view drilldown for the given root component and given metric - * @param rootComponent - * @param metric - * @param periodIndex - * @returns {{type: string, rootComponent: *, metric: *}} - */ -function init(rootComponent, metric, periodIndex = 1) { - return { type: INIT, rootComponent, metric, periodIndex }; -} - -/* - * Workflow - */ - -function getComplementary(metric) { - const comp = complementary[metric] || []; - return [metric, ...comp]; -} - -function makeRequest(rootComponent, baseComponent, metric, options, periodIndex = 1) { - const asc = metric.direction === 1; - const ps = 100; - const finalOptions = { asc, ps, metricSortFilter: 'withMeasuresOnly' }; - - if (metric.key.indexOf('new_') === 0) { - Object.assign(options, { - s: 'metricPeriod,name', - metricSort: metric.key, - metricPeriodSort: periodIndex - }); - } else { - Object.assign(options, { - s: 'metric,name', - metricSort: metric.key - }); - } - - if (rootComponent.qualifier === 'DEV' && baseComponent.qualifier !== 'DEV') { - Object.assign(options, { developerId: rootComponent.id }); - } - - Object.assign(finalOptions, options); - - const finalKey = baseComponent.refKey || baseComponent.key; - - return getComponentTree('children', finalKey, getComplementary(metric.key), finalOptions); -} - -function fetchComponents(rootComponent, baseComponent, metric, pageIndex = 1, periodIndex = 1) { - const options = { p: pageIndex }; - - return makeRequest(rootComponent, baseComponent, metric, options, periodIndex).then(r => { - const nextComponents = enhanceWithMeasure(r.components, metric.key, periodIndex); - - return { - baseComponent, - components: nextComponents, - pageIndex: r.paging.pageIndex, - total: r.paging.total - }; - }); -} - -/** - * Fetch the first page of components for a given base component - * @param baseComponent - */ -function fetchList(baseComponent) { - return (dispatch, getState) => { - const { metric, periodIndex, rootComponent } = getMeasuresAppTree(getState()); - - dispatch(startFetching()); - return fetchComponents(rootComponent, baseComponent, metric, 1, periodIndex).then(r => { - dispatch( - updateStore({ - ...r, - baseComponent, - breadcrumbs: [baseComponent] - }) - ); - dispatch(stopFetching()); - }); - }; -} - -/** - * Init tree view with root component and metric. - * Fetch the first page of components if needed. - * @param rootComponent - * @param metric - * @param periodIndex - * @returns {function()} - */ -export function start(rootComponent, metric, periodIndex = 1) { - return (dispatch, getState) => { - const tree = getMeasuresAppTree(getState()); - if (rootComponent === tree.rootComponent && metric === tree.metric) { - return Promise.resolve(); - } - - dispatch(init(rootComponent, metric, periodIndex)); - dispatch(fetchList(rootComponent)); - }; -} - -/** - * Drilldown to the component - * @param component - */ -export function drilldown(component) { - return (dispatch, getState) => { - const { metric, rootComponent, breadcrumbs, periodIndex } = getMeasuresAppTree(getState()); - dispatch(startFetching()); - return fetchComponents(rootComponent, component, metric, 1, periodIndex).then(r => { - dispatch( - updateStore({ - ...r, - breadcrumbs: [...breadcrumbs, component], - selected: undefined - }) - ); - dispatch(stopFetching()); - }); - }; -} - -/** - * Go up using breadcrumbs - * @param component - */ -export function useBreadcrumbs(component) { - return (dispatch, getState) => { - const { metric, rootComponent, breadcrumbs, periodIndex } = getMeasuresAppTree(getState()); - const index = breadcrumbs.indexOf(component); - dispatch(startFetching()); - return fetchComponents(rootComponent, component, metric, 1, periodIndex).then(r => { - dispatch( - updateStore({ - ...r, - breadcrumbs: breadcrumbs.slice(0, index + 1), - selected: undefined - }) - ); - dispatch(stopFetching()); - }); - }; -} - -export function fetchMore() { - return (dispatch, getState) => { - const { - rootComponent, - baseComponent, - metric, - pageIndex, - components, - periodIndex - } = getMeasuresAppTree(getState()); - dispatch(startFetching()); - return fetchComponents( - rootComponent, - baseComponent, - metric, - pageIndex + 1, - periodIndex - ).then(r => { - const nextComponents = [...components, ...r.components]; - dispatch(updateStore({ ...r, components: nextComponents })); - dispatch(stopFetching()); - }); - }; -} - -/** - * Select given component from the list - * @param component - */ -export function selectComponent(component) { - return (dispatch, getState) => { - const { breadcrumbs } = getMeasuresAppTree(getState()); - const nextBreadcrumbs = [...breadcrumbs, component]; - dispatch( - updateStore({ - selected: component, - breadcrumbs: nextBreadcrumbs - }) - ); - }; -} - -/** - * Select next element from the list of components - */ -export function selectNext() { - return (dispatch, getState) => { - const { components, selected, breadcrumbs } = getMeasuresAppTree(getState()); - const selectedIndex = components.indexOf(selected); - if (selectedIndex < components.length - 1) { - const nextSelected = components[selectedIndex + 1]; - const nextBreadcrumbs = [...initial(breadcrumbs), nextSelected]; - dispatch( - updateStore({ - selected: nextSelected, - breadcrumbs: nextBreadcrumbs - }) - ); - } - }; -} - -/** - * Select previous element from the list of components - */ -export function selectPrevious() { - return (dispatch, getState) => { - const { components, selected, breadcrumbs } = getMeasuresAppTree(getState()); - const selectedIndex = components.indexOf(selected); - if (selectedIndex > 0) { - const nextSelected = components[selectedIndex - 1]; - const nextBreadcrumbs = [...initial(breadcrumbs), nextSelected]; - dispatch( - updateStore({ - selected: nextSelected, - breadcrumbs: nextBreadcrumbs - }) - ); - } - }; -} diff --git a/server/sonar-web/src/main/js/apps/component-measures/store/treeViewReducer.js b/server/sonar-web/src/main/js/apps/component-measures/store/treeViewReducer.js deleted file mode 100644 index 71050fdad57..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/store/treeViewReducer.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 { pick } from 'lodash'; -import { DISPLAY_HOME } from './../app/actions'; -import { UPDATE_STORE, INIT } from './treeViewActions'; - -const initialState = { - components: [], - breadcrumbs: [], - total: 0 -}; - -export default function drilldownReducer(state = initialState, action = {}) { - switch (action.type) { - case DISPLAY_HOME: - return initialState; - case UPDATE_STORE: - return { ...state, ...action.state }; - case INIT: - return { ...state, ...pick(action, ['rootComponent', 'metric', 'periodIndex']) }; - default: - return state; - } -} 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 deleted file mode 100644 index b72fcf31384..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/styles.css +++ /dev/null @@ -1,404 +0,0 @@ -.home-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - margin-bottom: 20px; -} - -.measures-domains { -} - -.measures-domains > li { - margin-bottom: 20px; -} - -.measures-domains > li > div { - border: 1px solid #e6e6e6; - background-color: #fff; -} - -.measures-domains-leak-header { - line-height: 22px; - padding: 0 10px; - border: 1px solid #eae3c7; - background-color: #fbf3d5; - white-space: nowrap; -} - -.main-domain-measures { - display: flex; - flex-wrap: wrap; - justify-content: space-around; - float: left; - width: 480px; - margin-right: 60px; -} - -.main-domain-measures > li { - padding: 12px 0; -} - -.main-domain-measures > li > a { - display: flex; - flex-direction: column-reverse; - width: 160px; - border: none; - text-align: center; -} - -.main-domain-measures .domain-measures-value { - height: 40px; - box-sizing: border-box; - color: #444; - font-size: 30px; - font-weight: 300; -} - -.main-domain-measures .domain-measures-value .rating, -.measure-details-value .rating { - vertical-align: top; - width: 40px; - height: 40px; - line-height: 40px; - border-radius: 40px; - font-size: 24px; -} - -.main-domain-measures .domain-measures-name { - margin-top: 8px; -} - -.main-domain-measures .domain-measures-name > span:last-child { - border-bottom: 1px solid #cae3f2; -} - -.main-domain-measures .domain-measures-leak { - margin: 0 20px; - border: 1px solid #eae3c7; - background-color: #fbf3d5; -} - -.domain-measures { - overflow: hidden; - line-height: 1.4; -} - -.domain-measures > li > a { - display: flex; - justify-content: space-between; - border: none; -} - -.domain-measures > li:nth-child(odd) > a { - background-color: #f8f8f8; -} - -.domain-measures > li > a:hover { - background-color: #ecf6fe !important; -} - -.domain-measures .domain-measures-name, -.domain-measures .domain-measures-value { - padding: 7px 10px; - box-sizing: border-box; -} - -.domain-measures .domain-measures-name { - width: calc(100% - 160px); - line-height: 24px; -} - -.domain-measures .domain-measures-name > span { - border-bottom: 1px solid #cae3f2; -} - -.domain-measures .domain-measures-value { - min-width: 80px; - color: #444; - text-align: right; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.domain-measures .domain-measures-leak { - background-color: #fbf3d5; - transition: background-color 0.3s ease; -} - -.domain-measures .domain-measures > li:nth-child(odd) .domain-measures-leak { - background-color: #f5eed0; -} - -.measure-details { - margin-top: 10px; -} - -.measure-details-header { - position: relative; - margin-top: 10px; - margin-bottom: 30px; -} - -.measure-details-metric, -.measure-details-value { -} - -.measure-details-metric { - display: inline-block; - margin-bottom: 10px; -} - -.measure-details-metric > a:not(.button) { - border: none; - color: #444; -} - -.measure-details-metric > a:not(.button):hover { - color: #236a97; -} - -.measure-details-value { - font-size: 24px; -} - -.measure-details-value-absolute { - display: inline-block; - vertical-align: middle; - padding: 5px 0; - font-weight: 300; -} - -.measure-details-value-leak { - display: inline-block; - vertical-align: middle; - padding: 4px 10px; - border: 1px solid #eae3c7; - background-color: #fbf3d5; - font-weight: 300; -} - -.measure-details-value-absolute + .measure-details-value-leak { - margin-left: 20px; -} - -.measure-details-secondary { - display: inline-block; - vertical-align: middle; - width: 260px; - margin-left: 20px; -} - -.measure-details-drilldown { - margin-top: 20px; -} - -.measure-details-drilldown-mode { - display: flex; - margin-bottom: 10px; - border-bottom: 1px solid #e6e6e6; -} - -.measure-details-drilldown-mode > li { - margin-bottom: -1px; -} - -.measure-details-drilldown-mode > li + li { - margin-left: 2px; -} - -.measure-details-drilldown-mode > li > a { - display: inline-block; - padding: 5px 10px; - border-bottom: 2px solid transparent; - color: #444; -} - -.measure-details-drilldown-mode > li > a:hover, -.measure-details-drilldown-mode > li > a.active { - border-bottom-color: #4b9fd5; -} - -.measure-details-drilldown-mode > li > a.active .measure-tab-icon path { - fill: #4b9fd5; -} - -.measure-details-plain-list { -} - -.measure-details-components { - width: 300px; - padding: 10px; - box-sizing: border-box; -} - -.measure-details-components > li > a { - display: flex; - padding-top: 5px; - padding-bottom: 5px; - border: none; - color: #444; -} - -.measure-details-components > li > a:hover, -.measure-details-components > li > a.selected { - background-color: #cae3f2 !important; -} - -.measure-details-component-name, -.measure-details-component-value { - padding-right: 10px; - box-sizing: border-box; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.measure-details-component-name { - width: calc(100% - 60px); - padding-left: 10px; -} - -.measure-details-component-value { - width: 60px; - text-align: right; -} - -.measure-details-viewer { - min-height: 100vh; -} - -.measure-details-viewer-header { - margin-bottom: 10px; - line-height: 24px; -} - -.measure-details-viewer-header .button-group { - vertical-align: top; -} - -.measure-details-header-container { - display: inline-block; - line-height: 16px; - padding-right: 10px; -} - -.measure-tab-icon { - display: inline-block; - width: 14px; - height: 14px; - margin-right: 6px; -} - -.measure-tab-icon path { - fill: #aeaeae; - transition: fill 0.3s ease; -} - -.measure-details-components-up-icon path { - fill: #aeaeae; -} - -.measure-details-history { - padding: 10px 0; -} - -.measure-details-bubble-chart { - position: relative; - margin: 40px 0 10px; - padding: 30px 0 30px 60px; - border: 1px solid #e6e6e6; - background-color: #fff; -} - -.measure-details-bubble-chart-axis { - position: absolute; - color: #777; - font-size: 12px; -} - -.measure-details-bubble-chart-axis.x { - left: 50%; - bottom: 10px; - width: 500px; - margin-left: -250px; - text-align: center; -} - -.measure-details-bubble-chart-axis.y { - top: 50%; - left: -20px; - transform: rotate(-90deg); -} - -.measure-details-bubble-chart-axis.size { - left: 50%; - top: 10px; - width: 500px; - margin-left: -250px; - text-align: center; -} - -.measure-details-treemap { - margin: 20px 0; -} - -.measure-details-treemap-legend { - margin-bottom: 10px; -} - -.component-measures-breadcrumbs { - display: flex; - flex-wrap: wrap; -} - -.component-measures-breadcrumbs > li { - padding: 5px 5px 3px; -} - -.component-measures-breadcrumbs > li:first-child { - padding-left: 0; -} - -.component-measures-breadcrumbs > li::after { - position: relative; - top: -1px; - padding-left: 10px; - color: #777; - font-size: 11px; - content: ">"; -} - -.component-measures-breadcrumbs > li:last-child::after { - display: none; -} - -.home-measures-list { - border: 1px solid #e6e6e6; - background-color: #fff; -} - -.nav-pills > ul { - display: flex; - flex-wrap: wrap; -} - -.nav-pills > ul > li > a { - display: inline-block; - vertical-align: middle; - padding: 3px 10px; - border: 1px solid transparent; - border-radius: 24px; - color: #236a97; - transition: none; -} - -.nav-pills > ul > li > a:hover { - border-color: #236a97; -} - -.nav-pills > ul > li.active > a, -.nav-pills > ul > li > a.active { - background-color: #236a97; - color: #fff; -} 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 deleted file mode 100644 index 20595c7ab18..00000000000 --- a/server/sonar-web/src/main/js/apps/component-measures/utils.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info 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 bubbles from './config/bubbles'; -import { - formatMeasure, - formatMeasureVariation, - getRatingTooltip as nextGetRatingTooltip, - isDiffMetric -} from '../../helpers/measures'; - -export function getLeakValue(measure, periodIndex = 1) { - if (!measure) { - return null; - } - - const period = measure.periods - ? measure.periods.find(period => period.index === periodIndex) - : null; - - return period ? period.value : null; -} - -export function getSingleMeasureValue(measures) { - if (!measures || !measures.length) { - return null; - } - - return measures[0].value; -} - -export function getSingleLeakValue(measures, periodIndex = 1) { - if (!measures || !measures.length) { - return null; - } - - const measure = measures[0]; - - const period = measure.periods - ? measure.periods.find(period => period.index === periodIndex) - : null; - - return period ? period.value : null; -} - -export function formatLeak(value, metric, options) { - if (isDiffMetric(metric.key)) { - return formatMeasure(value, metric.type, options); - } else { - return formatMeasureVariation(value, metric.type, options); - } -} - -export function enhanceWithLeak(measures, periodIndex = 1) { - function enhanceSingle(measure) { - return { ...measure, leak: getLeakValue(measure, periodIndex) }; - } - - if (Array.isArray(measures)) { - return measures.map(enhanceSingle); - } else { - return enhanceSingle(measures); - } -} - -export function enhanceWithSingleMeasure(components, periodIndex = 1) { - return components.map(component => { - return { - ...component, - value: getSingleMeasureValue(component.measures), - leak: getSingleLeakValue(component.measures, periodIndex) - }; - }); -} - -export function enhanceWithMeasure(components, metric, periodIndex = 1) { - return components.map(component => { - const measuresWithLeak = enhanceWithLeak(component.measures, periodIndex); - const measure = measuresWithLeak.find(measure => measure.metric === metric); - const value = measure ? measure.value : null; - const leak = measure ? measure.leak : null; - return { ...component, value, leak, measures: measuresWithLeak }; - }); -} - -export function hasBubbleChart(domainName) { - return !!bubbles[domainName]; -} - -export function hasTreemap(metric) { - return ['PERCENT', 'RATING', 'LEVEL'].indexOf(metric.type) !== -1; -} - -export function filterOutEmptyMeasures(components) { - return components.filter(component => component.value !== null || component.leak !== null); -} - -export function getRatingTooltip(metricKey, value) { - const finalMetricKey = metricKey.indexOf('new_') === 0 ? metricKey.substr(4) : metricKey; - const KNOWN_RATINGS = ['sqale_rating', 'reliability_rating', 'security_rating']; - if (KNOWN_RATINGS.includes(finalMetricKey)) { - return nextGetRatingTooltip(finalMetricKey, value); - } - return null; -} diff --git a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js index ec90cafe30f..25af253cd1c 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js +++ b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js @@ -31,11 +31,11 @@ class BugsAndVulnerabilities extends React.PureComponent { renderHeader() { const { component } = this.props; const bugsDomainUrl = { - pathname: '/component_measures/domain/Reliability', + pathname: '/component_measures_old/domain/Reliability', query: { id: component.key } }; const vulnerabilitiesDomainUrl = { - pathname: '/component_measures/domain/Security', + pathname: '/component_measures_old/domain/Security', query: { id: component.key } }; diff --git a/server/sonar-web/src/main/js/apps/overview/main/enhance.js b/server/sonar-web/src/main/js/apps/overview/main/enhance.js index b5599d43c00..1deeeab4ddb 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/enhance.js +++ b/server/sonar-web/src/main/js/apps/overview/main/enhance.js @@ -56,7 +56,7 @@ export default function enhance(ComposedComponent) { renderHeader = (domain, label) => { const { component } = this.props; const domainUrl = { - pathname: `/component_measures/domain/${domain}`, + pathname: `/component_measures_old/domain/${domain}`, query: { id: component.key } }; diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js index 47ff132eadd..905f06b0d68 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js @@ -22,7 +22,7 @@ import React from 'react'; import classNames from 'classnames'; import { Link } from 'react-router'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; -import Measure from '../../component-measures/components/Measure'; +import Measure from '../../component-measures-old/components/Measure'; import { getPeriodValue, isDiffMetric, formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import { getComponentIssuesUrl } from '../../../helpers/urls'; diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js index 2675af49875..4189c2e1a64 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeakMeasures.js @@ -19,7 +19,7 @@ */ //@flow import React from 'react'; -import Measure from '../../component-measures/components/Measure'; +import Measure from '../../component-measures-old/components/Measure'; import BugIcon from '../../../components/icons-components/BugIcon'; import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; import Rating from '../../../components/ui/Rating'; diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js index 7a1c8a31c6c..546b511eb0e 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverallMeasures.js @@ -20,7 +20,7 @@ //@flow import React from 'react'; import ProjectCardLanguages from './ProjectCardLanguages'; -import Measure from '../../component-measures/components/Measure'; +import Measure from '../../component-measures-old/components/Measure'; import Rating from '../../../components/ui/Rating'; import CoverageRating from '../../../components/ui/CoverageRating'; import DuplicationsRating from '../../../components/ui/DuplicationsRating'; diff --git a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.js b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.js index 0f5fb66e39a..c74c18a8b36 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.js +++ b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.js @@ -78,14 +78,14 @@ describe('#getComponentIssuesUrl', () => { describe('#getComponentDrilldownUrl', () => { it('should return component drilldown url', () => { expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC)).toEqual({ - pathname: '/component_measures/metric/' + METRIC, + pathname: '/component_measures_old/metric/' + METRIC, query: { id: SIMPLE_COMPONENT_KEY } }); }); it('should not encode component key', () => { expect(getComponentDrilldownUrl(COMPLEX_COMPONENT_KEY, METRIC)).toEqual({ - pathname: '/component_measures/metric/' + METRIC, + pathname: '/component_measures_old/metric/' + METRIC, query: { id: COMPLEX_COMPONENT_KEY } }); }); diff --git a/server/sonar-web/src/main/js/helpers/urls.js b/server/sonar-web/src/main/js/helpers/urls.js index 27c2ec6ee6c..84bf3e4fd63 100644 --- a/server/sonar-web/src/main/js/helpers/urls.js +++ b/server/sonar-web/src/main/js/helpers/urls.js @@ -63,7 +63,7 @@ export function getComponentIssuesUrlAsString(componentKey, query) { */ export function getComponentDrilldownUrl(componentKey, metric) { return { - pathname: `/component_measures/metric/${metric}`, + pathname: `/component_measures_old/metric/${metric}`, query: { id: componentKey } }; } diff --git a/server/sonar-web/src/main/js/store/rootReducer.js b/server/sonar-web/src/main/js/store/rootReducer.js index a0f81547c53..76355147ac9 100644 --- a/server/sonar-web/src/main/js/store/rootReducer.js +++ b/server/sonar-web/src/main/js/store/rootReducer.js @@ -28,7 +28,7 @@ import notifications, * as fromNotifications from './notifications/duck'; import organizations, * as fromOrganizations from './organizations/duck'; import organizationsMembers, * as fromOrganizationsMembers from './organizationsMembers/reducer'; import globalMessages, * as fromGlobalMessages from './globalMessages/duck'; -import measuresApp, * as fromMeasuresApp from '../apps/component-measures/store/rootReducer'; +import measuresApp, * as fromMeasuresApp from '../apps/component-measures-old/store/rootReducer'; import permissionsApp, * as fromPermissionsApp from '../apps/permissions/shared/store/rootReducer'; import projectAdminApp, * as fromProjectAdminApp from '../apps/project-admin/store/rootReducer'; import projectsApp, * as fromProjectsApp from '../apps/projects/store/reducer';