diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-07-17 17:26:44 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-07-19 10:10:10 +0200 |
commit | 097f6826b2c684e22f4d57bd1d09c3a7029e5b55 (patch) | |
tree | 42e2c2e7ed83b08b9716436199be20e977a44d46 | |
parent | c79679129c7414e04c7c1d49e9c58ed5390748d7 (diff) | |
download | sonarqube-097f6826b2c684e22f4d57bd1d09c3a7029e5b55.tar.gz sonarqube-097f6826b2c684e22f4d57bd1d09c3a7029e5b55.zip |
SONAR-9546 Sync tooltips from the two graphs
11 files changed, 478 insertions, 268 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js new file mode 100644 index 00000000000..64cbfe5d0ab --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphHistory.js @@ -0,0 +1,116 @@ +/* + * 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 { AutoSizer } from 'react-virtualized'; +import AdvancedTimeline from '../../../components/charts/AdvancedTimeline'; +import GraphsTooltips from './GraphsTooltips'; +import GraphsLegendCustom from './GraphsLegendCustom'; +import GraphsLegendStatic from './GraphsLegendStatic'; +import { formatMeasure, getShortType } from '../../../helpers/measures'; +import type { Event, MeasureHistory } from '../types'; +import type { Serie } from '../../../components/charts/AdvancedTimeline'; + +type Props = { + events: Array<Event>, + graph: string, + graphEndDate: ?Date, + graphStartDate: ?Date, + leakPeriodDate: Date, + isCustom: boolean, + measuresHistory: Array<MeasureHistory>, + metricsType: string, + removeCustomMetric: (metric: string) => void, + showAreas: boolean, + series: Array<Serie>, + selectedDate?: ?Date, + updateGraphZoom: (from: ?Date, to: ?Date) => void, + updateSelectedDate: (selectedDate: ?Date) => void, + updateTooltip: (selectedDate: ?Date) => void +}; + +type State = { + tooltipIdx: ?number, + tooltipXPos: ?number +}; + +export default class GraphHistory extends React.PureComponent { + props: Props; + state: State = { + tooltipIdx: null, + tooltipXPos: null + }; + + formatValue = (tick: string | number) => + formatMeasure(tick, getShortType(this.props.metricsType)); + + updateTooltip = (selectedDate: ?Date, tooltipXPos: ?number, tooltipIdx: ?number) => { + this.props.updateTooltip(selectedDate); + this.setState({ tooltipXPos, tooltipIdx }); + }; + + render() { + const { graph, selectedDate, series } = this.props; + const { tooltipIdx, tooltipXPos } = this.state; + + return ( + <div className="project-activity-graph-container"> + {this.props.isCustom + ? <GraphsLegendCustom series={series} removeMetric={this.props.removeCustomMetric} /> + : <GraphsLegendStatic series={series} />} + <div className="project-activity-graph"> + <AutoSizer> + {({ height, width }) => + <div> + <AdvancedTimeline + endDate={this.props.graphEndDate} + height={height} + width={width} + interpolate="linear" + formatYTick={this.formatValue} + leakPeriodDate={this.props.leakPeriodDate} + metricType={this.props.metricsType} + selectedDate={selectedDate} + series={series} + showAreas={this.props.showAreas} + startDate={this.props.graphStartDate} + updateSelectedDate={this.props.updateSelectedDate} + updateTooltip={this.updateTooltip} + updateZoom={this.props.updateGraphZoom} + /> + {selectedDate != null && + tooltipXPos != null && + <GraphsTooltips + events={this.props.events} + formatValue={this.formatValue} + graph={graph} + graphWidth={width} + measuresHistory={this.props.measuresHistory} + selectedDate={selectedDate} + series={series} + tooltipIdx={tooltipIdx} + tooltipPos={tooltipXPos} + />} + </div>} + </AutoSizer> + </div> + </div> + ); + } +} 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 bb72897ea26..3fae4284ddd 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 @@ -19,14 +19,10 @@ */ import React from 'react'; import moment from 'moment'; -import { sortBy } from 'lodash'; -import { AutoSizer } from 'react-virtualized'; -import AdvancedTimeline from '../../../components/charts/AdvancedTimeline'; -import GraphsTooltips from './GraphsTooltips'; -import GraphsLegendCustom from './GraphsLegendCustom'; -import GraphsLegendStatic from './GraphsLegendStatic'; -import { formatMeasure, getShortType } from '../../../helpers/measures'; -import { EVENT_TYPES, isCustomGraph } from '../utils'; +import { isEqual, sortBy } from 'lodash'; +import GraphHistory from './GraphHistory'; +import { EVENT_TYPES, getSeriesMetricType, hasHistoryData, isCustomGraph } from '../utils'; +import { translate } from '../../../helpers/l10n'; import type { Analysis, MeasureHistory } from '../types'; import type { Serie } from '../../../components/charts/AdvancedTimeline'; @@ -34,11 +30,12 @@ type Props = { analyses: Array<Analysis>, eventFilter: string, graph: string, + graphs: Array<Array<Serie>>, graphEndDate: ?Date, graphStartDate: ?Date, leakPeriodDate: Date, + loading: boolean, measuresHistory: Array<MeasureHistory>, - metricsType: string, removeCustomMetric: (metric: string) => void, selectedDate: ?Date, series: Array<Serie>, @@ -47,20 +44,25 @@ type Props = { }; type State = { - selectedDate?: ?Date, - tooltipIdx: ?number, - tooltipXPos: ?number + selectedDate?: ?Date }; export default class GraphsHistory extends React.PureComponent { props: Props; - state: State = { - tooltipIdx: null, - tooltipXPos: null - }; + state: State; - formatValue = (tick: string | number) => - formatMeasure(tick, getShortType(this.props.metricsType)); + constructor(props: Props) { + super(props); + this.state = { + selectedDate: props.selectedDate + }; + } + + componentWillReceiveProps(nextProps: Props) { + if (!isEqual(nextProps.selectedDate, this.props.selectedDate)) { + this.setState({ selectedDate: nextProps.selectedDate }); + } + } getEvents = () => { const { analyses, eventFilter } = this.props; @@ -100,54 +102,59 @@ export default class GraphsHistory extends React.PureComponent { return []; }; - updateTooltip = (selectedDate: ?Date, tooltipXPos: ?number, tooltipIdx: ?number) => - this.setState({ selectedDate, tooltipXPos, tooltipIdx }); + updateTooltip = (selectedDate: ?Date) => this.setState({ selectedDate }); render() { const { graph, series } = this.props; const isCustom = isCustomGraph(graph); - const { selectedDate, tooltipIdx, tooltipXPos } = this.state; - return ( - <div className="project-activity-graph-container"> - {isCustom - ? <GraphsLegendCustom series={series} removeMetric={this.props.removeCustomMetric} /> - : <GraphsLegendStatic series={series} />} - <div className="project-activity-graph"> - <AutoSizer> - {({ height, width }) => - <div> - <AdvancedTimeline - endDate={this.props.graphEndDate} - height={height} - width={width} - interpolate="linear" - formatYTick={this.formatValue} - leakPeriodDate={this.props.leakPeriodDate} - metricType={this.props.metricsType} - selectedDate={this.props.selectedDate} - series={series} - showAreas={['coverage', 'duplications'].includes(graph)} - startDate={this.props.graphStartDate} - updateSelectedDate={this.props.updateSelectedDate} - updateTooltip={this.updateTooltip} - updateZoom={this.props.updateGraphZoom} - /> - {selectedDate != null && - tooltipXPos != null && - <GraphsTooltips - events={this.getSelectedDateEvents()} - formatValue={this.formatValue} - graph={graph} - graphWidth={width} - measuresHistory={this.props.measuresHistory} - selectedDate={selectedDate} - series={series} - tooltipIdx={tooltipIdx} - tooltipPos={tooltipXPos} - />} - </div>} - </AutoSizer> + + if (this.props.loading) { + return ( + <div className="project-activity-graph-container"> + <div className="text-center"> + <i className="spinner" /> + </div> </div> + ); + } + + if (!hasHistoryData(series)) { + return ( + <div className="project-activity-graph-container"> + <div className="note text-center"> + {translate( + isCustom + ? 'project_activity.graphs.custom.no_history' + : 'component_measures.no_history' + )} + </div> + </div> + ); + } + const events = this.getSelectedDateEvents(); + const showAreas = ['coverage', 'duplications'].includes(graph); + return ( + <div className="project-activity-graphs"> + {this.props.graphs.map((series, idx) => + <GraphHistory + key={idx} + events={events} + graph={graph} + graphEndDate={this.props.graphEndDate} + graphStartDate={this.props.graphStartDate} + isCustom={isCustom} + leakPeriodDate={this.props.leakPeriodDate} + measuresHistory={this.props.measuresHistory} + metricsType={getSeriesMetricType(series)} + removeCustomMetric={this.props.removeCustomMetric} + selectedDate={this.state.selectedDate} + series={series} + showAreas={showAreas} + updateGraphZoom={this.props.updateGraphZoom} + updateSelectedDate={this.props.updateSelectedDate} + updateTooltip={this.updateTooltip} + /> + )} </div> ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js index 80e881c755a..a743645085c 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js @@ -30,10 +30,8 @@ import { generateSeries, getDisplayedHistoryMetrics, getSeriesMetricType, - hasHistoryData, historyQueryChanged } from '../utils'; -import { translate } from '../../../helpers/l10n'; import type { RawQuery } from '../../../helpers/query'; import type { Analysis, MeasureHistory, Metric, Query } from '../types'; import type { Serie } from '../../../components/charts/AdvancedTimeline'; @@ -192,55 +190,6 @@ export default class ProjectActivityGraphs extends React.PureComponent { } }; - renderGraphs() { - const { leakPeriodDate, loading, query } = this.props; - const { graphEndDate, graphs, graphStartDate, series } = this.state; - const isCustom = isCustomGraph(query.graph); - - if (loading) { - return ( - <div className="project-activity-graph-container"> - <div className="text-center"> - <i className="spinner" /> - </div> - </div> - ); - } - - if (!hasHistoryData(series)) { - return ( - <div className="project-activity-graph-container"> - <div className="note text-center"> - {translate( - isCustom - ? 'project_activity.graphs.custom.no_history' - : 'component_measures.no_history' - )} - </div> - </div> - ); - } - - return graphs.map((series, idx) => - <GraphsHistory - key={idx} - analyses={this.props.analyses} - eventFilter={query.category} - graph={query.graph} - graphEndDate={graphEndDate} - graphStartDate={graphStartDate} - leakPeriodDate={leakPeriodDate} - measuresHistory={this.props.measuresHistory} - metricsType={getSeriesMetricType(series)} - removeCustomMetric={this.removeCustomMetric} - selectedDate={this.props.query.selectedDate} - series={series} - updateGraphZoom={this.updateGraphZoom} - updateSelectedDate={this.updateSelectedDate} - /> - ); - } - render() { const { leakPeriodDate, loading, metrics, query } = this.props; const { graphEndDate, graphStartDate, series } = this.state; @@ -255,7 +204,22 @@ export default class ProjectActivityGraphs extends React.PureComponent { selectedMetrics={this.props.query.customMetrics} updateGraph={this.updateGraph} /> - {this.renderGraphs()} + <GraphsHistory + analyses={this.props.analyses} + eventFilter={query.category} + graph={query.graph} + graphs={this.state.graphs} + graphEndDate={graphEndDate} + graphStartDate={graphStartDate} + leakPeriodDate={leakPeriodDate} + loading={loading} + measuresHistory={this.props.measuresHistory} + removeCustomMetric={this.removeCustomMetric} + selectedDate={this.props.query.selectedDate} + series={series} + updateGraphZoom={this.updateGraphZoom} + updateSelectedDate={this.updateSelectedDate} + /> <GraphsZoom graphEndDate={graphEndDate} graphStartDate={graphStartDate} diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphHistory-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphHistory-test.js new file mode 100644 index 00000000000..adeeb1afa0c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphHistory-test.js @@ -0,0 +1,57 @@ +/* + * 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 GraphHistory from '../GraphHistory'; + +const SERIES = [ + { + name: 'bugs', + translatedName: 'metric.bugs.name', + data: [ + { x: new Date('2016-10-27T16:33:50+0200'), y: 5 }, + { x: new Date('2016-10-27T12:21:15+0200'), y: 16 }, + { x: new Date('2016-10-26T12:17:29+0200'), y: 12 } + ] + } +]; + +const DEFAULT_PROPS = { + events: [], + graph: 'overview', + graphEndDate: null, + graphStartDate: null, + leakPeriodDate: '2017-05-16T13:50:02+0200', + isCustom: false, + measuresHistory: [], + metrics: [], + metricsType: 'INT', + removeCustomMetric: () => {}, + showAreas: true, + selectedDate: null, + series: SERIES, + updateGraphZoom: () => {}, + updateSelectedDate: () => {}, + updateTooltip: () => {} +}; + +it('should correctly render a graph', () => { + expect(shallow(<GraphHistory {...DEFAULT_PROPS} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsHistory-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsHistory-test.js index ab4fec25fb0..ea9e7c419b0 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsHistory-test.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsHistory-test.js @@ -72,11 +72,12 @@ const DEFAULT_PROPS = { analyses: ANALYSES, eventFilter: '', graph: 'overview', + graphs: [SERIES], graphEndDate: null, graphStartDate: null, leakPeriodDate: '2017-05-16T13:50:02+0200', + loading: false, measuresHistory: [], - metricsType: 'INT', removeCustomMetric: () => {}, selectedDate: null, series: SERIES, @@ -88,9 +89,37 @@ it('should correctly render a graph', () => { expect(shallow(<GraphsHistory {...DEFAULT_PROPS} />)).toMatchSnapshot(); }); +it('should correctly render multiple graphs', () => { + expect(shallow(<GraphsHistory {...DEFAULT_PROPS} graphs={[SERIES, SERIES]} />)).toMatchSnapshot(); +}); + it('should correctly filter events', () => { expect(shallow(<GraphsHistory {...DEFAULT_PROPS} />).instance().getEvents()).toMatchSnapshot(); expect( shallow(<GraphsHistory {...DEFAULT_PROPS} eventFilter="OTHER" />).instance().getEvents() ).toMatchSnapshot(); }); + +it('should show a loading view instead of the graph', () => { + expect( + shallow(<GraphsHistory {...DEFAULT_PROPS} loading={true} />).find('.spinner') + ).toHaveLength(1); +}); + +it('should show that there is no history data', () => { + expect(shallow(<GraphsHistory {...DEFAULT_PROPS} series={[]} />)).toMatchSnapshot(); + expect( + shallow( + <GraphsHistory + {...DEFAULT_PROPS} + series={[ + { + name: 'bugs', + translatedName: 'metric.bugs.name', + data: [{ x: new Date('2016-10-27T16:33:50+0200'), y: undefined }] + } + ]} + /> + ) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityGraphs-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityGraphs-test.js index 69327953ec2..4a6f3ba02e2 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityGraphs-test.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityGraphs-test.js @@ -90,39 +90,3 @@ it('should render correctly with filter history on dates', () => { ); expect(wrapper.state()).toMatchSnapshot(); }); - -it('should show a loading view instead of the graph', () => { - expect( - shallow(<ProjectActivityGraphs {...DEFAULT_PROPS} loading={true} />).find('.spinner') - ).toHaveLength(1); -}); - -it('should show that there is no history data', () => { - expect( - shallow( - <ProjectActivityGraphs - {...DEFAULT_PROPS} - measuresHistory={[{ metric: 'code_smells', history: [] }]} - /> - ) - ).toMatchSnapshot(); - expect( - shallow( - <ProjectActivityGraphs - {...DEFAULT_PROPS} - measuresHistory={[ - { - metric: 'code_smells', - history: [{ date: new Date('2016-10-26T12:17:29+0200'), value: undefined }] - } - ]} - query={{ - category: '', - graph: 'custom', - project: 'org.sonarsource.sonarqube:sonarqube', - customMetrics: ['code_smells'] - }} - /> - ) - ).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphHistory-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphHistory-test.js.snap new file mode 100644 index 00000000000..2b9e964ae1d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphHistory-test.js.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should correctly render a graph 1`] = ` +<div + className="project-activity-graph-container" +> + <GraphsLegendStatic + series={ + Array [ + Object { + "data": Array [ + Object { + "x": 2016-10-27T14:33:50.000Z, + "y": 5, + }, + Object { + "x": 2016-10-27T10:21:15.000Z, + "y": 16, + }, + Object { + "x": 2016-10-26T10:17:29.000Z, + "y": 12, + }, + ], + "name": "bugs", + "translatedName": "metric.bugs.name", + }, + ] + } + /> + <div + className="project-activity-graph" + > + <AutoSizer + onResize={[Function]} + /> + </div> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsHistory-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsHistory-test.js.snap index 7f82cd14330..0621e71f029 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsHistory-test.js.snap +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsHistory-test.js.snap @@ -27,9 +27,62 @@ Array [ exports[`should correctly render a graph 1`] = ` <div - className="project-activity-graph-container" + className="project-activity-graphs" +> + <GraphHistory + events={Array []} + graph="overview" + graphEndDate={null} + graphStartDate={null} + isCustom={false} + leakPeriodDate="2017-05-16T13:50:02+0200" + measuresHistory={Array []} + removeCustomMetric={[Function]} + selectedDate={null} + series={ + Array [ + Object { + "data": Array [ + Object { + "x": 2016-10-27T14:33:50.000Z, + "y": 5, + }, + Object { + "x": 2016-10-27T10:21:15.000Z, + "y": 16, + }, + Object { + "x": 2016-10-26T10:17:29.000Z, + "y": 12, + }, + ], + "name": "bugs", + "translatedName": "metric.bugs.name", + }, + ] + } + showAreas={false} + updateGraphZoom={[Function]} + updateSelectedDate={[Function]} + updateTooltip={[Function]} + /> +</div> +`; + +exports[`should correctly render multiple graphs 1`] = ` +<div + className="project-activity-graphs" > - <GraphsLegendStatic + <GraphHistory + events={Array []} + graph="overview" + graphEndDate={null} + graphStartDate={null} + isCustom={false} + leakPeriodDate="2017-05-16T13:50:02+0200" + measuresHistory={Array []} + removeCustomMetric={[Function]} + selectedDate={null} series={ Array [ Object { @@ -52,13 +105,71 @@ exports[`should correctly render a graph 1`] = ` }, ] } + showAreas={false} + updateGraphZoom={[Function]} + updateSelectedDate={[Function]} + updateTooltip={[Function]} /> + <GraphHistory + events={Array []} + graph="overview" + graphEndDate={null} + graphStartDate={null} + isCustom={false} + leakPeriodDate="2017-05-16T13:50:02+0200" + measuresHistory={Array []} + removeCustomMetric={[Function]} + selectedDate={null} + series={ + Array [ + Object { + "data": Array [ + Object { + "x": 2016-10-27T14:33:50.000Z, + "y": 5, + }, + Object { + "x": 2016-10-27T10:21:15.000Z, + "y": 16, + }, + Object { + "x": 2016-10-26T10:17:29.000Z, + "y": 12, + }, + ], + "name": "bugs", + "translatedName": "metric.bugs.name", + }, + ] + } + showAreas={false} + updateGraphZoom={[Function]} + updateSelectedDate={[Function]} + updateTooltip={[Function]} + /> +</div> +`; + +exports[`should show that there is no history data 1`] = ` +<div + className="project-activity-graph-container" +> + <div + className="note text-center" + > + component_measures.no_history + </div> +</div> +`; + +exports[`should show that there is no history data 2`] = ` +<div + className="project-activity-graph-container" +> <div - className="project-activity-graph" + className="note text-center" > - <AutoSizer - onResize={[Function]} - /> + component_measures.no_history </div> </div> `; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityGraphs-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityGraphs-test.js.snap index 3d4be8af2fa..5fccf4aef7c 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityGraphs-test.js.snap +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityGraphs-test.js.snap @@ -60,7 +60,33 @@ exports[`should render correctly the graph and legends 1`] = ` graph="overview" graphEndDate={null} graphStartDate={null} + graphs={ + Array [ + Array [ + Object { + "data": Array [ + Object { + "x": 2016-10-26T10:17:29.000Z, + "y": 2286, + }, + Object { + "x": 2016-10-27T10:21:15.000Z, + "y": 1749, + }, + Object { + "x": 2016-10-27T14:33:50.000Z, + "y": 500, + }, + ], + "name": "code_smells", + "translatedName": "Code Smells", + "type": "INT", + }, + ], + ] + } leakPeriodDate="2017-05-16T13:50:02+0200" + loading={false} measuresHistory={ Array [ Object { @@ -82,7 +108,6 @@ exports[`should render correctly the graph and legends 1`] = ` }, ] } - metricsType="INT" removeCustomMetric={[Function]} series={ Array [ @@ -195,113 +220,3 @@ Object { ], } `; - -exports[`should show that there is no history data 1`] = ` -<div - className="project-activity-layout-page-main-inner boxed-group boxed-group-inner" -> - <ProjectActivityGraphsHeader - addCustomMetric={[Function]} - graph="overview" - metrics={ - Array [ - Object { - "key": "code_smells", - "name": "Code Smells", - "type": "INT", - }, - ] - } - metricsTypeFilter={null} - updateGraph={[Function]} - /> - <div - className="project-activity-graph-container" - > - <div - className="note text-center" - > - component_measures.no_history - </div> - </div> - <GraphsZoom - graphEndDate={null} - graphStartDate={null} - leakPeriodDate="2017-05-16T13:50:02+0200" - loading={false} - metricsType="INT" - series={ - Array [ - Object { - "data": Array [], - "name": "code_smells", - "translatedName": "Code Smells", - "type": "INT", - }, - ] - } - showAreas={false} - updateGraphZoom={[Function]} - /> -</div> -`; - -exports[`should show that there is no history data 2`] = ` -<div - className="project-activity-layout-page-main-inner boxed-group boxed-group-inner" -> - <ProjectActivityGraphsHeader - addCustomMetric={[Function]} - graph="custom" - metrics={ - Array [ - Object { - "key": "code_smells", - "name": "Code Smells", - "type": "INT", - }, - ] - } - metricsTypeFilter={null} - selectedMetrics={ - Array [ - "code_smells", - ] - } - updateGraph={[Function]} - /> - <div - className="project-activity-graph-container" - > - <div - className="note text-center" - > - project_activity.graphs.custom.no_history - </div> - </div> - <GraphsZoom - graphEndDate={null} - graphStartDate={null} - leakPeriodDate="2017-05-16T13:50:02+0200" - loading={false} - metricsType="INT" - series={ - Array [ - Object { - "data": Array [ - Object { - "x": 2016-10-26T10:17:29.000Z, - "y": NaN, - }, - ], - "name": "code_smells", - "translatedName": "Code Smells", - "type": "INT", - }, - ] - } - showAreas={false} - updateGraphZoom={[Function]} - /> -</div> -`; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css index 5ef705363f2..8ef83fa028c 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css @@ -43,6 +43,14 @@ padding-top: 52px; } +.project-activity-graphs { + flex-grow: 1; + display: flex; + flex-direction: column; + align-items: stretch; + justify-content: center; +} + .project-activity-graph-container { padding: 10px 0; flex-grow: 1; diff --git a/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js b/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js index 872a1a8bee6..9578a6726f6 100644 --- a/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js +++ b/server/sonar-web/src/main/js/components/charts/AdvancedTimeline.js @@ -168,7 +168,7 @@ export default class AdvancedTimeline extends React.PureComponent { // $FlowFixMe selectedDate can't be null there p => p.x.valueOf() === selectedDate.valueOf() ); - const xRange = xScale.range(); + const xRange = xScale.range().sort(); const xPos = xScale(selectedDate); if (idx >= 0 && xPos >= xRange[0] && xPos <= xRange[1]) { return { |