diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2017-08-24 16:50:13 +0200 |
---|---|---|
committer | Janos Gyerik <janos.gyerik@sonarsource.com> | 2017-09-12 11:34:51 +0200 |
commit | 28012dbeab2d6fc67b136c8c1f2e5c0fd88d3025 (patch) | |
tree | 44ca5f49888d46f94a47ddc664d1fe7406e4f2ae /server/sonar-web | |
parent | 84fb7ffe3889723aa29df14ebaf874f577aa2842 (diff) | |
download | sonarqube-28012dbeab2d6fc67b136c8c1f2e5c0fd88d3025.tar.gz sonarqube-28012dbeab2d6fc67b136c8c1f2e5c0fd88d3025.zip |
Different branches UI fixes (#2418)
Diffstat (limited to 'server/sonar-web')
42 files changed, 520 insertions, 262 deletions
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.js b/server/sonar-web/src/main/js/apps/component-measures/components/App.js index e6545eea8ea..a8f6908e215 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.js @@ -41,7 +41,7 @@ import '../style.css'; fetchMeasures: ( component: string, metricsKey: Array<string>, - branch: string | null + branch?: string ) => Promise<{ component: Component, measures: Array<MeasureEnhanced>, leakPeriod: ?Period }>, fetchMetrics: () => void, metrics: { [string]: Metric }, @@ -127,11 +127,7 @@ export default class App extends React.PureComponent { }); this.props.router.push({ pathname: this.props.location.pathname, - query: { - ...query, - branch: getBranchName(this.props.branch), - id: this.props.component.key - } + query: { ...query, branch: getBranchName(this.props.branch), id: this.props.component.key } }); }; @@ -164,7 +160,7 @@ export default class App extends React.PureComponent { {metric != null && <MeasureContentContainer - branch={branch} + branch={getBranchName(branch)} className="layout-page-main" currentUser={this.props.currentUser} rootComponent={component} @@ -180,7 +176,7 @@ export default class App extends React.PureComponent { {metric == null && hasBubbleChart(query.metric) && <MeasureOverviewContainer - branch={branch} + branch={getBranchName(branch)} className="layout-page-main" rootComponent={component} currentUser={this.props.currentUser} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js index 896d6870e23..c5a6a79434b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js @@ -50,7 +50,7 @@ function banQualityGate(component /*: Component */) /*: Array<Measure> */ { const fetchMeasures = ( component /*: string */, metricsKey /*: Array<string> */, - branch /*: string | null */ + branch /*: string | void */ ) => (dispatch, getState) => { if (metricsKey.length <= 0) { return Promise.resolve({ component: {}, measures: [], leakPeriod: null }); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js b/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js index 7de031dee8a..6fa80158a26 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.js @@ -22,12 +22,11 @@ import React from 'react'; import key from 'keymaster'; import Breadcrumb from './Breadcrumb'; import { getBreadcrumbs } from '../../../api/components'; -import { getBranchName } from '../../../helpers/branches'; /*:: import type { Component } from '../types'; */ /*:: type Props = {| backToFirst: boolean, - branch: {}, + branch?: string, className?: string, component: Component, handleSelect: string => void, @@ -85,7 +84,7 @@ export default class Breadcrumbs extends React.PureComponent { } return; } - getBreadcrumbs(component.key, getBranchName(branch)).then(breadcrumbs => { + getBreadcrumbs(component.key, branch).then(breadcrumbs => { if (this.mounted) { this.setState({ breadcrumbs }); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js index 64411b028c1..6824148b0ee 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js @@ -32,7 +32,6 @@ import TreeMapView from '../drilldown/TreeMapView'; import { getComponentTree } from '../../../api/components'; import { complementary } from '../config/complementary'; import { enhanceComponent, isFileType, isViewType } from '../utils'; -import { getBranchName } from '../../../helpers/branches'; import { getProjectUrl } from '../../../helpers/urls'; import { isDiffMetric } from '../../../helpers/measures'; import { parseDate } from '../../../helpers/dates'; @@ -44,7 +43,7 @@ import { parseDate } from '../../../helpers/dates'; // https://github.com/facebook/flow/issues/3147 // router: { push: ({ pathname: string, query?: RawQuery }) => void } /*:: type Props = {| - branch: {}, + branch?: string, className?: string, component: Component, currentUser: { isLoggedIn: boolean }, @@ -117,7 +116,7 @@ export default class MeasureContent extends React.PureComponent { const strategy = view === 'list' ? 'leaves' : 'children'; const metricKeys = [metric.key]; const opts /*: Object */ = { - branch: getBranchName(this.props.branch), + branch: this.props.branch, metricSortFilter: 'withMeasuresOnly' }; const isDiff = isDiffMetric(metric.key); @@ -241,11 +240,7 @@ export default class MeasureContent extends React.PureComponent { } return ( <div className="measure-details-viewer"> - <SourceViewer - branch={getBranchName(branch)} - component={component.key} - filterLine={filterLine} - /> + <SourceViewer branch={branch} component={component.key} filterLine={filterLine} /> </div> ); } @@ -336,6 +331,7 @@ export default class MeasureContent extends React.PureComponent { measure != null && <div className="layout-page-main-inner measure-details-content"> <MeasureHeader + branch={branch} component={component} components={this.state.components} handleSelect={this.props.updateSelected} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js index faf2ee60d5f..bddca5d26c3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureContentContainer.js @@ -20,21 +20,20 @@ // @flow import React from 'react'; import MeasureContent from './MeasureContent'; -import { getBranchName } from '../../../helpers/branches'; /*:: import type { Component, Period, Query } from '../types'; */ /*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: import type { RawQuery } from '../../../helpers/query'; */ /*:: type Props = {| - branch: {}, + branch?: string, className?: string, currentUser: { isLoggedIn: boolean }, rootComponent: Component, fetchMeasures: ( component: string, metricsKey: Array<string>, - branch: string | null + branch?: string ) => Promise<{ component: Component, measures: Array<MeasureEnhanced> }>, leakPeriod?: Period, metric: Metric, @@ -102,7 +101,7 @@ export default class MeasureContentContainer extends React.PureComponent { metricKeys.push('file_complexity_distribution'); } - fetchMeasures(selected || rootComponent.key, metricKeys, getBranchName(branch)).then( + fetchMeasures(selected || rootComponent.key, metricKeys, branch).then( ({ component, measures }) => { if (this.mounted) { const measure = measures.find(measure => measure.metric.key === metric.key); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js index 558495e853b..fe905f163e0 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureHeader.js @@ -35,6 +35,7 @@ import { isDiffMetric } from '../../../helpers/measures'; /*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ /*:: type Props = {| + branch?: string, component: Component, components: Array<Component>, leakPeriod?: Period, @@ -93,7 +94,7 @@ export default class MeasureHeader extends React.PureComponent { } render() { - const { component, components, leakPeriod, measure, secondaryMeasure } = this.props; + const { branch, component, components, leakPeriod, measure, secondaryMeasure } = this.props; const metric = measure.metric; const isDiff = isDiffMetric(metric.key); const hasHistory = !isDiff && ['TRK', 'VW', 'SVW', 'APP'].includes(component.qualifier); @@ -117,7 +118,7 @@ export default class MeasureHeader extends React.PureComponent { overlay={translate('component_measures.show_metric_history')}> <Link className="js-show-history spacer-left button button-small button-compact" - to={getComponentMeasureHistory(component.key, metric.key)}> + to={getComponentMeasureHistory(component.key, metric.key, branch)}> <HistoryIcon /> </Link> </Tooltip>} diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js index 8543558ebc4..213fdf050fa 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverview.js @@ -26,13 +26,12 @@ import MeasureFavoriteContainer from './MeasureFavoriteContainer'; import PageActions from './PageActions'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; import { getComponentLeaves } from '../../../api/components'; -import { getBranchName } from '../../../helpers/branches'; import { enhanceComponent, getBubbleMetrics, isFileType } from '../utils'; /*:: import type { Component, ComponentEnhanced, Paging, Period } from '../types'; */ /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| - branch: {}, + branch?: string, className?: string, component: Component, currentUser: { isLoggedIn: boolean }, @@ -90,7 +89,7 @@ export default class MeasureOverview extends React.PureComponent { metricsKey.push(colors.map(metric => metric.key)); } const options = { - branch: getBranchName(branch), + branch, s: 'metric', metricSort: size.key, asc: false, @@ -119,7 +118,7 @@ export default class MeasureOverview extends React.PureComponent { if (isFileType(component)) { return ( <div className="measure-details-viewer"> - <SourceViewer branch={getBranchName(branch)} component={component.key} /> + <SourceViewer branch={branch} component={component.key} /> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js index 02c07128e45..61f3e58b1bf 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureOverviewContainer.js @@ -21,7 +21,6 @@ import React from 'react'; import MeasureOverview from './MeasureOverview'; import { getComponentShow } from '../../../api/components'; -import { getBranchName } from '../../../helpers/branches'; import { getProjectUrl } from '../../../helpers/urls'; import { isViewType } from '../utils'; /*:: import type { Component, Period, Query } from '../types'; */ @@ -29,7 +28,7 @@ import { isViewType } from '../utils'; /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| - branch: {}, + branch?: string, className?: string, rootComponent: Component, currentUser: { isLoggedIn: boolean }, @@ -89,7 +88,7 @@ export default class MeasureOverviewContainer extends React.PureComponent { return; } this.updateLoading({ component: true }); - getComponentShow(selected, getBranchName(branch)).then( + getComponentShow(selected, branch).then( ({ component }) => { if (this.mounted) { this.setState({ component }); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.js b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.js index 7df3340638f..b990be2ff47 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/App-test.js @@ -39,6 +39,7 @@ const METRICS = { }; const PROPS = { + branch: { isMain: true, name: 'master' }, component: { key: 'foo' }, location: { pathname: '/component_measures', query: { metric: 'coverage' } }, fetchMeasures: () => {}, diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.js b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.js index 46734ad83ca..73619312a76 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureHeader-test.js @@ -76,6 +76,10 @@ it('should render correctly for leak', () => { expect(shallow(<MeasureHeader {...PROPS} measure={LEAK_MEASURE} />)).toMatchSnapshot(); }); +it('should render with branch', () => { + expect(shallow(<MeasureHeader branch="feature" {...PROPS} />).find('Link')).toMatchSnapshot(); +}); + it('should display secondary measure too', () => { const wrapper = shallow(<MeasureHeader {...PROPS} secondaryMeasure={SECONDARY} />); expect(wrapper.find('LanguageDistribution')).toHaveLength(1); diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.js.snap b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.js.snap index e9ff866768e..52e73da3bc3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.js.snap +++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/MeasureHeader-test.js.snap @@ -257,3 +257,24 @@ exports[`should render correctly for leak 1`] = ` </div> </div> `; + +exports[`should render with branch 1`] = ` +<Link + className="js-show-history spacer-left button button-small button-compact" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/activity", + "query": Object { + "branch": "feature", + "custom_metrics": "reliability_rating", + "graph": "custom", + "id": "foo", + }, + } + } +> + <IconHistory /> +</Link> +`; diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js index a8f042e7bf0..1f4dc6dc78b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js @@ -20,13 +20,12 @@ // @flow import React from 'react'; import QualifierIcon from '../../../components/icons-components/QualifierIcon'; -import { getBranchName } from '../../../helpers/branches'; import { splitPath } from '../../../helpers/path'; import { getComponentUrl } from '../../../helpers/urls'; /*:: import type { ComponentEnhanced } from '../types'; */ /*:: type Props = { - branch: {}, + branch?: string, component: ComponentEnhanced, onClick: string => void }; */ @@ -76,14 +75,14 @@ export default class ComponentCell extends React.PureComponent { ? <a id={'component-measures-component-link-' + component.key} className="link-no-underline" - href={getComponentUrl(component.key, getBranchName(branch))} + href={getComponentUrl(component.key, branch)} onClick={this.handleClick}> {this.renderInner()} </a> : <a id={'component-measures-component-link-' + component.key} className="link-no-underline" - href={getComponentUrl(component.refKey, getBranchName(branch))}> + href={getComponentUrl(component.refKey, branch)}> <span className="big-spacer-right"> <i className="icon-detach" /> </span> diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js index 53175f19e06..18d307848e4 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js @@ -27,7 +27,7 @@ import { getLocalizedMetricName } from '../../../helpers/l10n'; /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| - branch: {}, + branch?: string, components: Array<ComponentEnhanced>, onClick: string => void, metric: Metric, diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js index 9e2a1e7ed3d..841ff84a60c 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js @@ -26,7 +26,7 @@ import MeasureCell from './MeasureCell'; /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| - branch: {}, + branch?: string, component: ComponentEnhanced, isSelected: boolean, onClick: string => void, diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js index 6fe0bb181b0..f7f26fe9e26 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js @@ -28,7 +28,7 @@ import { scrollToElement } from '../../../helpers/scrolling'; /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| - branch: {}, + branch?: string, components: Array<ComponentEnhanced>, fetchMore: () => void, handleSelect: string => void, diff --git a/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js b/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js index 9d1b3ff6d1a..f055ef7e68b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js +++ b/server/sonar-web/src/main/js/apps/component-measures/drilldown/TreeMapView.js @@ -26,7 +26,6 @@ import ColorGradientLegend from '../../../components/charts/ColorGradientLegend' import EmptyResult from './EmptyResult'; import QualifierIcon from '../../../components/icons-components/QualifierIcon'; import TreeMap from '../../../components/charts/TreeMap'; -import { getBranchName } from '../../../helpers/branches'; import { translate, translateWithParameters, getLocalizedMetricName } from '../../../helpers/l10n'; import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; import { getComponentUrl } from '../../../helpers/urls'; @@ -35,7 +34,7 @@ import { getComponentUrl } from '../../../helpers/urls'; /*:: import type { TreeMapItem } from '../../../components/charts/TreeMap'; */ /*:: type Props = {| - branch: {}, + branch?: string, components: Array<ComponentEnhanced>, handleSelect: string => void, metric: Metric @@ -95,7 +94,7 @@ export default class TreeMapView extends React.PureComponent { sizeValue ), label: component.name, - link: getComponentUrl(component.refKey || component.key, getBranchName(branch)) + link: getComponentUrl(component.refKey || component.key, branch) }; }) .filter(Boolean); diff --git a/server/sonar-web/src/main/js/apps/component/components/App.tsx b/server/sonar-web/src/main/js/apps/component/components/App.tsx index a1fb59f825c..e1943d4fb70 100644 --- a/server/sonar-web/src/main/js/apps/component/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/component/components/App.tsx @@ -23,6 +23,7 @@ import SourceViewer from '../../../components/SourceViewer/SourceViewer'; interface Props { location: { query: { + branch?: string; id: string; line?: string; }; @@ -44,7 +45,7 @@ export default class App extends React.PureComponent<Props> { }; render() { - const { id, line } = this.props.location.query; + const { branch, id, line } = this.props.location.query; const finalLine = line != null ? Number(line) : null; @@ -52,6 +53,7 @@ export default class App extends React.PureComponent<Props> { <div className="page page-limited"> <SourceViewer aroundLine={finalLine} + branch={branch} component={id} highlightedLine={finalLine} onLoaded={this.scrollToLine} diff --git a/server/sonar-web/src/main/js/apps/component/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/component/components/__tests__/App-test.tsx new file mode 100644 index 00000000000..6d9b1681536 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component/components/__tests__/App-test.tsx @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import App from '../App'; + +it('renders', () => { + expect( + shallow(<App location={{ query: { branch: 'b', id: 'foo', line: '7' } }} />) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/component/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/component/components/__tests__/__snapshots__/App-test.tsx.snap new file mode 100644 index 00000000000..1cb5c653533 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/component/components/__tests__/__snapshots__/App-test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` +<div + className="page page-limited" +> + <Connect(SourceViewerBase) + aroundLine={7} + branch="b" + component="foo" + highlightedLine={7} + onLoaded={[Function]} + /> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.js b/server/sonar-web/src/main/js/apps/issues/components/App.js index 87191bace08..486ee33abc0 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/App.js +++ b/server/sonar-web/src/main/js/apps/issues/components/App.js @@ -797,7 +797,7 @@ export default class App extends React.PureComponent { } renderList() { - const { component, currentUser, organization } = this.props; + const { branch, component, currentUser, organization } = this.props; const { issues, openIssue, paging } = this.state; const selectedIndex = this.getSelectedIndex(); const selectedIssue = selectedIndex != null ? issues[selectedIndex] : null; @@ -810,6 +810,7 @@ export default class App extends React.PureComponent { <div> {paging.total > 0 && <IssuesList + branch={getBranchName(branch)} checked={this.state.checked} component={component} issues={issues} @@ -872,6 +873,7 @@ export default class App extends React.PureComponent { {openIssue != null ? <div className="pull-left width-60"> <ComponentBreadcrumbs + branch={getBranchName(this.props.branch)} component={component} issue={openIssue} organization={this.props.organization} diff --git a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js deleted file mode 100644 index b8a770b5e0e..00000000000 --- a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.js +++ /dev/null @@ -1,78 +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 { Link } from 'react-router'; -import Organization from '../../../components/shared/Organization'; -import { collapsePath, limitComponentName } from '../../../helpers/path'; -import { getProjectUrl } from '../../../helpers/urls'; -/*:: import type { Component } from '../utils'; */ - -/*:: -type Props = { - component?: Component, - issue: Object, - organization?: { key: string } -}; -*/ - -export default class ComponentBreadcrumbs extends React.PureComponent { - /*:: props: Props; */ - - render() { - const { component, issue, organization } = this.props; - - const displayOrganization = - !organization && (component == null || ['VW', 'SVW'].includes(component.qualifier)); - const displayProject = - component == null || !['TRK', 'BRC', 'DIR'].includes(component.qualifier); - const displaySubProject = component == null || !['BRC', 'DIR'].includes(component.qualifier); - - return ( - <div className="component-name text-ellipsis"> - {displayOrganization && - <Organization linkClassName="link-no-underline" organizationKey={issue.organization} />} - - {displayProject && - <span title={issue.projectName}> - <Link to={getProjectUrl(issue.project)} className="link-no-underline"> - {limitComponentName(issue.projectName)} - </Link> - <span className="slash-separator" /> - </span>} - - {displaySubProject && - issue.subProject != null && - <span title={issue.subProjectName}> - <Link to={getProjectUrl(issue.subProject)} className="link-no-underline"> - {limitComponentName(issue.subProjectName)} - </Link> - <span className="slash-separator" /> - </span>} - - <Link to={getProjectUrl(issue.component)} className="link-no-underline"> - <span title={issue.componentLongName}> - {collapsePath(issue.componentLongName)} - </span> - </Link> - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.tsx b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.tsx new file mode 100644 index 00000000000..e02644dbda0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.tsx @@ -0,0 +1,78 @@ +/* + * 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 * as React from 'react'; +import { Link } from 'react-router'; +import Organization from '../../../components/shared/Organization'; +import { collapsePath, limitComponentName } from '../../../helpers/path'; +import { getProjectUrl } from '../../../helpers/urls'; +import { Component } from '../../../app/types'; + +interface Props { + branch?: string; + component?: Component; + issue: { + component: string; + componentLongName: string; + organization: string; + project: string; + projectName: string; + subProject?: string; + subProjectName?: string; + }; + organization?: { key: string }; +} + +export default function ComponentBreadcrumbs({ branch, component, issue, organization }: Props) { + const displayOrganization = + !organization && (component == null || ['VW', 'SVW'].includes(component.qualifier)); + const displayProject = component == null || !['TRK', 'BRC', 'DIR'].includes(component.qualifier); + const displaySubProject = component == null || !['BRC', 'DIR'].includes(component.qualifier); + + return ( + <div className="component-name text-ellipsis"> + {displayOrganization && + <Organization linkClassName="link-no-underline" organizationKey={issue.organization} />} + + {displayProject && + <span title={issue.projectName}> + <Link to={getProjectUrl(issue.project, branch)} className="link-no-underline"> + {limitComponentName(issue.projectName)} + </Link> + <span className="slash-separator" /> + </span>} + + {displaySubProject && + issue.subProject != undefined && + issue.subProjectName != undefined && + <span title={issue.subProjectName}> + <Link to={getProjectUrl(issue.subProject, branch)} className="link-no-underline"> + {limitComponentName(issue.subProjectName)} + </Link> + <span className="slash-separator" /> + </span>} + + <Link to={getProjectUrl(issue.component, branch)} className="link-no-underline"> + <span title={issue.componentLongName}> + {collapsePath(issue.componentLongName)} + </span> + </Link> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js b/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js index 8a405e94c33..e2228919ba9 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesList.js @@ -25,6 +25,7 @@ import ListItem from './ListItem'; /*:: type Props = {| + branch?: string, checked: Array<string>, component?: Component, issues: Array<Issue>, @@ -43,12 +44,13 @@ export default class IssuesList extends React.PureComponent { /*:: props: Props; */ render() { - const { checked, component, issues, openPopup, selectedIssue } = this.props; + const { branch, checked, component, issues, openPopup, selectedIssue } = this.props; return ( <div> {issues.map((issue, index) => <ListItem + branch={branch} checked={checked.includes(issue.key)} component={component} key={issue.key} diff --git a/server/sonar-web/src/main/js/apps/issues/components/ListItem.js b/server/sonar-web/src/main/js/apps/issues/components/ListItem.js index 20bd23dfb9f..c053d0fd2c7 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/ListItem.js +++ b/server/sonar-web/src/main/js/apps/issues/components/ListItem.js @@ -26,6 +26,7 @@ import Issue from '../../../components/issue/Issue'; /*:: type Props = {| + branch?: string, checked: boolean, component?: Component, issue: IssueType, @@ -88,7 +89,7 @@ export default class ListItem extends React.PureComponent { }; render() { - const { component, issue, previousIssue } = this.props; + const { branch, component, issue, previousIssue } = this.props; const displayComponent = previousIssue == null || previousIssue.component !== issue.component; @@ -97,6 +98,7 @@ export default class ListItem extends React.PureComponent { {displayComponent && <div className="issues-workspace-list-component"> <ComponentBreadcrumbs + branch={branch} component={component} issue={this.props.issue} organization={this.props.organization} diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/ComponentBreadcrumbs-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/ComponentBreadcrumbs-test.tsx new file mode 100644 index 00000000000..84a4635446f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/ComponentBreadcrumbs-test.tsx @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import ComponentBreadcrumbs from '../ComponentBreadcrumbs'; + +const baseIssue = { + component: 'comp', + componentLongName: 'comp-name', + organization: 'org', + project: 'proj', + projectName: 'proj-name' +}; + +it('renders', () => { + expect(shallow(<ComponentBreadcrumbs issue={baseIssue} />)).toMatchSnapshot(); +}); + +it('renders with sub-project', () => { + const issue = { ...baseIssue, subProject: 'sub-proj', subProjectName: 'sub-proj-name' }; + expect(shallow(<ComponentBreadcrumbs issue={issue} />)).toMatchSnapshot(); +}); + +it('renders with branch', () => { + const issue = { ...baseIssue, subProject: 'sub-proj', subProjectName: 'sub-proj-name' }; + expect(shallow(<ComponentBreadcrumbs branch="feature" issue={issue} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/ComponentBreadcrumbs-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/ComponentBreadcrumbs-test.tsx.snap new file mode 100644 index 00000000000..3861f4a0780 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/ComponentBreadcrumbs-test.tsx.snap @@ -0,0 +1,209 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` +<div + className="component-name text-ellipsis" +> + <Connect(Organization) + linkClassName="link-no-underline" + organizationKey="org" + /> + <span + title="proj-name" + > + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": undefined, + "id": "proj", + }, + } + } + > + proj-name + </Link> + <span + className="slash-separator" + /> + </span> + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": undefined, + "id": "comp", + }, + } + } + > + <span + title="comp-name" + > + comp-name + </span> + </Link> +</div> +`; + +exports[`renders with branch 1`] = ` +<div + className="component-name text-ellipsis" +> + <Connect(Organization) + linkClassName="link-no-underline" + organizationKey="org" + /> + <span + title="proj-name" + > + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": "feature", + "id": "proj", + }, + } + } + > + proj-name + </Link> + <span + className="slash-separator" + /> + </span> + <span + title="sub-proj-name" + > + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": "feature", + "id": "sub-proj", + }, + } + } + > + sub-proj-name + </Link> + <span + className="slash-separator" + /> + </span> + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": "feature", + "id": "comp", + }, + } + } + > + <span + title="comp-name" + > + comp-name + </span> + </Link> +</div> +`; + +exports[`renders with sub-project 1`] = ` +<div + className="component-name text-ellipsis" +> + <Connect(Organization) + linkClassName="link-no-underline" + organizationKey="org" + /> + <span + title="proj-name" + > + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": undefined, + "id": "proj", + }, + } + } + > + proj-name + </Link> + <span + className="slash-separator" + /> + </span> + <span + title="sub-proj-name" + > + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": undefined, + "id": "sub-proj", + }, + } + } + > + sub-proj-name + </Link> + <span + className="slash-separator" + /> + </span> + <Link + className="link-no-underline" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": undefined, + "id": "comp", + }, + } + } + > + <span + title="comp-name" + > + comp-name + </span> + </Link> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/overview/components/App.js b/server/sonar-web/src/main/js/apps/overview/components/App.js index 794aae352ca..cd5deb6d6e7 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/App.js +++ b/server/sonar-web/src/main/js/apps/overview/components/App.js @@ -22,7 +22,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import OverviewApp from './OverviewApp'; import EmptyOverview from './EmptyOverview'; -import { isShortLivingBranch } from '../../../helpers/branches'; +import { getBranchName, isShortLivingBranch } from '../../../helpers/branches'; import { getProjectBranchUrl } from '../../../helpers/urls'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; @@ -66,16 +66,16 @@ export default class App extends React.PureComponent { } render() { - if (this.isPortfolio() || isShortLivingBranch(this.props.branch)) { + const { branch, component } = this.props; + + if (this.isPortfolio() || isShortLivingBranch(branch)) { return null; } - const { component } = this.props; - if (['FIL', 'UTS'].includes(component.qualifier)) { return ( <div className="page page-limited"> - <SourceViewer component={component.key} /> + <SourceViewer branch={getBranchName(branch)} component={component.key} /> </div> ); } @@ -86,7 +86,7 @@ export default class App extends React.PureComponent { return ( <OverviewApp - branch={this.props.branch} + branch={branch} component={component} onComponentChange={this.props.onComponentChange} /> diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js index 907bc8c95c1..8dfcd55c171 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js @@ -76,7 +76,10 @@ export default class OverviewApp extends React.PureComponent { } componentDidUpdate(prevProps /*: Props */) { - if (this.props.component.key !== prevProps.component.key || this.props.branch !== prevProps.branch) { + if ( + this.props.component.key !== prevProps.component.key || + this.props.branch !== prevProps.branch + ) { this.loadMeasures().then(this.loadHistory); } } @@ -163,7 +166,15 @@ export default class OverviewApp extends React.PureComponent { const leakPeriod = component.qualifier === 'APP' ? this.getApplicationLeakPeriod() : getLeakPeriod(periods); - const domainProps = { branch, component, measures, leakPeriod, history, historyStartDate }; + const branchName = getBranchName(branch); + const domainProps = { + branch: branchName, + component, + measures, + leakPeriod, + history, + historyStartDate + }; return ( <div className="page page-limited"> @@ -171,7 +182,7 @@ export default class OverviewApp extends React.PureComponent { <div className="overview-main page-main"> {component.qualifier === 'APP' ? <ApplicationQualityGate component={component} /> - : <QualityGate branch={branch} component={component} measures={measures} />} + : <QualityGate branch={branchName} component={component} measures={measures} />} <div className="overview-domains-list"> <BugsAndVulnerabilities {...domainProps} /> @@ -183,7 +194,7 @@ export default class OverviewApp extends React.PureComponent { <div className="page-sidebar-fixed"> <Meta - branch={branch} + branch={branchName} component={component} history={history} measures={measures} diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js b/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js index a39a89c9c99..f2f2f34a1c4 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js @@ -24,13 +24,19 @@ import OverviewApp from '../OverviewApp'; import EmptyOverview from '../EmptyOverview'; it('should render OverviewApp', () => { - const component = { id: 'id', analysisDate: '2016-01-01' }; + const component = { key: 'foo', analysisDate: '2016-01-01' }; const output = shallow(<App component={component} />); expect(output.type()).toBe(OverviewApp); }); it('should render EmptyOverview', () => { - const component = { id: 'id' }; + const component = { key: 'foo' }; const output = shallow(<App component={component} />); expect(output.type()).toBe(EmptyOverview); }); + +it('renders SourceViewer with branch', () => { + const branch = { isMain: false, name: 'b' }; + const component = { key: 'foo', qualifier: 'FIL' }; + expect(shallow(<App branch={branch} component={component} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/App-test.js.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/App-test.js.snap new file mode 100644 index 00000000000..7f7335f6860 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/App-test.js.snap @@ -0,0 +1,12 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders SourceViewer with branch 1`] = ` +<div + className="page page-limited" +> + <Connect(SourceViewerBase) + branch="b" + component="foo" + /> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js b/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js index 937dd653952..9bb67dd44cc 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js +++ b/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js @@ -24,14 +24,13 @@ import Analysis from './Analysis'; import PreviewGraph from './PreviewGraph'; import { getMetrics } from '../../../api/metrics'; import { getProjectActivity } from '../../../api/projectActivity'; -import { getBranchName } from '../../../helpers/branches'; import { translate } from '../../../helpers/l10n'; /*:: import type { Analysis as AnalysisType } from '../../projectActivity/types'; */ /*:: import type { History, Metric } from '../types'; */ /*:: type Props = { - branch: {}, + branch?: string, history: ?History, project: string, qualifier: string, @@ -73,7 +72,7 @@ export default class AnalysesList extends React.PureComponent { this.setState({ loading: true }); Promise.all([ getProjectActivity({ - branch: getBranchName(this.props.branch), + branch: this.props.branch, project: this.props.project, ps: PAGE_SIZE }), @@ -130,7 +129,7 @@ export default class AnalysesList extends React.PureComponent { <Link to={{ pathname: '/project/activity', - query: { id: this.props.project, branch: getBranchName(this.props.branch) } + query: { id: this.props.project, branch: this.props.branch } }}> {translate('show_more')} </Link> diff --git a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js index 0c52daceb1a..d732c531419 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js +++ b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js @@ -31,7 +31,6 @@ import { hasHistoryDataValue, splitSeriesInGraphs } from '../../projectActivity/utils'; -import { getBranchName } from '../../../helpers/branches'; import { getCustomGraph, getGraph } from '../../../helpers/storage'; import { formatMeasure, getShortType } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; @@ -40,7 +39,7 @@ import { translate } from '../../../helpers/l10n'; /*:: type Props = { - branch: {}, + branch?: string, history: ?History, metrics: Array<Metric>, project: string, @@ -141,7 +140,7 @@ export default class PreviewGraph extends React.PureComponent { handleClick = () => { this.props.router.push({ pathname: '/project/activity', - query: { id: this.props.project, branch: getBranchName(this.props.branch) } + query: { id: this.props.project, branch: this.props.branch } }); }; 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 05d2f89d658..5f4cf9fbb8f 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 @@ -26,14 +26,12 @@ import BugIcon from '../../../components/icons-components/BugIcon'; import LeakPeriodLegend from '../components/LeakPeriodLegend'; import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon'; import { getMetricName } from '../helpers/metrics'; -import { getBranchName } from '../../../helpers/branches'; import { getComponentDrilldownUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; class BugsAndVulnerabilities extends React.PureComponent { renderHeader() { const { branch, component } = this.props; - const branchName = getBranchName(branch); return ( <div className="overview-card-header"> @@ -43,7 +41,7 @@ class BugsAndVulnerabilities extends React.PureComponent { </span> <Link className="button button-small button-compact spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component.key, 'Reliability', branchName)}> + to={getComponentDrilldownUrl(component.key, 'Reliability', branch)}> <BubblesIcon size={14} /> </Link> <span className="big-spacer-left"> @@ -51,7 +49,7 @@ class BugsAndVulnerabilities extends React.PureComponent { </span> <Link className="button button-small button-compact spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component.key, 'Security', branchName)}> + to={getComponentDrilldownUrl(component.key, 'Security', branch)}> <BubblesIcon size={14} /> </Link> </div> diff --git a/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js b/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js index a9ab208ea17..176c7e1c1d1 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js +++ b/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js @@ -28,7 +28,6 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; import { getComponentIssuesUrl } from '../../../helpers/urls'; import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; -import { getBranchName } from '../../../helpers/branches'; class CodeSmells extends React.PureComponent { renderHeader() { @@ -39,12 +38,7 @@ class CodeSmells extends React.PureComponent { const { branch, measures, component } = this.props; const measure = measures.find(measure => measure.metric.key === metric); const value = this.props.getValue(measure); - const params = { - branch: getBranchName(branch), - resolved: 'false', - facetMode: 'effort', - types: type - }; + const params = { branch, resolved: 'false', facetMode: 'effort', types: type }; if (isDiffMetric(metric)) { Object.assign(params, { sinceLeakPeriod: 'true' }); diff --git a/server/sonar-web/src/main/js/apps/overview/main/Coverage.js b/server/sonar-web/src/main/js/apps/overview/main/Coverage.js index 90cac0105d4..c7c01b91a1a 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/Coverage.js +++ b/server/sonar-web/src/main/js/apps/overview/main/Coverage.js @@ -20,7 +20,6 @@ import React from 'react'; import enhance from './enhance'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; -import { getBranchName } from '../../../helpers/branches'; import { getMetricName } from '../helpers/metrics'; import { formatMeasure, getPeriodValue } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; @@ -68,7 +67,7 @@ class Coverage extends React.PureComponent { <div className="display-inline-block text-middle"> <div className="overview-domain-measure-value"> - <DrilldownLink branch={getBranchName(branch)} component={component.key} metric={metric}> + <DrilldownLink branch={branch} component={component.key} metric={metric}> <span className="js-overview-main-coverage"> {formatMeasure(coverage, 'PERCENT')} </span> @@ -86,7 +85,6 @@ class Coverage extends React.PureComponent { renderNewCoverage() { const { branch, component, leakPeriod } = this.props; - const branchName = getBranchName(branch); const newCoverageMeasure = this.getNewCoverageMeasure(); const newLinesToCover = this.getNewLinesToCover(); @@ -101,7 +99,7 @@ class Coverage extends React.PureComponent { newCoverageValue != null ? <div> <DrilldownLink - branch={branchName} + branch={branch} component={component.key} metric={newCoverageMeasure.metric.key}> <span className="js-overview-main-new-coverage"> @@ -116,7 +114,7 @@ class Coverage extends React.PureComponent { {translate('overview.coverage_on')} <br /> <DrilldownLink - branch={branchName} + branch={branch} className="spacer-right overview-domain-secondary-measure-value" component={component.key} metric={newLinesToCover.metric.key}> diff --git a/server/sonar-web/src/main/js/apps/overview/main/Duplications.js b/server/sonar-web/src/main/js/apps/overview/main/Duplications.js index acad0d75090..397641eec23 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/Duplications.js +++ b/server/sonar-web/src/main/js/apps/overview/main/Duplications.js @@ -20,7 +20,6 @@ import React from 'react'; import enhance from './enhance'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; -import { getBranchName } from '../../../helpers/branches'; import { getMetricName } from '../helpers/metrics'; import { formatMeasure, getPeriodValue } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; @@ -53,7 +52,7 @@ class Duplications extends React.PureComponent { <div className="display-inline-block text-middle"> <div className="overview-domain-measure-value"> <DrilldownLink - branch={getBranchName(branch)} + branch={branch} component={component.key} metric="duplicated_lines_density"> {formatMeasure(duplications, 'PERCENT')} @@ -71,7 +70,6 @@ class Duplications extends React.PureComponent { renderNewDuplications() { const { branch, component, measures, leakPeriod } = this.props; - const branchName = getBranchName(branch); const newDuplicationsMeasure = measures.find( measure => measure.metric.key === 'new_duplicated_lines_density' ); @@ -88,7 +86,7 @@ class Duplications extends React.PureComponent { newDuplicationsValue != null ? <div> <DrilldownLink - branch={branchName} + branch={branch} component={component.key} metric={newDuplicationsMeasure.metric.key}> <span className="js-overview-main-new-duplications"> @@ -103,7 +101,7 @@ class Duplications extends React.PureComponent { {translate('overview.duplications_on')} <br /> <DrilldownLink - branch={branchName} + branch={branch} className="spacer-right overview-domain-secondary-measure-value" component={component.key} metric={newLinesMeasure.metric.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 a6ef18f6f8b..a3fbe1f8f86 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 @@ -26,7 +26,6 @@ import HistoryIcon from '../../../components/icons-components/HistoryIcon'; import Rating from './../../../components/ui/Rating'; import Timeline from '../components/Timeline'; import Tooltip from '../../../components/controls/Tooltip'; -import { getBranchName } from '../../../helpers/branches'; import { formatMeasure, formatMeasureVariation, @@ -69,7 +68,7 @@ export default function enhance(ComposedComponent) { </span> <Link className="button button-small button-compact spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component.key, domain, getBranchName(branch))}> + to={getComponentDrilldownUrl(component.key, domain, branch)}> <BubblesIcon size={14} /> </Link> </div> @@ -88,10 +87,7 @@ export default function enhance(ComposedComponent) { return ( <div className="overview-domain-measure"> <div className="overview-domain-measure-value"> - <DrilldownLink - branch={getBranchName(branch)} - component={component.key} - metric={metricKey}> + <DrilldownLink branch={branch} component={component.key} metric={metricKey}> <span className="js-overview-main-tests"> {formatMeasure(measure.value, getShortType(measure.metric.type))} </span> @@ -140,7 +136,7 @@ export default function enhance(ComposedComponent) { <Tooltip overlay={title} placement="top"> <div className="overview-domain-measure-sup"> <DrilldownLink - branch={getBranchName(branch)} + branch={branch} className="link-no-underline" component={component.key} metric={metricKey}> @@ -155,11 +151,7 @@ export default function enhance(ComposedComponent) { const { branch, measures, component } = this.props; const measure = measures.find(measure => measure.metric.key === metric); const value = this.getValue(measure); - const params = { - branch: getBranchName(branch), - resolved: 'false', - types: type - }; + const params = { branch, resolved: 'false', types: type }; if (isDiffMetric(metric)) { Object.assign(params, { sinceLeakPeriod: 'true' }); } @@ -188,11 +180,7 @@ export default function enhance(ComposedComponent) { return ( <Link className={linkClass} - to={getComponentMeasureHistory( - this.props.component.key, - metricKey, - getBranchName(this.props.branch) - )}> + to={getComponentMeasureHistory(this.props.component.key, metricKey, this.props.branch)}> <HistoryIcon /> </Link> ); diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js index 12c6172fde3..a54c39edcf6 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js @@ -23,14 +23,13 @@ import classNames from 'classnames'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; import LanguageDistribution from '../../../components/charts/LanguageDistribution'; import SizeRating from '../../../components/ui/SizeRating'; -import { getBranchName } from '../../../helpers/branches'; import { formatMeasure } from '../../../helpers/measures'; import { getMetricName } from '../helpers/metrics'; import { translate } from '../../../helpers/l10n'; export default class MetaSize extends React.PureComponent { static propTypes = { - branch: PropTypes.object.isRequired, + branch: PropTypes.string, component: PropTypes.object.isRequired, measures: PropTypes.array.isRequired }; @@ -44,10 +43,7 @@ export default class MetaSize extends React.PureComponent { <span className="spacer-right"> <SizeRating value={ncloc.value} /> </span> - <DrilldownLink - branch={getBranchName(this.props.branch)} - component={this.props.component.key} - metric="ncloc"> + <DrilldownLink branch={this.props.branch} component={this.props.component.key} metric="ncloc"> {formatMeasure(ncloc.value, 'SHORT_INT')} </DrilldownLink> <div className="overview-domain-measure-label text-muted"> @@ -75,7 +71,7 @@ export default class MetaSize extends React.PureComponent { id="overview-projects" className="overview-meta-size-ncloc is-half-width bordered-left"> <DrilldownLink - branch={getBranchName(this.props.branch)} + branch={this.props.branch} component={this.props.component.key} metric="projects"> {formatMeasure(projects.value, 'SHORT_INT')} diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js index bb4e7041003..03e930b66fa 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js @@ -35,7 +35,7 @@ function isProject(component /*: Component */) { /*:: type Props = { - branch: { name: string }, + branch?: string, component: Component, measures: MeasuresList }; 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 ddf81063fd6..fa18175019a 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 @@ -24,7 +24,6 @@ import { Link } from 'react-router'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; import Measure from '../../../components/measure/Measure'; import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; -import { getBranchName } from '../../../helpers/branches'; import { getPeriodValue, isDiffMetric, formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import { getComponentIssuesUrl } from '../../../helpers/urls'; @@ -33,7 +32,7 @@ import { getComponentIssuesUrl } from '../../../helpers/urls'; export default class QualityGateCondition extends React.PureComponent { /*:: props: { - branch: { name: string }, + branch?: string, component: Component, condition: { level: string, @@ -55,11 +54,7 @@ export default class QualityGateCondition extends React.PureComponent { } getIssuesUrl = (sinceLeakPeriod /*: boolean */, customQuery /*: {} */) => { - const query /*: Object */ = { - resolved: 'false', - branch: getBranchName(this.props.branch), - ...customQuery - }; + const query /*: Object */ = { resolved: 'false', branch: this.props.branch, ...customQuery }; if (sinceLeakPeriod) { Object.assign(query, { sinceLeakPeriod: 'true' }); } @@ -118,7 +113,7 @@ export default class QualityGateCondition extends React.PureComponent { {children} </Link> : <DrilldownLink - branch={getBranchName(branch)} + branch={branch} className={className} component={component.key} metric={condition.measure.metric.key} diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js index 02fbf9c5e5f..18392b0b189 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js @@ -22,7 +22,6 @@ import { sortBy } from 'lodash'; import QualityGateCondition from './QualityGateCondition'; import { ComponentType, ConditionsListType } from '../propTypes'; import { getMeasuresAndMeta } from '../../../api/measures'; -import { getBranchName } from '../../../helpers/branches'; import { enhanceMeasuresWithMetrics } from '../../../helpers/measures'; const LEVEL_ORDER = ['ERROR', 'WARN']; @@ -71,7 +70,7 @@ export default class QualityGateConditions extends React.PureComponent { const metrics = failedConditions.map(condition => condition.metric); getMeasuresAndMeta(component.key, metrics, { additionalFields: 'metrics', - branch: getBranchName(branch) + branch }).then(r => { if (this.mounted) { const measures = enhanceMeasuresWithMetrics(r.component.measures, r.metrics); diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGateCondition-test.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGateCondition-test.js index 1eee087a42f..41ac819c4eb 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGateCondition-test.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGateCondition-test.js @@ -56,13 +56,7 @@ it('open_issues', () => { op: 'GT' }; expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); @@ -85,52 +79,28 @@ it('new_open_issues', () => { period: 1 }; expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); it('reliability_rating', () => { const condition = mockRatingCondition('reliability_rating'); expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); it('security_rating', () => { const condition = mockRatingCondition('security_rating'); expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); it('sqale_rating', () => { const condition = mockRatingCondition('sqale_rating'); expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); @@ -139,13 +109,7 @@ it('new_reliability_rating', () => { condition.period = 1; condition.measure.periods = periods; expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); @@ -154,13 +118,7 @@ it('new_security_rating', () => { condition.period = 1; condition.measure.periods = periods; expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); @@ -169,24 +127,14 @@ it('new_maintainability_rating', () => { condition.period = 1; condition.measure.periods = periods; expect( - shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> - ) + shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />) ).toMatchSnapshot(); }); it('should be able to correctly decide how much decimals to show', () => { const condition = mockRatingCondition('new_maintainability_rating'); const instance = shallow( - <QualityGateCondition - branch={{ isMain: true }} - component={{ key: 'abcd-key' }} - condition={condition} - /> + <QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} /> ).instance(); expect(instance.getDecimalsNumber(85, 80)).toBe(undefined); expect(instance.getDecimalsNumber(85, 85)).toBe(undefined); @@ -202,7 +150,7 @@ it('should work with branch', () => { expect( shallow( <QualityGateCondition - branch={{ isMain: false, name: 'feature' }} + branch="feature" component={{ key: 'abcd-key' }} condition={condition} /> |