]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9605 Fix infinite spinner on project activity page
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Wed, 16 Aug 2017 09:56:17 +0000 (11:56 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Thu, 17 Aug 2017 14:42:34 +0000 (16:42 +0200)
server/sonar-web/src/main/js/apps/projectActivity/components/GraphsHistory.js
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppContainer.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsHistory-test.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap

index 252473187193b442e8ff5cafe8a8e4c91c5a6b22..4e5be7ea5db69f9b4b991f31540afc15e667a33f 100644 (file)
@@ -20,6 +20,7 @@
 import React from 'react';
 import moment from 'moment';
 import { isEqual, sortBy } from 'lodash';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
 import GraphHistory from './GraphHistory';
 import { EVENT_TYPES, getSeriesMetricType, hasHistoryData, isCustomGraph } from '../utils';
 import { translate } from '../../../helpers/l10n';
@@ -109,14 +110,14 @@ export default class GraphsHistory extends React.PureComponent {
   updateTooltip = (selectedDate /*: ?Date */) => this.setState({ selectedDate });
 
   render() {
-    const { graph, series } = this.props;
+    const { graph, loading, series } = this.props;
     const isCustom = isCustomGraph(graph);
 
-    if (this.props.loading) {
+    if (loading) {
       return (
         <div className="project-activity-graph-container">
           <div className="text-center">
-            <i className="spinner" />
+            <DeferredSpinner className="" loading={loading} />
           </div>
         </div>
       );
index e6a4b4f24b2669f1f9f98dca5deb8232015a3730..7f69288c33d974350fd7953343144dc41dec4484 100644 (file)
@@ -44,7 +44,7 @@ type Props = {
   changeEvent: (event: string, name: string) => Promise<*>,
   deleteAnalysis: (analysis: string) => Promise<*>,
   deleteEvent: (analysis: string, event: string) => Promise<*>,
-  loading: boolean,
+  initializing: boolean,
   project: { qualifier: string },
   query: Query,
   updateQuery: Object => void
@@ -155,7 +155,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
     if (this.props.analyses.length === 0 || !hasFilteredData) {
       return (
         <div className={this.props.className}>
-          {this.props.loading
+          {this.props.initializing
             ? <div className="text-center">
                 <i className="spinner" />
               </div>
index 717678a05617a66a22dcec4ee9a2106b188a6d02..cdc41b48e997826f460930a8377fe068d24a92cd 100644 (file)
@@ -38,7 +38,7 @@ type Props = {
   deleteAnalysis: (analysis: string) => Promise<*>,
   deleteEvent: (analysis: string, event: string) => Promise<*>,
   graphLoading: boolean,
-  loading: boolean,
+  initializing: boolean,
   project: {
     configuration?: { showHistory: boolean },
     key: string,
@@ -80,7 +80,7 @@ export default function ProjectActivityApp(props /*: Props */) {
             changeEvent={props.changeEvent}
             deleteAnalysis={props.deleteAnalysis}
             deleteEvent={props.deleteEvent}
-            loading={props.loading}
+            initializing={props.initializing}
             project={props.project}
             query={props.query}
             updateQuery={props.updateQuery}
index 1e212bc5f1340053c3701fd2c588202392b34833..61e9bd077c2729be243ef3a995426affcf7b2aaf 100644 (file)
@@ -225,36 +225,52 @@ class ProjectActivityAppContainer extends React.PureComponent {
       this.fetchActivity(query.project, 1, 100, serializeQuery(query)),
       this.fetchMetrics(),
       this.fetchMeasuresHistory(graphMetrics)
-    ]).then(response => {
-      if (this.mounted) {
-        this.setState({
-          analyses: response[0].analyses,
-          analysesLoading: true,
-          graphLoading: false,
-          initialized: true,
-          measuresHistory: response[2],
-          metrics: response[1],
-          paging: response[0].paging
-        });
+    ]).then(
+      response => {
+        if (this.mounted) {
+          this.setState({
+            analyses: response[0].analyses,
+            analysesLoading: true,
+            graphLoading: false,
+            initialized: true,
+            measuresHistory: response[2],
+            metrics: response[1],
+            paging: response[0].paging
+          });
 
-        this.loadAllActivities(query.project).then(({ analyses, paging }) => {
-          if (this.mounted) {
-            this.setState({
-              analyses,
-              analysesLoading: false,
-              paging
-            });
-          }
-        });
+          this.loadAllActivities(query.project).then(({ analyses, paging }) => {
+            if (this.mounted) {
+              this.setState({
+                analyses,
+                analysesLoading: false,
+                paging
+              });
+            }
+          });
+        }
+      },
+      () => {
+        if (this.mounted) {
+          this.setState({ initialized: true, analysesLoading: false, graphLoading: false });
+        }
       }
-    });
+    );
   }
 
   updateGraphData = (graph /*: string */, customMetrics /*: Array<string> */) => {
     const graphMetrics = getHistoryMetrics(graph, customMetrics);
     this.setState({ graphLoading: true });
-    this.fetchMeasuresHistory(graphMetrics).then((measuresHistory /*: Array<MeasureHistory> */) =>
-      this.setState({ graphLoading: false, measuresHistory })
+    this.fetchMeasuresHistory(graphMetrics).then(
+      (measuresHistory /*: Array<MeasureHistory> */) => {
+        if (this.mounted) {
+          this.setState({ graphLoading: false, measuresHistory });
+        }
+      },
+      () => {
+        if (this.mounted) {
+          this.setState({ graphLoading: false, measuresHistory: [] });
+        }
+      }
     );
   };
 
@@ -300,7 +316,7 @@ class ProjectActivityAppContainer extends React.PureComponent {
         deleteAnalysis={this.deleteAnalysis}
         deleteEvent={this.deleteEvent}
         graphLoading={!this.state.initialized || this.state.graphLoading}
-        loading={!this.state.initialized}
+        initializing={!this.state.initialized}
         metrics={this.state.metrics}
         measuresHistory={this.state.measuresHistory}
         project={this.props.project}
index 099b253622cfb0c9a497a45d39f9fa803e6ca24d..5a62d59c1fe993bbfbef2907b465ad333319f7e0 100644 (file)
@@ -103,7 +103,7 @@ it('should correctly filter events', () => {
 
 it('should show a loading view instead of the graph', () => {
   expect(
-    shallow(<GraphsHistory {...DEFAULT_PROPS} loading={true} />).find('.spinner')
+    shallow(<GraphsHistory {...DEFAULT_PROPS} loading={true} />).find('DeferredSpinner')
   ).toHaveLength(1);
 });
 
index c3d7833dd5dca8eef347e67f37d60de06ef1857f..30864a995f99b53bd22c3700bcc48b3948af7012 100644 (file)
@@ -77,7 +77,7 @@ const DEFAULT_PROPS = {
   changeEvent: () => {},
   deleteAnalysis: () => {},
   deleteEvent: () => {},
-  loading: false,
+  inizializing: false,
   project: { qualifier: 'TRK' },
   query: { category: '', graph: DEFAULT_GRAPH, project: 'org.sonarsource.sonarqube:sonarqube' },
   updateQuery: () => {}
index 6f3655c42ec68f85d96b1d477f808cf306392194..1d3d5cec2901a4a76946f9174292b22c82af3d5b 100644 (file)
@@ -66,7 +66,7 @@ const DEFAULT_PROPS = {
   deleteAnalysis: () => {},
   deleteEvent: () => {},
   graphLoading: false,
-  loading: false,
+  initializing: false,
   project: {
     key: 'org.sonarsource.sonarqube:sonarqube',
     leakPeriodDate: '2017-05-16T13:50:02+0200'
index 9a69a6e5a04e281983f4293358ae38029eb710de..64f9f8018aca928043af4696b83b6e62d4b111da 100644 (file)
@@ -70,7 +70,7 @@ exports[`should render correctly 1`] = `
         className="boxed-group-inner"
         deleteAnalysis={[Function]}
         deleteEvent={[Function]}
-        loading={false}
+        initializing={false}
         project={
           Object {
             "key": "org.sonarsource.sonarqube:sonarqube",