diff --git a/_attachments/partials/bug-details.html b/_attachments/partials/bug-details.html
index c42a5d3..a94db5c 100644
--- a/_attachments/partials/bug-details.html
+++ b/_attachments/partials/bug-details.html
@@ -5,15 +5,15 @@
Bug Summary
| Application version code: |
- {{bug.key[0]}} |
+ {{bug.value.appVersion}} |
| Exception: |
- {{bug.key[1]}} |
+ {{bug.value.exception}} |
| Root Exception: |
- {{bug.key[2]}} |
+ {{bug.value.rootCause}} |
| Solved: |
diff --git a/_attachments/partials/bugs-table.html b/_attachments/partials/bugs-table.html
index b97b69b..0341040 100644
--- a/_attachments/partials/bugs-table.html
+++ b/_attachments/partials/bugs-table.html
@@ -16,10 +16,10 @@
-
+
-
-
+
+
@@ -40,10 +40,10 @@
{{bug.value.count}}
{{bug.latest}}
- {{bug.key[0]}}
+ {{bug.value.appVersion}}
- {{bug.key[1]}}
- Caused by: {{bug.key[2]}}
+ {{bug.value.exception}}
+ Caused by: {{bug.value.rootCause}}
diff --git a/_attachments/partials/reports-table.html b/_attachments/partials/reports-table.html
index 81c7f51..e3b4cf7 100644
--- a/_attachments/partials/reports-table.html
+++ b/_attachments/partials/reports-table.html
@@ -18,14 +18,14 @@
-
+
{{report.displayDate}}
- {{report.value.application_version_name}}
- {{report.value.android_version}}
- {{report.value.device}}
+ {{report.doc.APP_VERSION_NAME}}
+ {{report.doc.ANDROID_VERSION}}
+ {{getDevice(report.doc)}}
- {{report.value.signature.digest}}
- Caused by: {{report.value.signature.rootCause}}
+ {{report.doc.SIGNATURE.full}}
+ Caused by: {{report.doc.SIGNATURE.rootCause}}
\ No newline at end of file
diff --git a/_attachments/script/DashboardControllers.js b/_attachments/script/DashboardControllers.js
index 497f57e..4e8a850 100644
--- a/_attachments/script/DashboardControllers.js
+++ b/_attachments/script/DashboardControllers.js
@@ -58,6 +58,29 @@
});
};
+ $scope.getDevice = function(doc) {
+ if(doc.BUILD) {
+ if(doc.BUILD.MANUFACTURER) {
+ return doc.BUILD.MANUFACTURER + " " + doc.BUILD.BRAND + " " + doc.BUILD.MODEL;
+ } else {
+ return doc.BUILD.BRAND + " " + doc.BUILD.MODEL;
+ }
+ } else {
+ var value = "";
+ if(doc.BRAND) {
+ value = doc.BRAND;
+ }
+ if(doc.PRODUCT) {
+ value += " " + doc.PRODUCT;
+ }
+ if(doc.PHONE_MODEL) {
+ value += " " + doc.MODEL;
+ }
+
+ return value;
+ }
+ };
+
$scope.loadReport = function(report) {
$scope.selectedReport = ReportsStore.reportDetails(report.id, function(data) {
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
@@ -121,7 +144,8 @@
};
$scope.getData = function() {
- ReportsStore.bugsList(function(data) {
+ ReportsStore.recentBugsList(
+ function(data) {
console.log("Refresh data for latest bugs");
mergeBugsLists($scope.bugs, data.rows);
$scope.totalBugs = data.total_rows;
@@ -373,11 +397,11 @@
/* Pie charts */
function PieChartsCtrl($scope, ReportsStore, $user) {
$scope.fieldNames = [
- {name: "android-version", label: "Android version"},
- {name: "android-sdk-version", label: "Android SDK version"},
- {name: "app-version-name", label: "Application version name"},
- {name: "app-version-code", label: "Application version code"},
- {name: "device", label: "Device"}
+ {name: "recent-items-by-androidver", label: "Android version"},
+ {name: "reports-per-android-sdk-version", label: "Android SDK version"},
+ {name: "recent-items-by-appver", label: "Application version name"},
+ {name: "recent-items-by-appvercode", label: "Application version code"},
+ {name: "reports-per-device", label: "Device"}
];
$scope.fieldName = $scope.fieldNames[0];
diff --git a/_attachments/script/ReportsBrowserControllers.js b/_attachments/script/ReportsBrowserControllers.js
index 3cb2c23..b818eb9 100644
--- a/_attachments/script/ReportsBrowserControllers.js
+++ b/_attachments/script/ReportsBrowserControllers.js
@@ -96,6 +96,29 @@
}
});
+ $scope.getDevice = function(doc) {
+ if(doc.BUILD) {
+ if(doc.BUILD.MANUFACTURER) {
+ return doc.BUILD.MANUFACTURER + " " + doc.BUILD.BRAND + " " + doc.BUILD.MODEL;
+ } else {
+ return doc.BUILD.BRAND + " " + doc.BUILD.MODEL;
+ }
+ } else {
+ var value = "";
+ if(doc.BRAND) {
+ value = doc.BRAND;
+ }
+ if(doc.PRODUCT) {
+ value += " " + doc.PRODUCT;
+ }
+ if(doc.PHONE_MODEL) {
+ value += " " + doc.MODEL;
+ }
+
+ return value;
+ }
+ };
+
$scope.getData = function() {
$scope.loading = true;
var successHandler = function(data) {
@@ -118,22 +141,22 @@
};
if(($scope.filterName === $scope.noFilter || $scope.filterValue === $scope.noFilterValue) && !$scope.bug && !$scope.selectedUser) {
- ReportsStore.reportsList($scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler);
+ ReportsStore.reportsList($scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler);
} else if($scope.filterName !== $scope.noFilter && $scope.filterValue !== $scope.noFilterValue){
- ReportsStore.filteredReportsList($scope.filterName.value, $scope.filterValue.value,$scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler);
+ ReportsStore.filteredReportsList($scope.filterName.value, $scope.filterValue.value,$scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler);
} else if($scope.bug) {
if($scope.selectedUser) {
// Filter by bug AND user
- var filterKey = $scope.bug.key.slice(0);
+ var filterKey = [$scope.bug.key];
filterKey.push($scope.selectedUser.installationId);
- ReportsStore.filteredReportsList("bug-by-installation-id", filterKey, $scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler);
+ ReportsStore.filteredReportsList("bug-by-installation-id", filterKey, $scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler);
} else {
// Filter by bug only
- ReportsStore.filteredReportsList("bug", $scope.bug.key, $scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler);
+ ReportsStore.filteredReportsList("bug-by-installation-id", $scope.bug.key, $scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler, 1);
}
} else if($scope.selectedUser) {
// Filter by user only
- ReportsStore.filteredReportsList("installation-id", $scope.selectedUser.installationId, $scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler);
+ ReportsStore.filteredReportsList("installation-id", $scope.selectedUser.installationId, $scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler);
}
};
diff --git a/_attachments/script/config.js b/_attachments/script/config.js
index c6692d0..f8abb77 100644
--- a/_attachments/script/config.js
+++ b/_attachments/script/config.js
@@ -1,7 +1,7 @@
(function(acralyzerConfig, undefined ) {
"use strict";
// Update this variable with the name of your app:
- acralyzerConfig.defaultApp = "";
+ acralyzerConfig.defaultApp = "test";
acralyzerConfig.backgroundPollingOnStartup = true;
acralyzerConfig.appDBPrefix = "acra-";
diff --git a/_attachments/script/service.reportsstore.js b/_attachments/script/service.reportsstore.js
index fa172d5..5a95fcf 100644
--- a/_attachments/script/service.reportsstore.js
+++ b/_attachments/script/service.reportsstore.js
@@ -26,7 +26,7 @@
* @singleton
* @static
*/
- acralyzer.factory('ReportsStore', ['$rootScope', '$http', '$resource', function($rootScope, $http, $resource) {
+ acralyzer.factory('ReportsStore', ['$rootScope', '$http', '$resource', '$location', function($rootScope, $http, $resource, $location) {
// ReportsStore service instance
var ReportsStore = {
lastseq : -1,
@@ -45,9 +45,17 @@
* @param {function} cb Callback to be executed after database changed.
*/
ReportsStore.setApp = function (newAppName, cb) {
+ var addLogcatLink = function(data, headersGetter) {
+ var report = JSON.parse(data);
+ if (report._attachments['logcat.txt'].stub) {
+ var link = $location.protocol() + '://' + $location.host() + ':' + $location.port() + '/' + ReportsStore.dbName + '/' + report._id + '/logcat.txt';
+ report._attachments['logcat.txt'].link = link;
+ }
+ return report;
+ };
ReportsStore.dbName = acralyzerConfig.appDBPrefix + newAppName;
ReportsStore.views = $resource('/' + ReportsStore.dbName + '/_design/acra-storage/_view/:view');
- ReportsStore.details = $resource('/' + ReportsStore.dbName + '/:reportid');
+ ReportsStore.details = $resource('/' + ReportsStore.dbName + '/:reportid', null, {'get': {method:'GET', transformResponse: addLogcatLink}});
ReportsStore.bug = $resource('/' + ReportsStore.dbName + '/:bugid', { bugid: '@_id' }, { save: {method: 'PUT'}});
ReportsStore.dbstate = $resource('/' + ReportsStore.dbName + '/');
ReportsStore.changes = $resource('/' + ReportsStore.dbName + '/_changes');
@@ -82,13 +90,13 @@
* @return Key: date/time, Value: quantity
*/
ReportsStore.reportsPerDay = function(grouplvl, cb, errorHandler) {
- return ReportsStore.views.get({view: 'reports-per-day', group_level: grouplvl}, cb, errorHandler);
+ return ReportsStore.views.get({view: 'reports-per-day', group_level: grouplvl, stale: 'update_after'}, cb, errorHandler);
};
// 10 latest reports - Key: date/time Value: report digest
ReportsStore.recentReports = function(cb, errorHandler) {
- return ReportsStore.views.get({view: 'recent-items', limit: 10, descending: true}, cb, errorHandler);
+ return ReportsStore.views.get({view: 'recent-items', limit: 10, descending: true, stale: 'update_after', include_docs: true}, cb, errorHandler);
};
// Key: report ID Value: report digest
@@ -97,6 +105,7 @@
view: 'recent-items',
descending: true,
limit: reportsCount + 1,
+ stale: 'update_after',
include_docs: includeDocs
};
if(startKey !== null) {
@@ -121,20 +130,13 @@
view: 'recent-items-by-' + filterName,
descending: true,
limit: reportsCount + 1,
+ stale: 'update_after',
include_docs: includeDocs,
reduce: false
};
- if(filterName.indexOf("bug") === 0) {
- // Bugs have composite keys, already an array.
- viewParams.endkey = JSON.stringify(filterValue);
- var startKeyValue = filterValue.slice(0);
- startKeyValue.push({});
- viewParams.startkey = JSON.stringify(startKeyValue);
- } else {
- viewParams.endkey = JSON.stringify([filterValue]);
- viewParams.startkey = JSON.stringify([filterValue,{}]);
- }
+ viewParams.endkey = JSON.stringify([].concat(filterValue));
+ viewParams.startkey = JSON.stringify([].concat(filterValue,{}));
if(pageStartKey !== null) {
viewParams.startkey = JSON.stringify(pageStartKey);
@@ -146,10 +148,8 @@
}
for(var row = 0; row < data.rows.length; row++) {
- if(filterName === "bug") {
- data.rows[row].displayDate = moment(data.rows[row].key[3]).fromNow();
- } else if(filterName === "bug-by-installation-id") {
- data.rows[row].displayDate = moment(data.rows[row].key[4]).fromNow();
+ if(filterName === "bug-by-installation-id") {
+ data.rows[row].displayDate = moment(data.rows[row].key[2]).fromNow();
} else {
data.rows[row].displayDate = moment(data.rows[row].key[1]).fromNow();
}
@@ -167,112 +167,111 @@
};
ReportsStore.reportsPerFieldName = function(fieldName, cb, errorHandler) {
- return ReportsStore.views.get({view: 'reports-per-' + fieldName, group_level: 1}, cb, errorHandler);
+ return ReportsStore.views.get({view: fieldName, group_level: 1, stale: 'update_after'}, cb, errorHandler);
};
ReportsStore.appVersionsList = function(cb) {
- return ReportsStore.views.get({view: 'recent-items-by-appver', group_level: 1}, cb);
+ return ReportsStore.views.get({view: 'recent-items-by-appver', reduce: true, group_level: 1, include_docs: false, stale: 'update_after'}, cb);
};
ReportsStore.appVersionCodesList = function(cb) {
- return ReportsStore.views.get({view: 'recent-items-by-appvercode', group_level: 1}, cb);
+ return ReportsStore.views.get({view: 'recent-items-by-appvercode', reduce: true, group_level: 1, include_docs: false, stale: 'update_after'}, cb);
};
ReportsStore.androidVersionsList = function(cb) {
- return ReportsStore.views.get({view: 'recent-items-by-androidver', group_level: 1}, cb);
+ return ReportsStore.views.get({view: 'recent-items-by-androidver', reduce: true, group_level: 1, include_docs: false, stale: 'update_after'}, cb);
};
- // BUGS MANAGEMENT
- var computeBugId = function(bug) {
- if (bug.id) {
- return bug.id;
- } else {
- return hex_md5(bug.key[0] + "|" + bug.key[1] + "|" + bug.key[2]);
- }
- };
-
- ReportsStore.bugsList = function(cb, errorHandler) {
- var viewParams = {
- view: 'bugs',
- descending: true,
- group: true
- };
+ ReportsStore.bugListWithLimit = function(limit, bugId) {
+
+ return function(cb, errorHandler){
+ var viewParams = {
+ view: 'bugs',
+ descending: true,
+ group: true,
+ stale: 'update_after'
+ };
+
+ if (limit > 0) { viewParams.limit = limit; }
+ if (bugId) { viewParams.key = bugId; }
+
+ var bugEqualityTest = function(bug2) {
+ if(
+ this.value.key !== bug2.value.key ||
+ this.value.latest !== bug2.value.latest ||
+ this.value.count !== bug2.value.count ||
+ this.value.solved !== bug2.value.solved ||
+ this.value.description !== bug2.value.description) {
+ return false;
+ }
+ return true;
+ };
- var bugEqualityTest = function(bug2) {
- if(this.value.latest !== bug2.value.latest ||
- this.value.count !== bug2.value.count ||
- this.value.solved !== bug2.value.solved ||
- this.value.description !== bug2.value.description) {
- return false;
- }
- return true;
- };
+ var bugUpdate = function(bug2) {
+ if(this.value.latest !== bug2.value.latest) {
+ this.value.latest = bug2.value.latest;
+ }
+ if(this.value.count !== bug2.value.count) {
+ this.value.count = bug2.value.count;
+ }
+ if(this.value.solved !== bug2.value.solved) {
+ this.value.solved = bug2.value.solved;
+ }
+ if(this.value.description !== bug2.value.description) {
+ this.value.description = bug2.value.description;
+ }
+ };
- var bugUpdate = function(bug2) {
- if(this.value.latest !== bug2.value.latest) {
- this.value.latest = bug2.value.latest;
- }
- if(this.value.count !== bug2.value.count) {
- this.value.count = bug2.value.count;
- }
- if(this.value.solved !== bug2.value.solved) {
- this.value.solved = bug2.value.solved;
- }
- if(this.value.description !== bug2.value.description) {
- this.value.description = bug2.value.description;
- }
- };
+ var toggleSolved = function() {
+ var bug = this;
+ this.solvedPending = true;
+ ReportsStore.toggleSolvedBug(bug, function(data){
+ bug.solvedPending = false;
+ });
+ };
+
+ var additionalCallback = function(data) {
+ // The bug view does not return individual documents. Unless data has been specifically updated about
+ // one bug, there is no bug document in a database. We add here the computed id of each 'virtual' bug.
+ for (var i = 0; i < data.rows.length; i++) {
+ data.rows[i].id = ""+data.rows[i].key;
+ data.rows[i].equals = bugEqualityTest;
+ data.rows[i].updateWithBug = bugUpdate;
+ data.rows[i].toggleSolved = toggleSolved;
+ data.rows[i].descriptionHtml = converter.makeHtml(data.rows[i].value.description);
+ }
+ cb(data);
+ };
- var toggleSolved = function() {
- var bug = this;
- this.solvedPending = true;
- ReportsStore.toggleSolvedBug(bug, function(data){
- bug.solvedPending = false;
- });
+ return ReportsStore.views.get(viewParams, additionalCallback, errorHandler);
};
+ };
- var additionalCallback = function(data) {
- // The bug view does not return individual documents. Unless data has been specifically updated about
- // one bug, there is no bug document in a database. We add here the computed id of each 'virtual' bug.
- for (var i = 0; i < data.rows.length; i++) {
- data.rows[i].id = computeBugId(data.rows[i]);
- data.rows[i].equals = bugEqualityTest;
- data.rows[i].updateWithBug = bugUpdate;
- data.rows[i].toggleSolved = toggleSolved;
- data.rows[i].descriptionHtml = converter.makeHtml(data.rows[i].value.description);
- }
- cb(data);
- };
+ ReportsStore.recentBugsList = ReportsStore.bugListWithLimit(0);
- return ReportsStore.views.get(viewParams, additionalCallback, errorHandler);
- };
+ ReportsStore.bugsList = ReportsStore.bugListWithLimit(0);
ReportsStore.toggleSolvedBug = function(bug, callback) {
+ var updateBrowserBug = function(data) {
+ bug.value.solved = curBug.solved;
+ callback(data);
+ };
var curBug = ReportsStore.bug.get({ bugid: bug.id}, function() {
// Success callback
curBug.solved = ! curBug.solved;
- var state = curBug.solved;
- curBug.$save(function(data) {
- bug.value.solved = state;
- console.log("bug is now:");
- console.log(bug);
- callback(data);
- });
+ ReportsStore.bug.save(curBug, updateBrowserBug);
}, function() {
// Fail callback
curBug = new ReportsStore.bug(
{
_id: bug.id,
- APP_VERSION_CODE: bug.key[0],
- digest: bug.key[1],
- rootCause: bug.key[2],
+ SIGNATURE: {
+ hash: bug.key
+ },
solved: true,
type: "solved_signature"
});
- curBug.$save(function(data) {
- bug.value.solved = curBug.solved;
- callback(data);
- });
+ ReportsStore.bug.save(curBug, updateBrowserBug);
});
};
@@ -285,9 +284,9 @@
curBug = new ReportsStore.bug(
{
_id: bug.id,
- APP_VERSION_CODE: bug.key[0],
- digest: bug.key[1],
- rootCause: bug.key[2],
+ signature: {
+ hash: bug.value.hash
+ },
solved: bug.value.solved,
type: "solved_signature",
description: bug.value.description
@@ -308,17 +307,11 @@
* @param cb
*/
ReportsStore.getBugForId = function(bugId, cb) {
- var bug = {};
- ReportsStore.bugsList(function(data) {
- console.log("looking for bug with id " + bugId);
- for (var i = 0; i < data.rows.length; i++) {
- if (data.rows[i].id === bugId) {
- bug = data.rows[i];
- console.log("Bug found:");
- console.log(bug);
- break;
- }
- }
+ var bug = null;
+ console.log("looking for bug with id " + bugId);
+ ReportsStore.bugListWithLimit(1, bugId)(function(data) {
+ bug = data.rows[0];
+ if (bug === null) { console.log("Error, unable to find bug with id " + bugId); }
cb(bug);
});
return bug;
@@ -483,16 +476,17 @@
var viewParams = {
view: 'users-per-bug',
reduce: true,
- group_level: 4
+ group_level: 2,
+ stale: 'update_after'
};
- viewParams.startkey = JSON.stringify([bug.key[0], bug.key[1], bug.key[2]]);
- viewParams.endkey = JSON.stringify([bug.key[0], bug.key[1], bug.key[2], {}]);
+ viewParams.startkey = JSON.stringify([bug.key]);
+ viewParams.endkey = JSON.stringify([bug.key, {}]);
var result = [];
ReportsStore.views.get(viewParams,function(data) {
for(var row = 0; row < data.rows.length; row++) {
var user = {
- installationId: data.rows[row].key[3],
+ installationId: data.rows[row].key[1],
reportsCount: data.rows[row].value
};
result.push(user);