Bug 1374298 - Revisit the ping selection in about:telemetry r?chutten draft
authorflyingrub <flyinggrub@gmail.com>
Thu, 29 Jun 2017 16:44:03 +0200
changeset 605298 be6faca182a60a98cca4c6343e1abdc71cd3263f
parent 604781 cb705f970cba61b094c10dbe6d059e1f0c88730b
child 605363 338d8f6660483e105bca44be4e65e5dfc09fccb5
push id67358
push userbmo:flyinggrub@gmail.com
push dateFri, 07 Jul 2017 10:44:34 +0000
reviewerschutten
bugs1374298
milestone56.0a1
Bug 1374298 - Revisit the ping selection in about:telemetry r?chutten Use a select with 3 optgroup (Today, Yesterday, Older) to sort ping. MozReview-Commit-ID: 4Imw0cI3zxk
toolkit/content/aboutTelemetry.js
toolkit/content/aboutTelemetry.xhtml
toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -178,16 +178,25 @@ function padToTwoDigits(n) {
  */
 function yesterday(date) {
   let d = new Date(date);
   d.setDate(d.getDate() - 1);
   return d;
 }
 
 /**
+ * Return tomorrow's date with the same time.
+ */
+function tomorrow(date) {
+  let d = new Date(date);
+  d.setDate(d.getDate() + 1);
+  return d;
+}
+
+/**
  * This returns a short date string of the form YYYY/MM/DD.
  */
 function shortDateString(date) {
   return date.getFullYear()
          + "/" + padToTwoDigits(date.getMonth() + 1)
          + "/" + padToTwoDigits(date.getDate());
 }
 
@@ -292,20 +301,16 @@ var PingPicker = {
     for (let el of displays) {
       el.addEventListener("change", () => this.onPingDisplayChanged());
     }
 
     document.getElementById("show-subsession-data").addEventListener("change", () => {
       this._updateCurrentPingData();
     });
 
-    document.getElementById("choose-ping-week").addEventListener("change", () => {
-      this._renderPingList();
-      this._updateArchivedPingData();
-    });
     document.getElementById("choose-ping-id").addEventListener("change", () => {
       this._updateArchivedPingData();
     });
     document.getElementById("choose-ping-type").addEventListener("change", () => {
       this.filterDisplayedPings();
     });
 
 
@@ -349,16 +354,17 @@ var PingPicker = {
     let pings = bundle.GetStringFromName("pingExplanationLink");
     let pingLink = "<a href=\"http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/concepts/pings.html\">&quot;" + pings + "&quot;</a>";
     let pingName = this._getSelectedPingName();
 
     let pingDate = document.getElementById("ping-date");
     pingDate.textContent = pingName;
     pingDate.setAttribute("title", pingName);
 
+    // Display the type and controls if the ping is not current
     let pingType = document.getElementById("ping-type");
     let older = document.getElementById("older-ping");
     let newer = document.getElementById("newer-ping");
     if (pingName !== "current") {
       pingType.hidden = false;
       older.hidden = false;
       newer.hidden = false;
       pingType.textContent = this._getSelectedPingType();
@@ -415,180 +421,158 @@ var PingPicker = {
     if (!ping) {
       return;
     }
     displayPingData(ping, true);
   },
 
   _updateArchivedPingData() {
     let id = this._getSelectedPingId();
-    return TelemetryArchive.promiseArchivedPingById(id)
-                           .then((ping) => displayPingData(ping, true));
+    let res = Promise.resolve();
+    if (id) {
+      res = TelemetryArchive.promiseArchivedPingById(id)
+                            .then((ping) => displayPingData(ping, true));
+    }
+    return res;
   },
 
   async _updateArchivedPingList(pingList) {
     // The archived ping list is sorted in ascending timestamp order,
     // but descending is more practical for the operations we do here.
     pingList.reverse();
-
     this._archivedPings = pingList;
-
-    // Collect the start dates for all the weeks we have pings for.
-    let weekStart = (date) => {
-      let weekDay = (date.getDay() + 6) % 7;
-      let monday = new Date(date);
-      monday.setDate(date.getDate() - weekDay);
-      return TelemetryUtils.truncateToDays(monday);
-    };
-
-    let weekStartDates = new Set();
-    for (let p of pingList) {
-      weekStartDates.add(weekStart(new Date(p.timestampCreated)).getTime());
-    }
-
-    // Build a list of the week date ranges we have ping data for.
-    let plusOneWeek = (date) => {
-      let d = date;
-      d.setDate(d.getDate() + 7);
-      return d;
-    };
-
-    this._weeks = Array.from(weekStartDates.values(), startTime => ({
-      startDate: new Date(startTime),
-      endDate: plusOneWeek(new Date(startTime)),
-    }));
-
     // Render the archive data.
-    this._renderWeeks();
     this._renderPingList();
-
     // Update the displayed ping.
     await this._updateArchivedPingData();
   },
 
-  _renderWeeks() {
-    let weekSelector = document.getElementById("choose-ping-week");
-    removeAllChildNodes(weekSelector);
-
-    for (let week of this._weeks) {
-      let text = shortDateString(week.startDate)
-                 + " - " + shortDateString(yesterday(week.endDate));
-
-      let option = document.createElement("option");
-      let content = document.createTextNode(text);
-      option.appendChild(content);
-      weekSelector.appendChild(option);
-    }
-  },
-
-  _getSelectedWeek() {
-    let weekSelector = document.getElementById("choose-ping-week");
-    return this._weeks[weekSelector.selectedIndex];
-  },
-
-  _renderPingList(id = null) {
+  _renderPingList() {
     let pingSelector = document.getElementById("choose-ping-id");
-    removeAllChildNodes(pingSelector);
-
-    let weekRange = this._getSelectedWeek();
-    let pings = this._archivedPings.filter(
-      (p) => p.timestampCreated >= weekRange.startDate.getTime() &&
-             p.timestampCreated < weekRange.endDate.getTime());
+    Array.from(pingSelector.children).forEach((child) => removeAllChildNodes(child));
 
     let pingTypes = new Set();
     pingTypes.add(this.TYPE_ALL);
-    for (let p of pings) {
+    let todayString =  (new Date()).toDateString();
+    let yesterdayString = yesterday(new Date()).toDateString();
+    for (let p of this._archivedPings) {
       pingTypes.add(p.type);
       let date = new Date(p.timestampCreated);
-      let text = shortDateString(date)
-                 + " " + shortTimeString(date);
+      let datetext = date.toLocaleDateString() + " " + shortTimeString(date);
+      let text = datetext + ", " + p.type;
 
       let option = document.createElement("option");
       let content = document.createTextNode(text);
       option.appendChild(content);
       option.setAttribute("value", p.id);
       option.dataset.type = p.type;
-      if (id && p.id == id) {
-        option.selected = true;
+      option.dataset.date = datetext;
+
+      if (date.toDateString() == todayString) {
+        pingSelector.children[0].appendChild(option);
+      } else if (date.toDateString() == yesterdayString) {
+        pingSelector.children[1].appendChild(option);
+      } else {
+        pingSelector.children[2].appendChild(option);
       }
-      pingSelector.appendChild(option);
     }
     this._renderPingTypes(pingTypes);
   },
 
-  filterDisplayedPings() {
-    let pingSelector = document.getElementById("choose-ping-id");
-    let typeSelector = document.getElementById("choose-ping-type");
-    let type = typeSelector.selectedOptions.item(0).value;
-    if (type == this.TYPE_ALL) {
-      Array.from(pingSelector.children).forEach((option) => option.hidden = false);
-      pingSelector.children[0].selected = true;
-    } else {
-      let first = true;
-      Array.from(pingSelector.children).forEach((option) => {
-        if (first && option.dataset.type == type) {
-          option.selected = true;
-          first = false;
-        }
-        option.hidden = option.dataset.type != type;
-      });
-    }
-    this._updateArchivedPingData();
-  },
-
   _renderPingTypes(pingTypes) {
     let pingTypeSelector = document.getElementById("choose-ping-type");
     removeAllChildNodes(pingTypeSelector);
     pingTypes.forEach((type) => {
       let option = document.createElement("option");
       option.appendChild(document.createTextNode(type));
       option.setAttribute("value", type);
       pingTypeSelector.appendChild(option);
     });
   },
 
+  _movePingIndex(offset) {
+    if (this.viewCurrentPingData) {
+      return;
+    }
+    let typeSelector = document.getElementById("choose-ping-type");
+    let type = typeSelector.selectedOptions.item(0).value;
+
+    let id = this._getSelectedPingId();
+    let index = this._archivedPings.findIndex((p) => p.id == id);
+    let newIndex = Math.min(Math.max(0, index + offset), this._archivedPings.length - 1);
+
+    let pingList;
+    if (offset > 0) {
+      pingList = this._archivedPings.slice(newIndex);
+    } else {
+      pingList = this._archivedPings.slice(0, newIndex);
+      pingList.reverse();
+    }
+
+    let ping = pingList.find((p) => {
+      return type == this.TYPE_ALL || p.type == type;
+    });
+
+    if (ping) {
+      this.selectPing(ping);
+      this._updateArchivedPingData();
+    }
+  },
+
+  selectPing(ping) {
+    let pingSelector = document.getElementById("choose-ping-id");
+    // Use some() to break if we find the ping.
+    Array.from(pingSelector.children).some((group) => {
+      return Array.from(group.children).some((option) => {
+        if (option.value == ping.id) {
+          option.selected = true;
+          return true;
+        }
+        return false;
+      });
+    });
+  },
+
+  filterDisplayedPings() {
+    let pingSelector = document.getElementById("choose-ping-id");
+    let typeSelector = document.getElementById("choose-ping-type");
+    let type = typeSelector.selectedOptions.item(0).value;
+    let first = true;
+    Array.from(pingSelector.children).forEach((group) => {
+      Array.from(group.children).forEach((option) => {
+        if (first && option.dataset.type == type) {
+          option.selected = true;
+          first = false;
+        }
+        option.hidden = (type != this.TYPE_ALL) && (option.dataset.type != type);
+      });
+    });
+    this._updateArchivedPingData();
+  },
+
   _getSelectedPingName() {
     if (this.viewCurrentPingData) return "current";
 
     let pingSelector = document.getElementById("choose-ping-id");
     let selected = pingSelector.selectedOptions.item(0);
-    return selected.textContent;
+    return selected.dataset.date;
   },
 
   _getSelectedPingType() {
     let pingSelector = document.getElementById("choose-ping-id");
     let selected = pingSelector.selectedOptions.item(0);
     return selected.dataset.type;
   },
 
   _getSelectedPingId() {
     let pingSelector = document.getElementById("choose-ping-id");
     let selected = pingSelector.selectedOptions.item(0);
     return selected.getAttribute("value");
   },
 
-  _movePingIndex(offset) {
-    if (this.viewCurrentPingData) {
-      return;
-    }
-    const id = this._getSelectedPingId();
-    const index = this._archivedPings.findIndex((p) => p.id == id);
-    const newIndex = Math.min(Math.max(index + offset, 0), this._archivedPings.length - 1);
-    const ping = this._archivedPings[newIndex];
-
-    const weekIndex = this._weeks.findIndex(
-      (week) => ping.timestampCreated >= week.startDate.getTime() &&
-                ping.timestampCreated < week.endDate.getTime());
-    const options = document.getElementById("choose-ping-week").options;
-    options.item(weekIndex).selected = true;
-
-    this._renderPingList(ping.id);
-    this._updateArchivedPingData();
-  },
-
   _showRawPingData() {
     show(document.getElementById("category-raw"));
   },
 
   _showStructuredPingData() {
     show(document.getElementById("category-home"));
   },
 };
--- a/toolkit/content/aboutTelemetry.xhtml
+++ b/toolkit/content/aboutTelemetry.xhtml
@@ -102,29 +102,30 @@
           <input type="radio" id="ping-source-archive" name="choose-ping-source" value="archive" />
           &aboutTelemetry.showArchivedPingData;
         </div>
         <div id="current-ping-picker">
           <input id="show-subsession-data" type="checkbox" checked="checked" />&aboutTelemetry.showSubsessionData;
         </div>
         <div id="archived-ping-picker" class="hidden">
           <h4 class="title">&aboutTelemetry.choosePing;</h4>
-          <button class="older-ping" type="button">&aboutTelemetry.showOlderPing;</button>
-          <button class="newer-ping" type="button">&aboutTelemetry.showNewerPing;</button>
-          <div>
-            <h4 class="title">&aboutTelemetry.archiveWeekHeader;</h4>
-            <select id="choose-ping-week"></select>
-          </div>
           <div>
             <h4 class="title">&aboutTelemetry.archivePingType;</h4>
             <select id="choose-ping-type"></select>
           </div>
           <div>
             <h4 class="title">&aboutTelemetry.archivePingHeader;</h4>
-            <select id="choose-ping-id"></select>
+            <select id="choose-ping-id">
+              <optgroup label="&aboutTelemetry.optionGroupToday;">
+              </optgroup>
+              <optgroup label="&aboutTelemetry.optionGroupYesterday;">
+              </optgroup>
+              <optgroup label="&aboutTelemetry.optionGroupOlder;">
+              </optgroup>
+            </select>
           </div>
         </div>
         <div>
           <h4 class="title">&aboutTelemetry.payloadChoiceHeader;</h4>
           <select id="choose-payload"></select>
         </div>
       </div>
 
--- a/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
@@ -43,16 +43,28 @@ Week
 <!ENTITY aboutTelemetry.archivePingType "
 Ping Type
 ">
 
 <!ENTITY aboutTelemetry.archivePingHeader "
 Ping
 ">
 
+<!ENTITY aboutTelemetry.optionGroupToday "
+Today
+">
+
+<!ENTITY aboutTelemetry.optionGroupYesterday "
+Yesterday
+">
+
+<!ENTITY aboutTelemetry.optionGroupOlder "
+Older
+">
+
 <!ENTITY aboutTelemetry.generalDataSection "
   General Data
 ">
 
 <!ENTITY aboutTelemetry.environmentDataSection "
   Environment Data
 ">