aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorPascal Mugnier <pascal.mugnier@sonarsource.com>2018-04-17 09:18:52 +0200
committerSonarTech <sonartech@sonarsource.com>2018-04-18 20:20:53 +0200
commit95dea523fad5239c13791404aff7a4d0dadd12d3 (patch)
tree2b5ed7a83e361e0f3d1847b32526f83498fdc74f /server
parenta22bc323f8d43fb243031ead669c5ff876f75c0a (diff)
downloadsonarqube-95dea523fad5239c13791404aff7a4d0dadd12d3.tar.gz
sonarqube-95dea523fad5239c13791404aff7a4d0dadd12d3.zip
SONAR-9843 Open measure page in blank page when middle click on a file
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js3
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentCell.js36
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsList.js20
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/ComponentsListRow.js17
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.js8
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/overview/main/enhance.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/Effort.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/MeasuresButtonLink.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/ReleasabilityBox.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx5
-rw-r--r--server/sonar-web/src/main/js/components/shared/DrilldownLink.tsx12
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts8
-rw-r--r--server/sonar-web/src/main/js/helpers/urls.ts33
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) {