Show a spinner while fetching data on summary page
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 May 2016 07:31:58 +0000 (07:31 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 May 2016 07:31:58 +0000 (07:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157658

Reviewed by Darin Adler.

Show a spinner while fetching JSON files on the summary page.

* public/v3/components/base.js:
(ComponentBase.prototype.renderReplace): Added a new implementation that simply calls the static version.
(ComponentBase.renderReplace): Made this static.

* public/v3/pages/summary-page.js:
(SummaryPage.prototype._constructRatioGraph): Show a spinner icon when SummaryPageConfigurationGroup's
isFetching returns true.
(SummaryPage.cssTemplate): Force the height of each cell to be 2.5rem so that the height of cell doesn't
change when a spinner is replaced by a ratio bar graph.

(SummaryPageConfigurationGroup): Added this._isFetching as an instance variable.
(SummaryPageConfigurationGroup.prototype.isFetching): Added.
(SummaryPageConfigurationGroup.prototype.fetchAndComputeSummary): Set this._isFetching while waiting for
the promises to resolve after 50ms. We don't immediately set this._isFetching to avoid FOC when all JSON
files have been cached.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200818 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Websites/perf.webkit.org/ChangeLog
Websites/perf.webkit.org/public/v3/components/base.js
Websites/perf.webkit.org/public/v3/pages/summary-page.js

index 089f6ad..a084c92 100644 (file)
@@ -1,3 +1,28 @@
+2016-05-13  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Show a spinner while fetching data on summary page
+        https://bugs.webkit.org/show_bug.cgi?id=157658
+
+        Reviewed by Darin Adler.
+
+        Show a spinner while fetching JSON files on the summary page.
+
+        * public/v3/components/base.js:
+        (ComponentBase.prototype.renderReplace): Added a new implementation that simply calls the static version.
+        (ComponentBase.renderReplace): Made this static.
+
+        * public/v3/pages/summary-page.js:
+        (SummaryPage.prototype._constructRatioGraph): Show a spinner icon when SummaryPageConfigurationGroup's
+        isFetching returns true.
+        (SummaryPage.cssTemplate): Force the height of each cell to be 2.5rem so that the height of cell doesn't
+        change when a spinner is replaced by a ratio bar graph.
+
+        (SummaryPageConfigurationGroup): Added this._isFetching as an instance variable.
+        (SummaryPageConfigurationGroup.prototype.isFetching): Added.
+        (SummaryPageConfigurationGroup.prototype.fetchAndComputeSummary): Set this._isFetching while waiting for
+        the promises to resolve after 50ms. We don't immediately set this._isFetching to avoid FOC when all JSON
+        files have been cached.
+
 2016-05-07  Ryosuke Niwa  <rniwa@webkit.org>
 
         Add horizontal between categories of tests
 2016-05-07  Ryosuke Niwa  <rniwa@webkit.org>
 
         Add horizontal between categories of tests
index 05160ad..4f7ab83 100644 (file)
@@ -12,7 +12,9 @@ class ComponentBase {
     content() { return this._shadow; }
     render() { }
 
     content() { return this._shadow; }
     render() { }
 
-    renderReplace(element, content)
+    renderReplace(element, content) { ComponentBase.renderReplace(element, content); }
+
+    static renderReplace(element, content)
     {
         element.innerHTML = '';
         if (content)
     {
         element.innerHTML = '';
         if (content)
index ffd844d..b7bae6b 100644 (file)
@@ -94,8 +94,20 @@ class SummaryPage extends PageWithHeading {
         var ratioGraph = new RatioBarGraph();
 
         var state = ChartsPage.createStateForConfigurationList(configurationList);
         var ratioGraph = new RatioBarGraph();
 
         var state = ChartsPage.createStateForConfigurationList(configurationList);
-        var anchor = link(ratioGraph, this.router().url('charts', state));
+
+        if (configurationList.length == 0) {
+            this._renderQueue.push(function () { ratioGraph.render(); });
+            return element('td', ratioGraph);
+        }
+
+        var cell = element('td');
+        var url = this.router().url('charts', state);
         this._renderQueue.push(function () {
         this._renderQueue.push(function () {
+            if (configurationGroup.isFetching()) {
+                ComponentBase.renderReplace(cell, new SpinnerIcon);
+                return;
+            }
+
             var warnings = configurationGroup.warnings();
             var warningText = '';
             for (var type in warnings) {
             var warnings = configurationGroup.warnings();
             var warningText = '';
             for (var type in warnings) {
@@ -103,14 +115,13 @@ class SummaryPage extends PageWithHeading {
                 warningText += `Missing ${type} for following platform(s): ${platformString}`;
             }
 
                 warningText += `Missing ${type} for following platform(s): ${platformString}`;
             }
 
-            anchor.title = warningText || 'Open charts';
+            ComponentBase.renderReplace(cell, link(ratioGraph, warningText || 'Open charts', url));
+
             ratioGraph.update(configurationGroup.ratio(), configurationGroup.label(), !!warningText);
             ratioGraph.render();
         });
             ratioGraph.update(configurationGroup.ratio(), configurationGroup.label(), !!warningText);
             ratioGraph.render();
         });
-        if (configurationList.length == 0)
-            return element('td', ratioGraph);
 
 
-        return element('td', anchor);
+        return cell;
     }
 
     static htmlTemplate()
     }
 
     static htmlTemplate()
@@ -167,14 +178,24 @@ class SummaryPage extends PageWithHeading {
             }
 
             .summary-table tbody td {
             }
 
             .summary-table tbody td {
+                position: relative;
                 font-weight: inherit;
                 font-size: 0.9rem;
                 font-weight: inherit;
                 font-size: 0.9rem;
+                height: 2.5rem;
                 padding: 0;
             }
 
             .summary-table td > * {
                 height: 100%;
             }
                 padding: 0;
             }
 
             .summary-table td > * {
                 height: 100%;
             }
+
+            .summary-table td spinner-icon {
+                display: block;
+                position: absolute;
+                top: 0.25rem;
+                left: calc(50% - 1rem);
+                z-index: 100;
+            }
         `;
     }
 }
         `;
     }
 }
@@ -188,6 +209,7 @@ class SummaryPageConfigurationGroup {
         this._ratio = null;
         this._label = null;
         this._warnings = {};
         this._ratio = null;
         this._label = null;
         this._warnings = {};
+        this._isFetching = false;
         this._smallerIsBetter = metrics.length ? metrics[0].isSmallerBetter() : null;
 
         for (var platform of platforms) {
         this._smallerIsBetter = metrics.length ? metrics[0].isSmallerBetter() : null;
 
         for (var platform of platforms) {
@@ -212,6 +234,7 @@ class SummaryPageConfigurationGroup {
     warnings() { return this._warnings; }
     changeType() { return this._changeType; }
     configurationList() { return this._configurationList; }
     warnings() { return this._warnings; }
     changeType() { return this._changeType; }
     configurationList() { return this._configurationList; }
+    isFetching() { return this._isFetching; }
 
     fetchAndComputeSummary(timeRange)
     {
 
     fetchAndComputeSummary(timeRange)
     {
@@ -223,7 +246,19 @@ class SummaryPageConfigurationGroup {
         for (var set of this._measurementSets)
             promises.push(this._fetchAndComputeRatio(set, timeRange));
 
         for (var set of this._measurementSets)
             promises.push(this._fetchAndComputeRatio(set, timeRange));
 
-        return Promise.all(promises).then(this._computeSummary.bind(this));
+        var self = this;
+        var fetched = false;
+        setTimeout(function () {
+            // Don't set _isFetching to true if all promises were to resolve immediately (cached).
+            if (!fetched)
+                self._isFetching = true;
+        }, 50);
+
+        return Promise.all(promises).then(function () {
+            fetched = true;
+            self._isFetching = false;
+            self._computeSummary();
+        });
     }
 
     _computeSummary()
     }
 
     _computeSummary()