diff options
author | Pascal Mugnier <pascal.mugnier@sonarsource.com> | 2018-04-17 09:18:52 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-04-18 20:20:53 +0200 |
commit | 95dea523fad5239c13791404aff7a4d0dadd12d3 (patch) | |
tree | 2b5ed7a83e361e0f3d1847b32526f83498fdc74f /server/sonar-web/src/main | |
parent | a22bc323f8d43fb243031ead669c5ff876f75c0a (diff) | |
download | sonarqube-95dea523fad5239c13791404aff7a4d0dadd12d3.tar.gz sonarqube-95dea523fad5239c13791404aff7a4d0dadd12d3.zip |
SONAR-9843 Open measure page in blank page when middle click on a file
Diffstat (limited to 'server/sonar-web/src/main')
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 ( <td className="measure-details-component-cell"> <div className="text-ellipsis"> - {/* TODO make this <a> link a react-router <Link /> */} {component.refKey == null ? ( - <a - id={'component-measures-component-link-' + component.key} + <Link className="link-no-underline" - href={getPathUrlAsString(getBranchLikeUrl(component.key, branchLike))} - onClick={this.handleClick}> + id={'component-measures-component-link-' + component.key} + to={getComponentDrilldownUrlWithSelection( + rootComponent.key, + component.key, + metric.key, + branchLike + )}> {this.renderInner()} - </a> + </Link> ) : ( <Link className="link-no-underline" 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 0e29a704f0c..cfc0aa28aa2 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 @@ -23,7 +23,7 @@ import ComponentsListRow from './ComponentsListRow'; import EmptyResult from './EmptyResult'; import { complementary } from '../config/complementary'; import { getLocalizedMetricName } from '../../../helpers/l10n'; -/*:: import type { ComponentEnhanced } from '../types'; */ +/*:: import type { Component, ComponentEnhanced } from '../types'; */ /*:: import type { Metric } from '../../../store/metrics/actions'; */ /*:: type Props = {| @@ -32,11 +32,20 @@ import { getLocalizedMetricName } from '../../../helpers/l10n'; onClick: string => 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 <EmptyResult />; @@ -53,7 +62,7 @@ export default function ComponentsList( <span className="small">{getLocalizedMetricName(metric)}</span> </th> {otherMetrics.map(metric => ( - <th key={metric.key} className="text-right"> + <th className="text-right" key={metric.key}> <span className="small">{getLocalizedMetricName(metric)}</span> </th> ))} @@ -64,13 +73,14 @@ export default function ComponentsList( <tbody> {components.map(component => ( <ComponentsListRow - key={component.id} branchLike={branchLike} component={component} - otherMetrics={otherMetrics} isSelected={component.key === selectedComponent} + key={component.id} metric={metric} onClick={onClick} + otherMetrics={otherMetrics} + rootComponent={rootComponent} /> ))} </tbody> 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: 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 ( <tr className={rowClass}> - <ComponentCell branchLike={branchLike} component={component} onClick={props.onClick} /> + <ComponentCell + branchLike={branchLike} + component={component} + metric={props.metric} + onClick={props.onClick} + rootComponent={rootComponent} + /> <MeasureCell component={component} metric={props.metric} /> {otherMeasures.map(measure => ( <MeasureCell - key={measure.metric.key} component={component} + key={measure.metric.key} measure={measure} metric={measure.metric} /> 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 { <ComponentsList branchLike={this.props.branchLike} components={this.props.components} - metrics={this.props.metrics} metric={this.props.metric} + metrics={this.props.metrics} onClick={this.props.handleOpen} + rootComponent={this.props.rootComponent} selectedComponent={this.props.selectedKey} /> {this.props.paging && this.props.components.length > 0 && ( <ListFooter count={this.props.components.length} - total={this.props.paging.total} loadMore={this.props.fetchMore} + total={this.props.paging.total} /> )} </div> 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<ComposedProps> { <span>{translate('metric.bugs.name')}</span> <Link className="button button-small spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component.key, 'Reliability', branchLike)}> + to={getComponentDrilldownUrl({ + componentKey: component.key, + metric: 'Reliability', + branchLike + })}> <BubblesIcon size={14} /> </Link> <span className="big-spacer-left">{translate('metric.vulnerabilities.name')}</span> <Link className="button button-small spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component.key, 'Security', branchLike)}> + to={getComponentDrilldownUrl({ + componentKey: component.key, + metric: 'Security', + branchLike + })}> <BubblesIcon size={14} /> </Link> </div> 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<ComposedP <span>{label}</span> <Link className="button button-small spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component.key, domain, branchLike)}> + to={getComponentDrilldownUrl({ + componentKey: component.key, + metric: domain, + branchLike + })}> <BubblesIcon size={14} /> </Link> </div> 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: ( - <Link to={getComponentDrilldownUrl(component, metricKey)}> + <Link to={getComponentDrilldownUrl({ componentKey: component, metric: metricKey })}> <span> <Measure className="little-spacer-right" diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/MeasuresButtonLink.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/MeasuresButtonLink.tsx index 8cb9d28bc76..9f90824d2b8 100644 --- a/server/sonar-web/src/main/js/apps/portfolio/components/MeasuresButtonLink.tsx +++ b/server/sonar-web/src/main/js/apps/portfolio/components/MeasuresButtonLink.tsx @@ -31,7 +31,7 @@ export default function MeasuresButtonLink({ component, metric }: Props) { return ( <Link className="button button-small spacer-left text-text-bottom" - to={getComponentDrilldownUrl(component, metric)}> + to={getComponentDrilldownUrl({ componentKey: component, metric })}> <BubblesIcon size={14} /> </Link> ); 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 && ( <Link - to={getComponentDrilldownUrl(component, 'alert_status')} + to={getComponentDrilldownUrl({ componentKey: component, metric: 'alert_status' })} className="portfolio-box-rating"> <Rating value={rating} /> </Link> @@ -52,7 +52,8 @@ export default function ReleasabilityBox({ component, measures }: Props) { {effort && Number(effort) > 0 && ( <div className="portfolio-effort"> - <Link to={getComponentDrilldownUrl(component, 'alert_status')}> + <Link + to={getComponentDrilldownUrl({ componentKey: component, metric: 'alert_status' })}> <span> <Measure className="little-spacer-right" diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx index 7d438b6167f..3f3ed3e1253 100644 --- a/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx +++ b/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx @@ -41,7 +41,8 @@ export default function Summary({ component, measures }: Props) { <li> <div className="portfolio-measure-secondary-value"> {projects ? ( - <Link to={getComponentDrilldownUrl(component.key, 'projects')}> + <Link + to={getComponentDrilldownUrl({ componentKey: component.key, metric: 'projects' })}> <Measure metricKey="projects" metricType="SHORT_INT" value={projects} /> </Link> ) : ( @@ -53,7 +54,7 @@ export default function Summary({ component, measures }: Props) { <li> <div className="portfolio-measure-secondary-value"> {ncloc ? ( - <Link to={getComponentDrilldownUrl(component.key, 'ncloc')}> + <Link to={getComponentDrilldownUrl({ componentKey: component.key, metric: 'ncloc' })}> <Measure metricKey="ncloc" metricType="SHORT_INT" value={ncloc} /> </Link> ) : ( 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<Props> { 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 ( - <Link to={url} className={this.props.className}> + <Link className={this.props.className} to={url}> {this.props.children} </Link> ); 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) { |