From 95dea523fad5239c13791404aff7a4d0dadd12d3 Mon Sep 17 00:00:00 2001 From: Pascal Mugnier Date: Tue, 17 Apr 2018 09:18:52 +0200 Subject: [PATCH] SONAR-9843 Open measure page in blank page when middle click on a file --- .../components/MeasureContent.js | 3 +- .../drilldown/ComponentCell.js | 36 +++++++++---------- .../drilldown/ComponentsList.js | 20 ++++++++--- .../drilldown/ComponentsListRow.js | 17 ++++++--- .../component-measures/drilldown/FilesView.js | 8 +++-- .../overview/main/BugsAndVulnerabilities.tsx | 12 +++++-- .../main/js/apps/overview/main/enhance.tsx | 6 +++- .../js/apps/portfolio/components/Effort.tsx | 2 +- .../components/MeasuresButtonLink.tsx | 2 +- .../portfolio/components/ReleasabilityBox.tsx | 5 +-- .../js/apps/portfolio/components/Summary.tsx | 5 +-- .../js/components/shared/DrilldownLink.tsx | 12 +++---- .../main/js/helpers/__tests__/urls-test.ts | 8 +++-- server/sonar-web/src/main/js/helpers/urls.ts | 33 +++++++++++------ 14 files changed, 108 insertions(+), 61 deletions(-) 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 f18f16b55e2..a4847ed1848 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 @@ -253,8 +253,9 @@ export default class MeasureContent extends React.PureComponent { metric={metric} metrics={this.props.metrics} paging={this.state.paging} - selectedKey={selectedIdx != null ? this.state.selected : null} + rootComponent={this.props.rootComponent} selectedIdx={selectedIdx} + selectedKey={selectedIdx != null ? this.state.selected : null} /> ); } 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 248b6469e2b..25b6b7b4f10 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 @@ -23,28 +23,21 @@ import { Link } from 'react-router'; import LinkIcon from '../../../components/icons-components/LinkIcon'; import QualifierIcon from '../../../components/icons-components/QualifierIcon'; import { splitPath } from '../../../helpers/path'; -import { getPathUrlAsString, getBranchLikeUrl } from '../../../helpers/urls'; -/*:: import type { ComponentEnhanced } from '../types'; */ +import { getBranchLikeUrl, getComponentDrilldownUrlWithSelection } from '../../../helpers/urls'; +/*:: import type { Component, ComponentEnhanced } from '../types'; */ +/*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = { branchLike?: { id?: string; name: string }, component: ComponentEnhanced, - onClick: string => void + onClick: string => void, + metric: Metric, + rootComponent: Component }; */ export default class ComponentCell extends React.PureComponent { /*:: props: Props; */ - handleClick = (e /*: MouseEvent */) => { - const isLeftClickEvent = e.button === 0; - const isModifiedEvent = !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey); - - if (isLeftClickEvent && !isModifiedEvent) { - e.preventDefault(); - this.props.onClick(this.props.component.key); - } - }; - renderInner() { const { component } = this.props; let head = ''; @@ -65,19 +58,22 @@ export default class ComponentCell extends React.PureComponent { } render() { - const { branchLike, component } = this.props; + const { branchLike, component, metric, rootComponent } = this.props; return (
- {/* TODO make this link a react-router */} {component.refKey == null ? ( - + id={'component-measures-component-link-' + component.key} + to={getComponentDrilldownUrlWithSelection( + rootComponent.key, + component.key, + metric.key, + branchLike + )}> {this.renderInner()} - + ) : ( void, metric: Metric, metrics: { [string]: Metric }, + rootComponent: Component, selectedComponent?: ?string |}; */ export default function ComponentsList( - { branchLike, components, onClick, metrics, metric, selectedComponent } /*: Props */ + { + branchLike, + components, + onClick, + metrics, + metric, + rootComponent, + selectedComponent + } /*: Props */ ) { if (!components.length) { return ; @@ -53,7 +62,7 @@ export default function ComponentsList( {getLocalizedMetricName(metric)} {otherMetrics.map(metric => ( - + {getLocalizedMetricName(metric)} ))} @@ -64,13 +73,14 @@ export default function ComponentsList( {components.map(component => ( ))} 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 47a5d2bf29a..891bd5b5747 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 @@ -22,7 +22,7 @@ import React from 'react'; import classNames from 'classnames'; import ComponentCell from './ComponentCell'; import MeasureCell from './MeasureCell'; -/*:: import type { ComponentEnhanced } from '../types'; */ +/*:: import type { Component, ComponentEnhanced } from '../types'; */ /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| @@ -31,11 +31,12 @@ import MeasureCell from './MeasureCell'; isSelected: boolean, onClick: string => void, otherMetrics: Array, - metric: Metric + metric: Metric, + rootComponent: Component |}; */ export default function ComponentsListRow(props /*: Props */) { - const { branchLike, component } = props; + const { branchLike, component, rootComponent } = props; const otherMeasures = props.otherMetrics.map(metric => { const measure = component.measures.find(measure => measure.metric.key === metric.key); return { ...measure, metric }; @@ -45,14 +46,20 @@ export default function ComponentsListRow(props /*: Props */) { }); return ( - + {otherMeasures.map(measure => ( 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 2fd8d7feb27..4c1fbb8ce08 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 @@ -24,7 +24,7 @@ import { throttle } from 'lodash'; import ComponentsList from './ComponentsList'; import ListFooter from '../../../components/controls/ListFooter'; import { scrollToElement } from '../../../helpers/scrolling'; -/*:: import type { ComponentEnhanced, Paging } from '../types'; */ +/*:: import type { Component, ComponentEnhanced, Paging } from '../types'; */ /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| @@ -36,6 +36,7 @@ import { scrollToElement } from '../../../helpers/scrolling'; metric: Metric, metrics: { [string]: Metric }, paging: ?Paging, + rootComponent: Component, selectedKey: ?string, selectedIdx: ?number |}; */ @@ -125,17 +126,18 @@ export default class ListView extends React.PureComponent { {this.props.paging && this.props.components.length > 0 && ( )}
diff --git a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx index 52fd2d5253b..3ce147ba718 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx +++ b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx @@ -39,13 +39,21 @@ export class BugsAndVulnerabilities extends React.PureComponent { {translate('metric.bugs.name')} + to={getComponentDrilldownUrl({ + componentKey: component.key, + metric: 'Reliability', + branchLike + })}> {translate('metric.vulnerabilities.name')} + to={getComponentDrilldownUrl({ + componentKey: component.key, + metric: 'Security', + branchLike + })}> diff --git a/server/sonar-web/src/main/js/apps/overview/main/enhance.tsx b/server/sonar-web/src/main/js/apps/overview/main/enhance.tsx index 9797387082d..2ff27976bf8 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/enhance.tsx +++ b/server/sonar-web/src/main/js/apps/overview/main/enhance.tsx @@ -85,7 +85,11 @@ export default function enhance(ComposedComponent: React.ComponentType{label} + to={getComponentDrilldownUrl({ + componentKey: component.key, + metric: domain, + branchLike + })}> diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/Effort.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/Effort.tsx index 4029dbe7a38..d2f0235d455 100644 --- a/server/sonar-web/src/main/js/apps/portfolio/components/Effort.tsx +++ b/server/sonar-web/src/main/js/apps/portfolio/components/Effort.tsx @@ -39,7 +39,7 @@ export default function Effort({ component, effort, metricKey }: Props) { id="portfolio.x_in_y" values={{ projects: ( - + + to={getComponentDrilldownUrl({ componentKey: component, metric })}> ); diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/ReleasabilityBox.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/ReleasabilityBox.tsx index a33d40f9ef1..3dd30c83541 100644 --- a/server/sonar-web/src/main/js/apps/portfolio/components/ReleasabilityBox.tsx +++ b/server/sonar-web/src/main/js/apps/portfolio/components/ReleasabilityBox.tsx @@ -41,7 +41,7 @@ export default function ReleasabilityBox({ component, measures }: Props) { {rating && ( @@ -52,7 +52,8 @@ export default function ReleasabilityBox({ component, measures }: Props) { {effort && Number(effort) > 0 && (
- +
{projects ? ( - + ) : ( @@ -53,7 +54,7 @@ export default function Summary({ component, measures }: Props) {
  • {ncloc ? ( - + ) : ( diff --git a/server/sonar-web/src/main/js/components/shared/DrilldownLink.tsx b/server/sonar-web/src/main/js/components/shared/DrilldownLink.tsx index ff5587d95b4..8836780c7f9 100644 --- a/server/sonar-web/src/main/js/components/shared/DrilldownLink.tsx +++ b/server/sonar-web/src/main/js/components/shared/DrilldownLink.tsx @@ -138,13 +138,13 @@ export default class DrilldownLink extends React.PureComponent { return this.renderIssuesLink(); } - const url = getComponentDrilldownUrl( - this.props.component, - this.props.metric, - this.props.branchLike - ); + const url = getComponentDrilldownUrl({ + componentKey: this.props.component, + metric: this.props.metric, + branchLike: this.props.branchLike + }); return ( - + {this.props.children} ); diff --git a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts index 75382073d32..bb637690f4c 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts @@ -81,14 +81,18 @@ describe('#getComponentIssuesUrl', () => { describe('#getComponentDrilldownUrl', () => { it('should return component drilldown url', () => { - expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC)).toEqual({ + expect( + getComponentDrilldownUrl({ componentKey: SIMPLE_COMPONENT_KEY, metric: METRIC }) + ).toEqual({ pathname: '/component_measures', query: { id: SIMPLE_COMPONENT_KEY, metric: METRIC } }); }); it('should not encode component key', () => { - expect(getComponentDrilldownUrl(COMPLEX_COMPONENT_KEY, METRIC)).toEqual({ + expect( + getComponentDrilldownUrl({ componentKey: COMPLEX_COMPONENT_KEY, metric: METRIC }) + ).toEqual({ pathname: '/component_measures', query: { id: COMPLEX_COMPONENT_KEY, metric: METRIC } }); diff --git a/server/sonar-web/src/main/js/helpers/urls.ts b/server/sonar-web/src/main/js/helpers/urls.ts index 20cec1b04fb..a04d8376536 100644 --- a/server/sonar-web/src/main/js/helpers/urls.ts +++ b/server/sonar-web/src/main/js/helpers/urls.ts @@ -103,22 +103,35 @@ export function getComponentIssuesUrl(componentKey: string, query?: Query): Loca /** * Generate URL for a component's drilldown page */ -export function getComponentDrilldownUrl( +export function getComponentDrilldownUrl(options: { + componentKey: string; + metric: string; + branchLike?: BranchLike; + selectionKey?: string; + treemapView?: boolean; +}): Location { + const { componentKey, metric, branchLike, selectionKey, treemapView } = options; + const query: Query = { id: componentKey, metric, ...getBranchLikeQuery(branchLike) }; + if (treemapView) { + query.view = 'treemap'; + } + if (selectionKey) { + query.selected = selectionKey; + } + return { pathname: '/component_measures', query }; +} + +export function getComponentDrilldownUrlWithSelection( componentKey: string, + selectionKey: string, metric: string, branchLike?: BranchLike ): Location { - return { - pathname: '/component_measures', - query: { id: componentKey, metric, ...getBranchLikeQuery(branchLike) } - }; + return getComponentDrilldownUrl({ componentKey, selectionKey, metric, branchLike }); } -export function getMeasureTreemapUrl(component: string, metric: string) { - return { - pathname: '/component_measures', - query: { id: component, metric, view: 'treemap' } - }; +export function getMeasureTreemapUrl(componentKey: string, metric: string) { + return getComponentDrilldownUrl({ componentKey, metric, treemapView: true }); } export function getActivityUrl(component: string, branchLike?: BranchLike) { -- 2.39.5