New perf dashboard should have multiple dashboard pages
[WebKit-https.git] / Websites / perf.webkit.org / public / v2 / data.js
index b95dc64b6668be0e0cdf009a20ecfdd27745d0ba..dfe3133d323746e1130835086753d4d782761a1b 100755 (executable)
@@ -1,5 +1,54 @@
 // We don't use DS.Model for these object types because we can't afford to process millions of them.
 
+var PrivilegedAPI = {
+    _token: null,
+    _expiration: null,
+    _maxNetworkLatency: 3 * 60 * 1000 /* 3 minutes */,
+};
+
+PrivilegedAPI.sendRequest = function (url, parameters)
+{
+    return this._generateTokenInServerIfNeeded().then(function (token) {
+        return PrivilegedAPI._post(url, $.extend({token: token}, parameters));
+    });
+}
+
+PrivilegedAPI._generateTokenInServerIfNeeded = function ()
+{
+    var self = this;
+    return new Ember.RSVP.Promise(function (resolve, reject) {
+        if (self._token && self._expiration > Date.now() + self._maxNetworkLatency)
+            resolve(self._token);
+
+        PrivilegedAPI._post('generate-csrf-token')
+            .then(function (result, reject) {
+                self._token = result['token'];
+                self._expiration = new Date(result['expiration']);
+                resolve(self._token);
+            }).catch(reject);
+    });
+}
+
+PrivilegedAPI._post = function (url, parameters)
+{
+    return new Ember.RSVP.Promise(function (resolve, reject) {
+        $.ajax({
+            url: '../privileged-api/' + url,
+            type: 'POST',
+            contentType: 'application/json',
+            data: parameters ? JSON.stringify(parameters) : '{}',
+            dataType: 'json',
+        }).done(function (data) {
+            if (data.status != 'OK')
+                reject(data.status);
+            else
+                resolve(data);
+        }).fail(function (xhr, status, error) {
+            reject(xhr.status + (error ? ', ' + error : '') + '\n\nWith response:\n' + xhr.responseText);
+        });
+    });
+}
+
 var CommitLogs = {
     _cachedCommitsByRepository: {}
 };
@@ -27,8 +76,6 @@ CommitLogs.fetchForTimeRange = function (repository, from, to, keyword)
             return new Ember.RSVP.Promise(function (resolve) { resolve(cachedCommitsForRange); });
     }
 
-    console.log('Fecthing ' + url);
-
     return new Ember.RSVP.Promise(function (resolve, reject) {
         $.getJSON(url, function (data) {
             if (data.status != 'OK') {
@@ -94,8 +141,8 @@ function Measurement(rawData)
         revisions = {};
     this._raw['revisions'] = revisions;
 
-    for (var repositoryName in revisions) {
-        var commitTimeOrUndefined = revisions[repositoryName][1]; // e.g. ["162190", 1389945046000]
+    for (var repositoryId in revisions) {
+        var commitTimeOrUndefined = revisions[repositoryId][1]; // e.g. ["162190", 1389945046000]
         if (latestTime < commitTimeOrUndefined)
             latestTime = commitTimeOrUndefined;
     }
@@ -105,10 +152,10 @@ function Measurement(rawData)
     this._formattedRevisions = undefined;
 }
 
-Measurement.prototype.commitTimeForRepository = function (repositoryName)
+Measurement.prototype.commitTimeForRepository = function (repositoryId)
 {
     var revisions = this._raw['revisions'];
-    var rawData = revisions[repositoryName];
+    var rawData = revisions[repositoryId];
     if (!rawData)
         return null;
     return new Date(rawData[1]);
@@ -119,11 +166,11 @@ Measurement.prototype.formattedRevisions = function (previousMeasurement)
     var revisions = this._raw['revisions'];
     var previousRevisions = previousMeasurement ? previousMeasurement._raw['revisions'] : null;
     var formattedRevisions = {};
-    for (var repositoryName in revisions) {
-        var currentRevision = revisions[repositoryName][0];
-        var previousRevision = previousRevisions ? previousRevisions[repositoryName][0] : null;
+    for (var repositoryId in revisions) {
+        var currentRevision = revisions[repositoryId][0];
+        var previousRevision = previousRevisions ? previousRevisions[repositoryId][0] : null;
         var formatttedRevision = this._formatRevisionRange(previousRevision, currentRevision);
-        formattedRevisions[repositoryName] = formatttedRevision;
+        formattedRevisions[repositoryId] = formatttedRevision;
     }
 
     return formattedRevisions;
@@ -148,18 +195,18 @@ Measurement.prototype._formatRevisionRange = function (previousRevision, current
     } else if (currentRevision.indexOf(' ') >= 0) // e.g. 10.9 13C64.
         revisionDelimiter = ' - ';
     else if (currentRevision.length == 40) { // e.g. git hash
-        formattedCurrentHash = currentRevision.substring(0, 8);
+        var formattedCurrentHash = currentRevision.substring(0, 8);
         if (previousRevision)
             label = previousRevision.substring(0, 8) + '..' + formattedCurrentHash;
         else
-            label = 'At ' + formattedCurrentHash;
+            label = formattedCurrentHash;
     }
 
     if (!label) {
         if (previousRevision)
             label = revisionPrefix + previousRevision + revisionDelimiter + revisionPrefix + currentRevision;
         else
-            label = 'At ' + revisionPrefix + currentRevision;
+            label = revisionPrefix + currentRevision;
     }
 
     return {
@@ -220,6 +267,17 @@ Measurement._formatDate = function (date)
     return date.toISOString().replace('T', ' ').replace(/\.\d+Z$/, '');
 }
 
+Measurement.prototype.bugs = function ()
+{
+    return this._raw['bugs'];
+}
+
+Measurement.prototype.hasBugs = function ()
+{
+    var bugs = this.bugs();
+    return bugs && Object.keys(bugs).length;
+}
+
 function RunsData(rawData)
 {
     this._measurements = rawData.map(function (run) { return new Measurement(run); });
@@ -297,6 +355,23 @@ function TimeSeries(series)
     this._max = max;
 }
 
+TimeSeries.prototype.findPointByMeasurementId = function (measurementId)
+{
+    return this._series.find(function (point) { return point.measurement.id() == measurementId; });
+}
+
+TimeSeries.prototype.findPointAfterTime = function (time)
+{
+    return this._series.find(function (point) { return point.time >= time; });
+}
+
+TimeSeries.prototype.seriesBetweenPoints = function (startPoint, endPoint)
+{
+    if (!startPoint.seriesIndex || !endPoint.seriesIndex)
+        return null;
+    return this._series.slice(startPoint.seriesIndex, endPoint.seriesIndex + 1);
+}
+
 TimeSeries.prototype.minMaxForTimeRange = function (startTime, endTime)
 {
     var data = this._series;
@@ -330,9 +405,23 @@ TimeSeries.prototype.minMaxForTimeRange = function (startTime, endTime)
 
 TimeSeries.prototype.series = function () { return this._series; }
 
+TimeSeries.prototype.lastPoint = function ()
+{
+    if (!this._series || !this._series.length)
+        return null;
+    return this._series[this._series.length - 1];
+}
+
 TimeSeries.prototype.previousPoint = function (point)
 {
     if (!point.seriesIndex)
         return null;
     return this._series[point.seriesIndex - 1];
 }
+
+TimeSeries.prototype.nextPoint = function (point)
+{
+    if (!point.seriesIndex)
+        return null;
+    return this._series[point.seriesIndex + 1];
+}