From 8a457c9d5d80c5e618fd9c79a366cbfc2746e8f2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Wed, 28 Jun 2017 10:48:55 +0200 Subject: [PATCH] Fix project history data loading bug when a graph is saved in localstorage --- .../apps/overview/components/OverviewApp.js | 10 ++-- .../components/ProjectActivityAnalysesList.js | 8 ++- .../components/ProjectActivityApp.js | 7 ++- .../components/ProjectActivityAppContainer.js | 57 +++++++++++-------- .../__tests__/ProjectActivityApp-test.js | 2 + .../ProjectActivityApp-test.js.snap | 1 + .../ProjectActivityGraphs-test.js.snap | 10 ++-- .../src/main/js/apps/projectActivity/utils.js | 6 +- .../icons-components/ProjectEventIcon.js | 2 +- .../src/main/less/components/graphics.less | 4 ++ 10 files changed, 67 insertions(+), 40 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js index b9071b92d74..2be253ef9f6 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js @@ -19,13 +19,15 @@ */ // @flow import React from 'react'; +import { uniq } from 'lodash'; import moment from 'moment'; import QualityGate from '../qualityGate/QualityGate'; import BugsAndVulnerabilities from '../main/BugsAndVulnerabilities'; import CodeSmells from '../main/CodeSmells'; import Coverage from '../main/Coverage'; import Duplications from '../main/Duplications'; -import Meta from './../meta/Meta'; +import Meta from '../meta/Meta'; +import throwGlobalError from '../../../app/utils/throwGlobalError'; import { getMeasuresAndMeta } from '../../../api/measures'; import { getAllTimeMachineData } from '../../../api/time-machine'; import { enhanceMeasuresWithMetrics } from '../../../helpers/measures'; @@ -95,11 +97,11 @@ export default class OverviewApp extends React.PureComponent { periods: r.periods }); } - }); + }, throwGlobalError); } loadHistory(component: Component) { - const metrics = HISTORY_METRICS_LIST.concat(GRAPHS_METRICS[getGraph()]); + const metrics = uniq(HISTORY_METRICS_LIST.concat(GRAPHS_METRICS[getGraph()])); return getAllTimeMachineData(component.key, metrics).then(r => { if (this.mounted) { const history: History = {}; @@ -113,7 +115,7 @@ export default class OverviewApp extends React.PureComponent { const historyStartDate = history[HISTORY_METRICS_LIST[0]][0].date; this.setState({ history, historyStartDate }); } - }); + }, throwGlobalError); } renderLoading() { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js index d0655faec68..368ecf5abe9 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js @@ -21,6 +21,7 @@ import React from 'react'; import classNames from 'classnames'; import moment from 'moment'; +import { throttle } from 'lodash'; import ProjectActivityAnalysis from './ProjectActivityAnalysis'; import FormattedDate from '../../../components/ui/FormattedDate'; import { translate } from '../../../helpers/l10n'; @@ -45,6 +46,11 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { badges: HTMLCollection; props: Props; + constructor(props: Props) { + super(props); + this.handleScroll = throttle(this.handleScroll, 20); + } + componentDidMount() { this.badges = document.getElementsByClassName('project-activity-version-badge'); } @@ -107,7 +113,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent { onScroll={this.handleScroll} ref={element => (this.scrollContainer = element)}> {byVersionByDay.map((version, idx) => ( -
  • +
  • {version.version &&
    diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js index 1904f8d975d..9b4f2a595dd 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js @@ -37,6 +37,7 @@ type Props = { changeEvent: (event: string, name: string) => Promise<*>, deleteAnalysis: (analysis: string) => Promise<*>, deleteEvent: (analysis: string, event: string) => Promise<*>, + graphLoading: boolean, loading: boolean, project: { configuration?: { showHistory: boolean }, key: string, leakPeriodDate: string }, metrics: Array, @@ -87,7 +88,7 @@ export default class ProjectActivityApp extends React.PureComponent { }; render() { - const { loading, measuresHistory, query } = this.props; + const { measuresHistory, query } = this.props; const { filteredAnalyses } = this.state; const { configuration } = this.props.project; const canAdmin = configuration ? configuration.showHistory : false; @@ -109,14 +110,14 @@ export default class ProjectActivityApp extends React.PureComponent { changeEvent={this.props.changeEvent} deleteAnalysis={this.props.deleteAnalysis} deleteEvent={this.props.deleteEvent} - loading={loading} + loading={this.props.loading} />
    ): Promise> => - getAllTimeMachineData(this.props.project.key, metrics).then( + fetchMeasuresHistory = (metrics: Array): Promise> => { + return getAllTimeMachineData(this.props.project.key, metrics).then( ({ measures }) => measures.map(measure => ({ metric: measure.metric, @@ -169,6 +169,7 @@ class ProjectActivityAppContainer extends React.PureComponent { })), throwGlobalError ); + }; fetchMetrics = (): Promise> => getMetrics().catch(throwGlobalError); @@ -197,31 +198,41 @@ class ProjectActivityAppContainer extends React.PureComponent { firstLoadData() { const { query } = this.state; const graphMetrics = GRAPHS_METRICS[query.graph]; + const ignoreHistory = this.shouldRedirect(); Promise.all([ this.fetchActivity(query.project, 1, 100, serializeQuery(query)), this.fetchMetrics(), - this.fetchMeasuresHistory(graphMetrics) + ignoreHistory ? Promise.resolve() : this.fetchMeasuresHistory(graphMetrics) ]).then(response => { if (this.mounted) { - this.setState({ - analyses: response[0].analyses, - analysesLoading: true, - graphLoading: false, - loading: false, - metrics: response[1], - measuresHistory: response[2], - paging: response[0].paging - }); - - this.loadAllActivities(query.project).then(({ analyses, paging }) => { - if (this.mounted) { + setTimeout(() => { + const newState = { + analyses: response[0].analyses, + analysesLoading: true, + loading: false, + metrics: response[1], + paging: response[0].paging + }; + if (ignoreHistory) { + this.setState(newState); + } else { this.setState({ - analyses, - analysesLoading: false, - paging + ...newState, + graphLoading: false, + measuresHistory: response[2] }); } - }); + + this.loadAllActivities(query.project).then(({ analyses, paging }) => { + if (this.mounted) { + this.setState({ + analyses, + analysesLoading: false, + paging + }); + } + }); + }, 1000); } }); } @@ -273,7 +284,7 @@ class ProjectActivityAppContainer extends React.PureComponent { changeEvent={this.changeEvent} deleteAnalysis={this.deleteAnalysis} deleteEvent={this.deleteEvent} - graphLoading={this.state.graphLoading} + graphLoading={this.state.loading || this.state.graphLoading} loading={this.state.loading} metrics={this.state.metrics} measuresHistory={this.state.measuresHistory} diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js index e6122763349..22f85b2a28f 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js @@ -60,9 +60,11 @@ const DEFAULT_PROPS = { addCustomEvent: () => {}, addVersion: () => {}, analyses: ANALYSES, + analysesLoading: false, changeEvent: () => {}, deleteAnalysis: () => {}, deleteEvent: () => {}, + graphLoading: false, loading: false, project: { key: 'org.sonarsource.sonarqube:sonarqube', diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap index c34ab47e81c..0f5a433fbfe 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap @@ -103,6 +103,7 @@ exports[`should render correctly 1`] = ` }, ] } + analysesLoading={false} canAdmin={false} changeEvent={[Function]} className="boxed-group-inner" 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 67899574868..920f463b1ea 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 @@ -46,8 +46,8 @@ exports[`should render correctly the graph and legends 1`] = ` ] } eventFilter="" - graphEndDate={null} - graphStartDate={null} + graphEndDate={2016-10-27T14:33:50.000Z} + graphStartDate={2016-10-26T10:17:29.000Z} leakPeriodDate="2017-05-16T13:50:02+0200" loading={false} metricsType="INT" @@ -79,8 +79,8 @@ exports[`should render correctly the graph and legends 1`] = ` updateGraphZoom={[Function]} /> ): Array<{ version: ?string, + key: ?string, byDay: { [string]: Array } }> => analyses.reduce((acc, analysis) => { if (acc.length === 0) { - acc.push({ version: undefined, byDay: {} }); + acc.push({ version: undefined, key: undefined, byDay: {} }); } const currentVersion = acc[acc.length - 1]; const day = moment(analysis.date).startOf('day').valueOf().toString(); @@ -122,7 +123,8 @@ export const getAnalysesByVersionByDay = ( const lastEvent = sortedEvents[sortedEvents.length - 1]; if (lastEvent && lastEvent.category === 'VERSION') { currentVersion.version = lastEvent.name; - acc.push({ version: undefined, byDay: {} }); + currentVersion.key = lastEvent.key; + acc.push({ version: undefined, key: undefined, byDay: {} }); } return acc; }, []); diff --git a/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js b/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js index 985d68baae3..747cc2bfbce 100644 --- a/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js +++ b/server/sonar-web/src/main/js/components/icons-components/ProjectEventIcon.js @@ -32,7 +32,7 @@ export default function ProjectEventIcon({ className, size = 14 }: Props) { width={size} height={size}> diff --git a/server/sonar-web/src/main/less/components/graphics.less b/server/sonar-web/src/main/less/components/graphics.less index 916fea38a74..07e7b5857e3 100644 --- a/server/sonar-web/src/main/less/components/graphics.less +++ b/server/sonar-web/src/main/less/components/graphics.less @@ -276,6 +276,10 @@ .line-chart-path { clip-path: url(#chart-clip); } + + .leak-chart-rect { + clip-path: url(#chart-clip); + } } .chart-zoom-tick { -- 2.39.5