aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-07-10 11:23:58 +0200
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-07-13 14:34:17 +0200
commit598a5a81e4842fa03705f7f1c26a79bc520c70ef (patch)
tree322a37d422c83618e70218b34067f268209c7864
parente74ceaafe5549e07cc8ab52c7fb39945a6c3ed83 (diff)
downloadsonarqube-598a5a81e4842fa03705f7f1c26a79bc520c70ef.tar.gz
sonarqube-598a5a81e4842fa03705f7f1c26a79bc520c70ef.zip
SONAR-9418 Add tooltips on the project dashboard preview graph
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js4
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js73
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js82
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js45
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltips-test.js99
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltipsContent-test.js36
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltips-test.js.snap96
-rw-r--r--server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltipsContent-test.js.snap25
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/Meta.js7
-rw-r--r--server/sonar-web/src/main/js/apps/overview/styles.css26
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js6
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js19
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js7
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltips-test.js12
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltipsContent-test.js3
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsTooltips-test.js.snap15
-rw-r--r--server/sonar-web/src/main/less/init/misc.less3
17 files changed, 516 insertions, 42 deletions
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 9b199036fb2..9746ea02c4a 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
@@ -31,7 +31,8 @@ import type { History, Metric } from '../types';
type Props = {
history: History,
- project: string
+ project: string,
+ router: { replace: ({ pathname: string, query?: {} }) => void }
};
type State = {
@@ -107,6 +108,7 @@ export default class AnalysesList extends React.PureComponent {
history={this.props.history}
project={this.props.project}
metrics={this.state.metrics}
+ router={this.props.router}
/>
{this.renderList(analyses)}
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 d5cd5f6aea5..148557d6b68 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
@@ -20,26 +20,33 @@
// @flow
import React from 'react';
import { map } from 'lodash';
-import { Link } from 'react-router';
import { AutoSizer } from 'react-virtualized';
import { generateSeries, GRAPHS_METRICS_DISPLAYED } from '../../projectActivity/utils';
import { getGraph } from '../../../helpers/storage';
import AdvancedTimeline from '../../../components/charts/AdvancedTimeline';
+import PreviewGraphTooltips from './PreviewGraphTooltips';
+import { formatMeasure, getShortType } from '../../../helpers/measures';
import type { Serie } from '../../../components/charts/AdvancedTimeline';
import type { History, Metric } from '../types';
type Props = {
history: History,
metrics: Array<Metric>,
- project: string
+ project: string,
+ router: { replace: ({ pathname: string, query?: {} }) => void }
};
type State = {
graph: string,
metricsType: string,
- series: Array<Serie>
+ selectedDate: ?Date,
+ series: Array<Serie>,
+ tooltipIdx: ?number,
+ tooltipXPos: ?number
};
+const GRAPH_PADDING = [4, 0, 4, 0];
+
export default class PreviewGraph extends React.PureComponent {
props: Props;
state: State;
@@ -51,7 +58,10 @@ export default class PreviewGraph extends React.PureComponent {
this.state = {
graph,
metricsType,
- series: this.getSeries(props.history, graph, metricsType)
+ selectedDate: null,
+ series: this.getSeries(props.history, graph, metricsType),
+ tooltipIdx: null,
+ tooltipXPos: null
};
}
@@ -67,15 +77,18 @@ export default class PreviewGraph extends React.PureComponent {
}
}
- getDisplayedMetrics = (graph: string) => {
- const metrics = GRAPHS_METRICS_DISPLAYED[graph];
+ formatValue = (tick: number | string) =>
+ formatMeasure(tick, getShortType(this.state.metricsType));
+
+ getDisplayedMetrics = (graph: string): Array<string> => {
+ const metrics: Array<string> = GRAPHS_METRICS_DISPLAYED[graph];
if (!metrics || metrics.length <= 0) {
return GRAPHS_METRICS_DISPLAYED['overview'];
}
return metrics;
};
- getSeries = (history: History, graph: string, metricsType: string): Array<Serie> => {
+ getSeries = (history: History, graph: string, metricsType: string) => {
const measureHistory = map(history, (item, key) => ({
metric: key,
history: item.filter(p => p.value != null)
@@ -89,14 +102,24 @@ export default class PreviewGraph extends React.PureComponent {
return metric ? metric.type : 'INT';
};
+ handleClick = () => {
+ this.props.router.replace({ pathname: '/project/activity', query: { id: this.props.project } });
+ };
+
+ updateTooltip = (selectedDate: ?Date, tooltipXPos: ?number, tooltipIdx: ?number) =>
+ this.setState({ selectedDate, tooltipXPos, tooltipIdx });
+
render() {
+ const { graph, selectedDate, tooltipIdx, tooltipXPos } = this.state;
return (
- <div className="big-spacer-bottom spacer-top">
- <Link
- className="overview-analysis-graph"
- to={{ pathname: '/project/activity', query: { id: this.props.project } }}>
- <AutoSizer disableHeight={true}>
- {({ width }) => (
+ <div
+ className="overview-analysis-graph big-spacer-bottom spacer-top"
+ onClick={this.handleClick}
+ tabIndex={0}
+ role="link">
+ <AutoSizer disableHeight={true}>
+ {({ width }) => (
+ <div>
<AdvancedTimeline
endDate={null}
startDate={null}
@@ -106,13 +129,27 @@ export default class PreviewGraph extends React.PureComponent {
hideXAxis={true}
interpolate="linear"
metricType={this.state.metricsType}
- padding={[4, 0, 4, 0]}
+ padding={GRAPH_PADDING}
series={this.state.series}
- showAreas={['coverage', 'duplications'].includes(this.state.graph)}
+ showAreas={['coverage', 'duplications'].includes(graph)}
+ updateTooltip={this.updateTooltip}
/>
- )}
- </AutoSizer>
- </Link>
+ {selectedDate != null &&
+ tooltipXPos != null &&
+ tooltipIdx != null &&
+ <PreviewGraphTooltips
+ formatValue={this.formatValue}
+ graph={graph}
+ graphWidth={width}
+ metrics={this.props.metrics}
+ selectedDate={selectedDate}
+ series={this.state.series}
+ tooltipIdx={tooltipIdx}
+ tooltipPos={tooltipXPos}
+ />}
+ </div>
+ )}
+ </AutoSizer>
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js
new file mode 100644
index 00000000000..dfcf88e1289
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js
@@ -0,0 +1,82 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import React from 'react';
+import BubblePopup from '../../../components/common/BubblePopup';
+import FormattedDate from '../../../components/ui/FormattedDate';
+import PreviewGraphTooltipsContent from './PreviewGraphTooltipsContent';
+import type { Metric } from '../types';
+import type { Serie } from '../../../components/charts/AdvancedTimeline';
+
+type Props = {
+ formatValue: (number | string) => string,
+ graph: string,
+ graphWidth: number,
+ metrics: Array<Metric>,
+ selectedDate: Date,
+ series: Array<Serie & { translatedName: string }>,
+ tooltipIdx: number,
+ tooltipPos: number
+};
+
+const TOOLTIP_WIDTH = 150;
+
+export default class PreviewGraphTooltips extends React.PureComponent {
+ props: Props;
+
+ render() {
+ const { tooltipIdx } = this.props;
+ const top = 16;
+ let left = this.props.tooltipPos;
+ let customClass;
+ if (left > this.props.graphWidth - TOOLTIP_WIDTH + 20) {
+ left -= TOOLTIP_WIDTH;
+ customClass = 'bubble-popup-right';
+ }
+
+ return (
+ <BubblePopup customClass={customClass} position={{ top, left, width: TOOLTIP_WIDTH }}>
+ <div className="overview-analysis-graph-tooltip">
+ <div className="overview-analysis-graph-tooltip-title">
+ <FormattedDate date={this.props.selectedDate} format="LL" />
+ </div>
+ <table className="width-100">
+ <tbody>
+ {this.props.series.map(serie => {
+ const point = serie.data[tooltipIdx];
+ if (!point || (!point.y && point.y !== 0)) {
+ return null;
+ }
+ const metric = this.props.metrics.find(metric => metric.key === serie.name);
+ return (
+ <PreviewGraphTooltipsContent
+ key={serie.name}
+ serie={serie}
+ translatedName={metric && metric.custom ? metric.name : serie.translatedName}
+ value={this.props.formatValue(point.y)}
+ />
+ );
+ })}
+ </tbody>
+ </table>
+ </div>
+ </BubblePopup>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js
new file mode 100644
index 00000000000..a91af02daf3
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+// @flow
+import React from 'react';
+import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon';
+import type { Serie } from '../../../components/charts/AdvancedTimeline';
+
+type Props = {
+ serie: Serie,
+ translatedName: string,
+ value: string
+};
+
+export default function PreviewGraphTooltipsContent({ serie, translatedName, value }: Props) {
+ return (
+ <tr className="overview-analysis-graph-tooltip-line">
+ <td className="thin">
+ <ChartLegendIcon
+ className={'little-spacer-right line-chart-legend line-chart-legend-' + serie.style}
+ />
+ </td>
+ <td className="overview-analysis-graph-tooltip-value text-right little-spacer-right thin">
+ {value}
+ </td>
+ <td className="text-ellipsis">{translatedName}</td>
+ </tr>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltips-test.js b/server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltips-test.js
new file mode 100644
index 00000000000..10a9a0864cb
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltips-test.js
@@ -0,0 +1,99 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import React from 'react';
+import { shallow } from 'enzyme';
+import PreviewGraphTooltips from '../PreviewGraphTooltips';
+
+const SERIES_OVERVIEW = [
+ {
+ name: 'code_smells',
+ translatedName: 'Code Smells',
+ style: 1,
+ data: [
+ {
+ x: '2011-10-01T22:01:00.000Z',
+ y: 18
+ },
+ {
+ x: '2011-10-25T10:27:41.000Z',
+ y: 15
+ }
+ ]
+ },
+ {
+ name: 'bugs',
+ translatedName: 'Bugs',
+ style: 0,
+ data: [
+ {
+ x: '2011-10-01T22:01:00.000Z',
+ y: 3
+ },
+ {
+ x: '2011-10-25T10:27:41.000Z',
+ y: 0
+ }
+ ]
+ },
+ {
+ name: 'vulnerabilities',
+ translatedName: 'Vulnerabilities',
+ style: 2,
+ data: [
+ {
+ x: '2011-10-01T22:01:00.000Z',
+ y: 0
+ },
+ {
+ x: '2011-10-25T10:27:41.000Z',
+ y: 1
+ }
+ ]
+ }
+];
+
+const METRICS = [
+ { key: 'bugs', name: 'Bugs', type: 'INT' },
+ { key: 'vulnerabilities', name: 'Vulnerabilities', type: 'INT', custom: true }
+];
+
+const DEFAULT_PROPS = {
+ formatValue: val => 'Formated.' + val,
+ graph: 'overview',
+ graphWidth: 150,
+ metrics: METRICS,
+ selectedDate: new Date('2011-10-01T22:01:00.000Z'),
+ series: SERIES_OVERVIEW,
+ tooltipIdx: 0,
+ tooltipPos: 25
+};
+
+it('should render correctly', () => {
+ expect(
+ shallow(
+ <PreviewGraphTooltips
+ {...DEFAULT_PROPS}
+ graph="random"
+ selectedDate={new Date('2011-10-25T10:27:41.000Z')}
+ tooltipIdx={1}
+ />
+ )
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltipsContent-test.js b/server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltipsContent-test.js
new file mode 100644
index 00000000000..4195a9cfd1c
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/events/__tests__/PreviewGraphTooltipsContent-test.js
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import React from 'react';
+import { shallow } from 'enzyme';
+import PreviewGraphTooltipsContent from '../PreviewGraphTooltipsContent';
+
+const DEFAULT_PROPS = {
+ serie: {
+ name: 'code_smells',
+ translatedName: 'metric.code_smells.name',
+ style: 1
+ },
+ translatedName: 'Code Smells',
+ value: '1.2k'
+};
+
+it('should render correctly', () => {
+ expect(shallow(<PreviewGraphTooltipsContent {...DEFAULT_PROPS} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltips-test.js.snap b/server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltips-test.js.snap
new file mode 100644
index 00000000000..e8090585551
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltips-test.js.snap
@@ -0,0 +1,96 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<BubblePopup
+ customClass="bubble-popup-right"
+ position={
+ Object {
+ "left": -125,
+ "top": 16,
+ "width": 150,
+ }
+ }
+>
+ <div
+ className="overview-analysis-graph-tooltip"
+ >
+ <div
+ className="overview-analysis-graph-tooltip-title"
+ >
+ <FormattedDate
+ date={2011-10-25T10:27:41.000Z}
+ format="LL"
+ />
+ </div>
+ <table
+ className="width-100"
+ >
+ <tbody>
+ <PreviewGraphTooltipsContent
+ serie={
+ Object {
+ "data": Array [
+ Object {
+ "x": "2011-10-01T22:01:00.000Z",
+ "y": 18,
+ },
+ Object {
+ "x": "2011-10-25T10:27:41.000Z",
+ "y": 15,
+ },
+ ],
+ "name": "code_smells",
+ "style": 1,
+ "translatedName": "Code Smells",
+ }
+ }
+ translatedName="Code Smells"
+ value="Formated.15"
+ />
+ <PreviewGraphTooltipsContent
+ serie={
+ Object {
+ "data": Array [
+ Object {
+ "x": "2011-10-01T22:01:00.000Z",
+ "y": 3,
+ },
+ Object {
+ "x": "2011-10-25T10:27:41.000Z",
+ "y": 0,
+ },
+ ],
+ "name": "bugs",
+ "style": 0,
+ "translatedName": "Bugs",
+ }
+ }
+ translatedName="Bugs"
+ value="Formated.0"
+ />
+ <PreviewGraphTooltipsContent
+ serie={
+ Object {
+ "data": Array [
+ Object {
+ "x": "2011-10-01T22:01:00.000Z",
+ "y": 0,
+ },
+ Object {
+ "x": "2011-10-25T10:27:41.000Z",
+ "y": 1,
+ },
+ ],
+ "name": "vulnerabilities",
+ "style": 2,
+ "translatedName": "Vulnerabilities",
+ }
+ }
+ translatedName="Vulnerabilities"
+ value="Formated.1"
+ />
+ </tbody>
+ </table>
+ </div>
+</BubblePopup>
+`;
diff --git a/server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltipsContent-test.js.snap b/server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltipsContent-test.js.snap
new file mode 100644
index 00000000000..db45985ac21
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltipsContent-test.js.snap
@@ -0,0 +1,25 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<tr
+ className="overview-analysis-graph-tooltip-line"
+>
+ <td
+ className="thin"
+ >
+ <ChartLegendIcon
+ className="little-spacer-right line-chart-legend line-chart-legend-1"
+ />
+ </td>
+ <td
+ className="overview-analysis-graph-tooltip-value text-right little-spacer-right thin"
+ >
+ 1.2k
+ </td>
+ <td
+ className="text-ellipsis"
+ >
+ Code Smells
+ </td>
+</tr>
+`;
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/Meta.js b/server/sonar-web/src/main/js/apps/overview/meta/Meta.js
index 3f8cd994a1e..db9b0cb523c 100644
--- a/server/sonar-web/src/main/js/apps/overview/meta/Meta.js
+++ b/server/sonar-web/src/main/js/apps/overview/meta/Meta.js
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
+import { withRouter } from 'react-router';
import { connect } from 'react-redux';
import MetaKey from './MetaKey';
import MetaOrganizationKey from './MetaOrganizationKey';
@@ -29,7 +30,7 @@ import MetaSize from './MetaSize';
import MetaTags from './MetaTags';
import { areThereCustomOrganizations } from '../../../store/rootReducer';
-const Meta = ({ component, history, measures, areThereCustomOrganizations }) => {
+const Meta = ({ component, history, measures, areThereCustomOrganizations, router }) => {
const { qualifier, description, qualityProfiles, qualityGate } = component;
const isProject = qualifier === 'TRK';
@@ -70,7 +71,7 @@ const Meta = ({ component, history, measures, areThereCustomOrganizations }) =>
{shouldShowOrganizationKey && <MetaOrganizationKey component={component} />}
- {isProject && <AnalysesList project={component.key} history={history} />}
+ {isProject && <AnalysesList project={component.key} history={history} router={router} />}
</div>
);
};
@@ -79,4 +80,4 @@ const mapStateToProps = state => ({
areThereCustomOrganizations: areThereCustomOrganizations(state)
});
-export default connect(mapStateToProps)(Meta);
+export default connect(mapStateToProps)(withRouter(Meta));
diff --git a/server/sonar-web/src/main/js/apps/overview/styles.css b/server/sonar-web/src/main/js/apps/overview/styles.css
index 575ff4a859f..45911113921 100644
--- a/server/sonar-web/src/main/js/apps/overview/styles.css
+++ b/server/sonar-web/src/main/js/apps/overview/styles.css
@@ -347,10 +347,36 @@
.overview-analysis-graph {
display: block;
+ cursor: pointer;
outline: none;
border: none;
}
+.overview-analysis-graph .bubble-popup {
+ opacity: 0.8;
+ padding: 0;
+}
+
+.overview-analysis-graph-tooltip {
+ padding: 4px;
+ pointer-events: none;
+ font-size: 12px;
+ overflow: hidden;
+}
+
+.overview-analysis-graph-tooltip-line {
+ padding-bottom: 2px;
+}
+
+.overview-analysis-graph-tooltip-title {
+ font-weight: bold;
+ margin-bottom: 4px;
+}
+
+.overview-analysis-graph-tooltip-value {
+ font-weight: bold;
+}
+
.overview-analysis-event {}
.overview-analysis-event.badge {
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js
index 130bf03e018..6ce8ad5825b 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js
@@ -43,7 +43,7 @@ type Props = {
metrics: Array<Metric>,
metricsType: string,
removeCustomMetric: (metric: string) => void,
- selectedDate?: ?Date => void,
+ selectedDate: ?Date,
series: Array<Serie>,
updateGraphZoom: (from: ?Date, to: ?Date) => void,
updateSelectedDate: (selectedDate: ?Date) => void
@@ -62,7 +62,8 @@ export default class GraphsHistory extends React.PureComponent {
tooltipXPos: null
};
- formatValue = tick => formatMeasure(tick, getShortType(this.props.metricsType));
+ formatValue = (tick: string | number) =>
+ formatMeasure(tick, getShortType(this.props.metricsType));
getEvents = () => {
const { analyses, eventFilter } = this.props;
@@ -172,6 +173,7 @@ export default class GraphsHistory extends React.PureComponent {
graph={graph}
graphWidth={width}
measuresHistory={this.props.measuresHistory}
+ metrics={this.props.metrics}
selectedDate={selectedDate}
series={series}
tooltipIdx={tooltipIdx}
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js
index 6162767369a..d4b13addd4a 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltips.js
@@ -26,7 +26,7 @@ import GraphsTooltipsContentEvents from './GraphsTooltipsContentEvents';
import GraphsTooltipsContentCoverage from './GraphsTooltipsContentCoverage';
import GraphsTooltipsContentDuplication from './GraphsTooltipsContentDuplication';
import GraphsTooltipsContentOverview from './GraphsTooltipsContentOverview';
-import type { Event, MeasureHistory } from '../types';
+import type { Event, MeasureHistory, Metric } from '../types';
import type { Serie } from '../../../components/charts/AdvancedTimeline';
type Props = {
@@ -35,6 +35,7 @@ type Props = {
graph: string,
graphWidth: number,
measuresHistory: Array<MeasureHistory>,
+ metrics: Array<Metric>,
selectedDate: Date,
series: Array<Serie & { translatedName: string }>,
tooltipIdx: number,
@@ -68,19 +69,27 @@ export default class GraphsTooltips extends React.PureComponent {
if (!point || (!point.y && point.y !== 0)) {
return null;
}
- return this.props.graph === 'overview'
- ? <GraphsTooltipsContentOverview
+ if (this.props.graph === 'overview') {
+ return (
+ <GraphsTooltipsContentOverview
key={serie.name}
measuresHistory={measuresHistory}
serie={serie}
tooltipIdx={tooltipIdx}
value={this.props.formatValue(point.y)}
/>
- : <GraphsTooltipsContent
+ );
+ } else {
+ const metric = this.props.metrics.find(metric => metric.key === serie.name);
+ return (
+ <GraphsTooltipsContent
key={serie.name}
serie={serie}
+ translatedName={metric && metric.custom ? metric.name : serie.translatedName}
value={this.props.formatValue(point.y)}
- />;
+ />
+ );
+ }
})}
</tbody>
{this.props.graph === 'coverage' &&
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js
index 43eebc411fb..f3dae718ad6 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsTooltipsContent.js
@@ -24,11 +24,12 @@ import ChartLegendIcon from '../../../components/icons-components/ChartLegendIco
import type { Serie } from '../../../components/charts/AdvancedTimeline';
type Props = {
- serie: Serie & { translatedName: string },
+ serie: Serie,
+ translatedName: string,
value: string
};
-export default function GraphsTooltipsContent({ serie, value }: Props) {
+export default function GraphsTooltipsContent({ serie, translatedName, value }: Props) {
return (
<tr key={serie.name} className="project-activity-graph-tooltip-line">
<td className="thin">
@@ -42,7 +43,7 @@ export default function GraphsTooltipsContent({ serie, value }: Props) {
<td className="project-activity-graph-tooltip-value text-right spacer-right thin">
{value}
</td>
- <td>{serie.translatedName}</td>
+ <td>{translatedName}</td>
</tr>
);
}
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltips-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltips-test.js
index 206491eff31..cebdb8265a7 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltips-test.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltips-test.js
@@ -24,7 +24,7 @@ import GraphsTooltips from '../GraphsTooltips';
const SERIES_OVERVIEW = [
{
name: 'code_smells',
- translatedName: 'Code Smells',
+ translatedName: 'metric.code_smells.name',
style: 1,
data: [
{
@@ -39,7 +39,7 @@ const SERIES_OVERVIEW = [
},
{
name: 'bugs',
- translatedName: 'Bugs',
+ translatedName: 'metric.bugs.name',
style: 0,
data: [
{
@@ -54,7 +54,7 @@ const SERIES_OVERVIEW = [
},
{
name: 'vulnerabilities',
- translatedName: 'Vulnerabilities',
+ translatedName: 'metric.vulnerabilities.name',
style: 2,
data: [
{
@@ -69,11 +69,17 @@ const SERIES_OVERVIEW = [
}
];
+const METRICS = [
+ { key: 'bugs', name: 'Bugs', type: 'INT' },
+ { key: 'vulnerabilities', name: 'Vulnerabilities', type: 'INT', custom: true }
+];
+
const DEFAULT_PROPS = {
formatValue: val => 'Formated.' + val,
graph: 'overview',
graphWidth: 500,
measuresHistory: [],
+ metrics: METRICS,
selectedDate: new Date('2011-10-01T22:01:00.000Z'),
series: SERIES_OVERVIEW,
tooltipIdx: 0,
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltipsContent-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltipsContent-test.js
index 46de44dffa6..ce610f0bdf9 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltipsContent-test.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsTooltipsContent-test.js
@@ -24,9 +24,10 @@ import GraphsTooltipsContent from '../GraphsTooltipsContent';
const DEFAULT_PROPS = {
serie: {
name: 'code_smells',
- translatedName: 'Code Smells',
+ translatedName: 'metric.code_smells.name',
style: 1
},
+ translatedName: 'Code Smells',
value: '1.2k'
};
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsTooltips-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsTooltips-test.js.snap
index a43f2d4b0fb..8cc911548dc 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsTooltips-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsTooltips-test.js.snap
@@ -42,7 +42,7 @@ exports[`should render correctly for overview graphs 1`] = `
],
"name": "code_smells",
"style": 1,
- "translatedName": "Code Smells",
+ "translatedName": "metric.code_smells.name",
}
}
tooltipIdx={0}
@@ -64,7 +64,7 @@ exports[`should render correctly for overview graphs 1`] = `
],
"name": "bugs",
"style": 0,
- "translatedName": "Bugs",
+ "translatedName": "metric.bugs.name",
}
}
tooltipIdx={0}
@@ -86,7 +86,7 @@ exports[`should render correctly for overview graphs 1`] = `
],
"name": "vulnerabilities",
"style": 2,
- "translatedName": "Vulnerabilities",
+ "translatedName": "metric.vulnerabilities.name",
}
}
tooltipIdx={0}
@@ -139,9 +139,10 @@ exports[`should render correctly for random graphs 1`] = `
],
"name": "code_smells",
"style": 1,
- "translatedName": "Code Smells",
+ "translatedName": "metric.code_smells.name",
}
}
+ translatedName="metric.code_smells.name"
value="Formated.15"
/>
<GraphsTooltipsContent
@@ -159,9 +160,10 @@ exports[`should render correctly for random graphs 1`] = `
],
"name": "bugs",
"style": 0,
- "translatedName": "Bugs",
+ "translatedName": "metric.bugs.name",
}
}
+ translatedName="metric.bugs.name"
value="Formated.0"
/>
<GraphsTooltipsContent
@@ -179,9 +181,10 @@ exports[`should render correctly for random graphs 1`] = `
],
"name": "vulnerabilities",
"style": 2,
- "translatedName": "Vulnerabilities",
+ "translatedName": "metric.vulnerabilities.name",
}
}
+ translatedName="Vulnerabilities"
value="Formated.1"
/>
</tbody>
diff --git a/server/sonar-web/src/main/less/init/misc.less b/server/sonar-web/src/main/less/init/misc.less
index 91b035a151b..ccb7e767196 100644
--- a/server/sonar-web/src/main/less/init/misc.less
+++ b/server/sonar-web/src/main/less/init/misc.less
@@ -60,6 +60,9 @@ table.nowrap td, td.nowrap, th.nowrap { white-space: nowrap; }
.little-spacer-bottom { margin-bottom: 4px; }
.little-spacer-top { margin-top: 4px; }
+td.little-spacer-left { padding-left: 4px; }
+td.little-spacer-right { padding-right: 4px; }
+
td.spacer-left { padding-left: 8px; }
td.spacer-right { padding-right: 8px; }
td.spacer-bottom { padding-bottom: 8px; }