mirror of
https://github.com/mupen64plus-ae/acralyzer.git
synced 2024-11-26 23:10:32 +00:00
add indent and trailing space to jshint support
This commit is contained in:
parent
af1c6f2c21
commit
5dedd6c10c
15
.jshintrc
15
.jshintrc
@ -1,11 +1,14 @@
|
||||
{
|
||||
"predef": {
|
||||
"angular": true,
|
||||
"moment": true,
|
||||
"predef": [
|
||||
"angular",
|
||||
"moment",
|
||||
|
||||
"d3",
|
||||
"prettyPrint"
|
||||
],
|
||||
"indent": 4,
|
||||
"trailing": true,
|
||||
|
||||
"d3": true,
|
||||
"prettyPrint": true
|
||||
},
|
||||
"strict": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
|
@ -17,92 +17,92 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzer,acralyzerEvents) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function AccountCtrl($scope, $user, $dialog) {
|
||||
$scope.$on(acralyzerEvents.LOGIN_CHANGE, function(event, $user) {
|
||||
$scope.username = $user.username;
|
||||
$scope.isAdmin = $user.isAdmin;
|
||||
});
|
||||
|
||||
$scope.showLogin = function() {
|
||||
var d = $dialog.dialog({
|
||||
templateUrl: 'partials/login-dialog.html',
|
||||
controller: 'LoginDialogCtrl'
|
||||
function AccountCtrl($scope, $user, $dialog) {
|
||||
$scope.$on(acralyzerEvents.LOGIN_CHANGE, function(event, $user) {
|
||||
$scope.username = $user.username;
|
||||
$scope.isAdmin = $user.isAdmin;
|
||||
});
|
||||
d.open().then(function(result){
|
||||
});
|
||||
};
|
||||
$scope.showChangePassword = function() {
|
||||
if (!$user.hasAdminPath && $user.isAdmin) {
|
||||
alert("Sorry, your couchdb setup does not allow you to change an admins password");
|
||||
return;
|
||||
}
|
||||
var d = $dialog.dialog({
|
||||
templateUrl: 'partials/change-password.html',
|
||||
controller: 'ChangePasswordDialogCtrl'
|
||||
});
|
||||
d.open().then(function(result){
|
||||
});
|
||||
};
|
||||
|
||||
$scope.logout = function() {
|
||||
$user.logout();
|
||||
};
|
||||
}
|
||||
$scope.showLogin = function() {
|
||||
var d = $dialog.dialog({
|
||||
templateUrl: 'partials/login-dialog.html',
|
||||
controller: 'LoginDialogCtrl'
|
||||
});
|
||||
d.open().then(function(result){
|
||||
});
|
||||
};
|
||||
$scope.showChangePassword = function() {
|
||||
if (!$user.hasAdminPath && $user.isAdmin) {
|
||||
alert("Sorry, your couchdb setup does not allow you to change an admins password");
|
||||
return;
|
||||
}
|
||||
var d = $dialog.dialog({
|
||||
templateUrl: 'partials/change-password.html',
|
||||
controller: 'ChangePasswordDialogCtrl'
|
||||
});
|
||||
d.open().then(function(result){
|
||||
});
|
||||
};
|
||||
|
||||
function LoginDialogCtrl($scope, $user, dialog) {
|
||||
$scope.username = "";
|
||||
$scope.password = "";
|
||||
$scope.pending = false;
|
||||
$scope.badUsername = false;
|
||||
$scope.logout = function() {
|
||||
$user.logout();
|
||||
};
|
||||
}
|
||||
|
||||
$scope.close = function(result) {
|
||||
if (this.disabled) { return; }
|
||||
$scope.pending = true;
|
||||
function LoginDialogCtrl($scope, $user, dialog) {
|
||||
$scope.username = "";
|
||||
$scope.password = "";
|
||||
$scope.pending = false;
|
||||
$scope.badUsername = false;
|
||||
$user.login($scope.username, $scope.password).then(
|
||||
function(data) {
|
||||
$scope.pending = false;
|
||||
dialog.close();
|
||||
},
|
||||
function(data) {
|
||||
$scope.badUsername = true;
|
||||
$scope.pending = false;
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
}
|
||||
$scope.close = function(result) {
|
||||
if (this.disabled) { return; }
|
||||
$scope.pending = true;
|
||||
$scope.badUsername = false;
|
||||
$user.login($scope.username, $scope.password).then(
|
||||
function(data) {
|
||||
$scope.pending = false;
|
||||
dialog.close();
|
||||
},
|
||||
function(data) {
|
||||
$scope.badUsername = true;
|
||||
$scope.pending = false;
|
||||
}
|
||||
);
|
||||
|
||||
function ChangePasswordDialogCtrl($scope, $user, dialog) {
|
||||
$scope.isAdmin = $user.isAdmin;
|
||||
$scope.username = $user.username;
|
||||
$scope.password = "";
|
||||
$scope.confirm_password = "";
|
||||
$scope.pending = false;
|
||||
};
|
||||
}
|
||||
|
||||
$scope.close = function(password) {
|
||||
if (this.disabled) { return; }
|
||||
$scope.pending = true;
|
||||
$scope.errmessage = null;
|
||||
$user.changePassword($scope.password).then(
|
||||
function() {
|
||||
/* success */
|
||||
$scope.pending = false;
|
||||
dialog.close();
|
||||
},
|
||||
function(result) {
|
||||
/* error */
|
||||
$scope.pending = false;
|
||||
$scope.errmessage = result;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
function ChangePasswordDialogCtrl($scope, $user, dialog) {
|
||||
$scope.isAdmin = $user.isAdmin;
|
||||
$scope.username = $user.username;
|
||||
$scope.password = "";
|
||||
$scope.confirm_password = "";
|
||||
$scope.pending = false;
|
||||
|
||||
acralyzer.controller('AccountCtrl', ['$scope','$user','$dialog', AccountCtrl]);
|
||||
acralyzer.controller('LoginDialogCtrl', ['$scope','$user','dialog', LoginDialogCtrl]);
|
||||
acralyzer.controller('ChangePasswordDialogCtrl', ['$scope', '$user', 'dialog', ChangePasswordDialogCtrl]);
|
||||
$scope.close = function(password) {
|
||||
if (this.disabled) { return; }
|
||||
$scope.pending = true;
|
||||
$scope.errmessage = null;
|
||||
$user.changePassword($scope.password).then(
|
||||
function() {
|
||||
/* success */
|
||||
$scope.pending = false;
|
||||
dialog.close();
|
||||
},
|
||||
function(result) {
|
||||
/* error */
|
||||
$scope.pending = false;
|
||||
$scope.errmessage = result;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
acralyzer.controller('AccountCtrl', ['$scope','$user','$dialog', AccountCtrl]);
|
||||
acralyzer.controller('LoginDialogCtrl', ['$scope','$user','dialog', LoginDialogCtrl]);
|
||||
acralyzer.controller('ChangePasswordDialogCtrl', ['$scope', '$user', 'dialog', ChangePasswordDialogCtrl]);
|
||||
|
||||
})(window.acralyzerConfig,window.angular,window.acralyzer, window.acralyzerEvents);
|
||||
|
@ -17,70 +17,70 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzer,acralyzerEvents,$) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function AcralyzerCtrl($scope, ReportsStore, $rootScope, desktopNotifications) {
|
||||
$scope.acralyzer = {
|
||||
apps: []
|
||||
};
|
||||
$scope.acralyzer.app = acralyzerConfig.defaultApp;
|
||||
$scope.acralyzer.isPolling = false;
|
||||
|
||||
$scope.acralyzer.setApp = function(appName) {
|
||||
$scope.acralyzer.app = appName;
|
||||
ReportsStore.setApp($scope.acralyzer.app,
|
||||
function() {
|
||||
console.log("broadcasting APP_CHANGED");
|
||||
$rootScope.$broadcast(acralyzerEvents.APP_CHANGED);
|
||||
}
|
||||
);
|
||||
if($scope.acralyzer.isPolling) {
|
||||
$scope.acralyzer.startPolling();
|
||||
}
|
||||
};
|
||||
$scope.acralyzer.setApp($scope.acralyzer.app);
|
||||
|
||||
ReportsStore.listApps(function(data) {
|
||||
console.log("Storage list retrieved.");
|
||||
$scope.acralyzer.apps.length = 0;
|
||||
$scope.acralyzer.apps = data;
|
||||
console.log($scope.acralyzer.apps);
|
||||
}, function() {
|
||||
|
||||
});
|
||||
|
||||
$scope.acralyzer.startPolling = function() {
|
||||
$scope.acralyzer.isPolling = true;
|
||||
ReportsStore.startPolling(function(){
|
||||
if($scope.acralyzer.isPolling) {
|
||||
$rootScope.$broadcast(acralyzerEvents.NEW_DATA);
|
||||
} // Do not refresh if a late response is received after the user asked to stop polling.
|
||||
});
|
||||
};
|
||||
|
||||
$scope.acralyzer.stopPolling = function() {
|
||||
console.log("Ok, let's stop polling...");
|
||||
function AcralyzerCtrl($scope, ReportsStore, $rootScope, desktopNotifications) {
|
||||
$scope.acralyzer = {
|
||||
apps: []
|
||||
};
|
||||
$scope.acralyzer.app = acralyzerConfig.defaultApp;
|
||||
$scope.acralyzer.isPolling = false;
|
||||
ReportsStore.stopPolling();
|
||||
};
|
||||
|
||||
var notifyNewData = function() {
|
||||
desktopNotifications.notify({ title: "Acralyzer - " + $scope.acralyzer.app, body: "Received new report(s)", icon: "img/loader.gif" });
|
||||
$('.top-right').notify({
|
||||
message: { text: 'Received new report(s)' },
|
||||
type: 'warning'
|
||||
}).show();
|
||||
};
|
||||
$scope.acralyzer.setApp = function(appName) {
|
||||
$scope.acralyzer.app = appName;
|
||||
ReportsStore.setApp($scope.acralyzer.app,
|
||||
function() {
|
||||
console.log("broadcasting APP_CHANGED");
|
||||
$rootScope.$broadcast(acralyzerEvents.APP_CHANGED);
|
||||
}
|
||||
);
|
||||
if($scope.acralyzer.isPolling) {
|
||||
$scope.acralyzer.startPolling();
|
||||
}
|
||||
};
|
||||
$scope.acralyzer.setApp($scope.acralyzer.app);
|
||||
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, notifyNewData);
|
||||
$scope.$on(acralyzerEvents.POLLING_FAILED, $scope.acralyzer.stopPolling);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.acralyzer.stopPolling);
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, function() {
|
||||
if(acralyzerConfig.backgroundPollingOnStartup) {
|
||||
$scope.acralyzer.startPolling();
|
||||
}
|
||||
});
|
||||
}
|
||||
ReportsStore.listApps(function(data) {
|
||||
console.log("Storage list retrieved.");
|
||||
$scope.acralyzer.apps.length = 0;
|
||||
$scope.acralyzer.apps = data;
|
||||
console.log($scope.acralyzer.apps);
|
||||
}, function() {
|
||||
|
||||
acralyzer.controller('AcralyzerCtrl', AcralyzerCtrl);
|
||||
});
|
||||
|
||||
$scope.acralyzer.startPolling = function() {
|
||||
$scope.acralyzer.isPolling = true;
|
||||
ReportsStore.startPolling(function(){
|
||||
if($scope.acralyzer.isPolling) {
|
||||
$rootScope.$broadcast(acralyzerEvents.NEW_DATA);
|
||||
} // Do not refresh if a late response is received after the user asked to stop polling.
|
||||
});
|
||||
};
|
||||
|
||||
$scope.acralyzer.stopPolling = function() {
|
||||
console.log("Ok, let's stop polling...");
|
||||
$scope.acralyzer.isPolling = false;
|
||||
ReportsStore.stopPolling();
|
||||
};
|
||||
|
||||
var notifyNewData = function() {
|
||||
desktopNotifications.notify({ title: "Acralyzer - " + $scope.acralyzer.app, body: "Received new report(s)", icon: "img/loader.gif" });
|
||||
$('.top-right').notify({
|
||||
message: { text: 'Received new report(s)' },
|
||||
type: 'warning'
|
||||
}).show();
|
||||
};
|
||||
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, notifyNewData);
|
||||
$scope.$on(acralyzerEvents.POLLING_FAILED, $scope.acralyzer.stopPolling);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.acralyzer.stopPolling);
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, function() {
|
||||
if(acralyzerConfig.backgroundPollingOnStartup) {
|
||||
$scope.acralyzer.startPolling();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
acralyzer.controller('AcralyzerCtrl', AcralyzerCtrl);
|
||||
})(window.acralyzerConfig,window.angular,window.acralyzer,window.acralyzerEvents,window.jQuery);
|
||||
|
@ -17,20 +17,20 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzer,acralyzerEvents,$) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function getBidimensionalArray(rows) {
|
||||
var result = new Array(rows.length);
|
||||
for(var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if(row.key && row.value) {
|
||||
result[i] = [row.key, row.value];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function getBidimensionalArray(rows) {
|
||||
var result = new Array(rows.length);
|
||||
for(var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if(row.key && row.value) {
|
||||
result[i] = [row.key, row.value];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var formatAsPercentage = d3.format("%"),
|
||||
var formatAsPercentage = d3.format("%"),
|
||||
formatAsPercentage1Dec = d3.format(".1%"),
|
||||
formatAsInteger = d3.format(","),
|
||||
fsec = d3.time.format("%S s"),
|
||||
@ -40,322 +40,326 @@ var formatAsPercentage = d3.format("%"),
|
||||
fdat = d3.time.format("%d d"),
|
||||
fmon = d3.time.format("%b");
|
||||
|
||||
function CrashReportsCtrl($scope, ReportsStore) {
|
||||
$scope.selectedReport = "";
|
||||
function CrashReportsCtrl($scope, ReportsStore) {
|
||||
$scope.selectedReport = "";
|
||||
|
||||
$scope.getData = function() {
|
||||
ReportsStore.recentReports(function(data) {
|
||||
console.log("Refresh data for latest reports");
|
||||
$scope.reports = data.rows;
|
||||
$scope.totalReports = data.total_rows;
|
||||
for(var row = 0; row < $scope.reports.length; row++) {
|
||||
$scope.reports[row].displayDate = moment($scope.reports[row].key).fromNow();
|
||||
}
|
||||
},
|
||||
function(response, getResponseHeaders){
|
||||
$scope.reports=[];
|
||||
$scope.totalReports="";
|
||||
});
|
||||
};
|
||||
|
||||
$scope.loadReport = function(report) {
|
||||
$scope.selectedReport = ReportsStore.reportDetails(report.id, function(data) {
|
||||
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
|
||||
data.formatedCrashDate = moment(data.USER_CRASH_DATE).format('LLL');
|
||||
data.formatedTimestamp = moment(data.timestamp).format('LLL');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
|
||||
|
||||
function ReportsPerDayCtrl($scope, ReportsStore) {
|
||||
$scope.periods = [
|
||||
{name: "Year", value: 1},
|
||||
{name: "Month", value: 2},
|
||||
{name: "Day", value: 3},
|
||||
{name: "Hour", value: 4},
|
||||
{name: "Minute", value: 5},
|
||||
{name: "Second", value: 6}
|
||||
];
|
||||
$scope.period = $scope.periods[2];
|
||||
|
||||
$scope.reportsPerDay=[];
|
||||
|
||||
$scope.dataDate = function(d) {
|
||||
var result = new Date();
|
||||
var dateArray = d[0];
|
||||
if(dateArray[0]) {
|
||||
result.setFullYear(dateArray[0]);
|
||||
} else {
|
||||
result.setFullYear(0);
|
||||
}
|
||||
if(dateArray[1]) {
|
||||
result.setMonth(dateArray[1]);
|
||||
} else {
|
||||
result.setMonth(0);
|
||||
}
|
||||
if(dateArray[2]) {
|
||||
result.setDate(dateArray[2]);
|
||||
} else {
|
||||
result.setDate(0);
|
||||
}
|
||||
if(dateArray[3]) {
|
||||
result.setHours(dateArray[3]);
|
||||
} else {
|
||||
result.setHours(0);
|
||||
}
|
||||
if(dateArray[4]) {
|
||||
result.setMinutes(dateArray[4]);
|
||||
} else {
|
||||
result.setMinutes(0);
|
||||
}
|
||||
if(dateArray[5]) {
|
||||
result.setSeconds(dateArray[5]);
|
||||
} else {
|
||||
result.setSeconds(0);
|
||||
}
|
||||
if(dateArray[6]) {
|
||||
result.setMilliseconds(dateArray[6]);
|
||||
} else {
|
||||
result.setMilliseconds(0);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
$scope.dataValue = function(d) {
|
||||
return d[1];
|
||||
};
|
||||
|
||||
|
||||
$scope.getData = function() {
|
||||
$.couch.session({
|
||||
success: function(session) {
|
||||
if(session.userCtx.roles.indexOf("reader") >= 0 || session.userCtx.roles.indexOf("_admin") >= 0) {
|
||||
console.log("You are authorized as a reader!");
|
||||
ReportsStore.reportsPerDay($scope.period.value, function(data) {
|
||||
$scope.reportsPerDay= getBidimensionalArray(data.rows);
|
||||
$scope.updateGraph();
|
||||
},
|
||||
function(response, getResonseHeaders){
|
||||
$scope.reportsPerDay=[[]];
|
||||
$scope.updateGraph();
|
||||
});
|
||||
$scope.getData = function() {
|
||||
ReportsStore.recentReports(function(data) {
|
||||
console.log("Refresh data for latest reports");
|
||||
$scope.reports = data.rows;
|
||||
$scope.totalReports = data.total_rows;
|
||||
for(var row = 0; row < $scope.reports.length; row++) {
|
||||
$scope.reports[row].displayDate = moment($scope.reports[row].key).fromNow();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.buildGraph = function () {
|
||||
var container = $("#graph-container");
|
||||
$scope.metrics = {
|
||||
/* width : parseInt(container.style.width),
|
||||
height : parseInt(container.style.height),
|
||||
*/ width : container.width(),
|
||||
height : container.height() * 0.8,
|
||||
padding : container.height() * 0.15
|
||||
},
|
||||
function(response, getResponseHeaders){
|
||||
$scope.reports=[];
|
||||
$scope.totalReports="";
|
||||
});
|
||||
};
|
||||
|
||||
// create an svg container
|
||||
if(!$scope.vis) {
|
||||
$scope.vis = d3.select("#graph-container")
|
||||
$scope.loadReport = function(report) {
|
||||
$scope.selectedReport = ReportsStore.reportDetails(report.id, function(data) {
|
||||
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
|
||||
data.formatedCrashDate = moment(data.USER_CRASH_DATE).format('LLL');
|
||||
data.formatedTimestamp = moment(data.timestamp).format('LLL');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
|
||||
|
||||
function ReportsPerDayCtrl($scope, ReportsStore) {
|
||||
$scope.periods = [
|
||||
{name: "Year", value: 1},
|
||||
{name: "Month", value: 2},
|
||||
{name: "Day", value: 3},
|
||||
{name: "Hour", value: 4},
|
||||
{name: "Minute", value: 5},
|
||||
{name: "Second", value: 6}
|
||||
];
|
||||
$scope.period = $scope.periods[2];
|
||||
|
||||
$scope.reportsPerDay=[];
|
||||
|
||||
$scope.dataDate = function(d) {
|
||||
var result = new Date();
|
||||
var dateArray = d[0];
|
||||
if(dateArray[0]) {
|
||||
result.setFullYear(dateArray[0]);
|
||||
} else {
|
||||
result.setFullYear(0);
|
||||
}
|
||||
if(dateArray[1]) {
|
||||
result.setMonth(dateArray[1]);
|
||||
} else {
|
||||
result.setMonth(0);
|
||||
}
|
||||
if(dateArray[2]) {
|
||||
result.setDate(dateArray[2]);
|
||||
} else {
|
||||
result.setDate(0);
|
||||
}
|
||||
if(dateArray[3]) {
|
||||
result.setHours(dateArray[3]);
|
||||
} else {
|
||||
result.setHours(0);
|
||||
}
|
||||
if(dateArray[4]) {
|
||||
result.setMinutes(dateArray[4]);
|
||||
} else {
|
||||
result.setMinutes(0);
|
||||
}
|
||||
if(dateArray[5]) {
|
||||
result.setSeconds(dateArray[5]);
|
||||
} else {
|
||||
result.setSeconds(0);
|
||||
}
|
||||
if(dateArray[6]) {
|
||||
result.setMilliseconds(dateArray[6]);
|
||||
} else {
|
||||
result.setMilliseconds(0);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
$scope.dataValue = function(d) {
|
||||
return d[1];
|
||||
};
|
||||
|
||||
|
||||
$scope.getData = function() {
|
||||
$.couch.session({
|
||||
success: function(session) {
|
||||
if(session.userCtx.roles.indexOf("reader") >= 0 || session.userCtx.roles.indexOf("_admin") >= 0) {
|
||||
console.log("You are authorized as a reader!");
|
||||
ReportsStore.reportsPerDay($scope.period.value, function(data) {
|
||||
$scope.reportsPerDay= getBidimensionalArray(data.rows);
|
||||
$scope.updateGraph();
|
||||
},
|
||||
function(response, getResonseHeaders){
|
||||
$scope.reportsPerDay=[[]];
|
||||
$scope.updateGraph();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.buildGraph = function () {
|
||||
var container = $("#graph-container");
|
||||
$scope.metrics = {
|
||||
/*
|
||||
width : parseInt(container.style.width),
|
||||
height : parseInt(container.style.height),
|
||||
*/
|
||||
width : container.width(),
|
||||
height : container.height() * 0.8,
|
||||
padding : container.height() * 0.15
|
||||
};
|
||||
|
||||
// create an svg container
|
||||
if(!$scope.vis) {
|
||||
$scope.vis = d3.select("#graph-container")
|
||||
.append("svg:svg")
|
||||
.attr("width", "100%")
|
||||
.attr("height", "80%")
|
||||
.attr("viewBox", "0 0 " + $scope.metrics.width + " " + $scope.metrics.height)
|
||||
.attr("preserveAspectRatio", "xMidYMid meet");
|
||||
/* .attr("width", $scope.metrics.width)
|
||||
/*
|
||||
.attr("width", $scope.metrics.width)
|
||||
.attr("height", $scope.metrics.height);
|
||||
*/ }
|
||||
|
||||
|
||||
$scope.xScale = d3.time.scale()
|
||||
.domain([d3.min($scope.reportsPerDay, $scope.dataDate), new Date()])
|
||||
.range([$scope.metrics.padding, $scope.metrics.width - $scope.metrics.padding]); // map these the the chart width = total width minus padding at both sides
|
||||
|
||||
|
||||
// define the y scale (vertical)
|
||||
$scope.yScale = d3.scale.linear()
|
||||
.domain([0, d3.max($scope.reportsPerDay, $scope.dataValue)])
|
||||
.range([$scope.metrics.height - $scope.metrics.padding, $scope.metrics.padding]); // map these to the chart height, less padding.
|
||||
//REMEMBER: y axis range has the bigger number first because the y value of zero is at the top of chart and increases as you go down.
|
||||
|
||||
|
||||
// define the y axis
|
||||
$scope.yAxis = d3.svg.axis()
|
||||
.orient("left")
|
||||
.scale($scope.yScale);
|
||||
|
||||
// define the y axis
|
||||
$scope.xAxis = d3.svg.axis()
|
||||
.orient("bottom")
|
||||
.scale($scope.xScale);
|
||||
|
||||
// draw y axis with labels and move in from the size by the amount of padding
|
||||
$scope.vis.append("g")
|
||||
.attr("class", "yaxis") // give it a class so it can be used to select only xaxis labels below
|
||||
.attr("transform", "translate("+$scope.metrics.padding+",0)")
|
||||
.call($scope.yAxis);
|
||||
|
||||
// draw x axis with labels and move to the bottom of the chart area
|
||||
$scope.vis.append("g")
|
||||
.attr("class", "xaxis") // give it a class so it can be used to select only xaxis labels below
|
||||
.attr("transform", "translate(0," + ($scope.metrics.height - $scope.metrics.padding) + ")")
|
||||
.call($scope.xAxis);
|
||||
|
||||
};
|
||||
|
||||
|
||||
$scope.updateGraph = function updateGraph() {
|
||||
|
||||
$scope.xScale.domain([d3.min($scope.reportsPerDay, $scope.dataDate), new Date()]);
|
||||
$scope.yScale.domain([0, d3.max($scope.reportsPerDay, $scope.dataValue)]);
|
||||
$scope.vis.select(".xaxis")
|
||||
.transition().duration(750)
|
||||
.call($scope.xAxis);
|
||||
$scope.vis.select(".yaxis")
|
||||
.transition().duration(750)
|
||||
.call($scope.yAxis);
|
||||
|
||||
// now rotate text on x axis
|
||||
// solution based on idea here: https://groups.google.com/forum/?fromgroups#!topic/d3-js/heOBPQF3sAY
|
||||
// first move the text left so no longer centered on the tick
|
||||
// then rotate up to get 45 degrees.
|
||||
$scope.vis.selectAll(".xaxis text") // select all the text elements for the xaxis
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + this.getBBox().height*-2 + "," + this.getBBox().height + ")rotate(-45)";
|
||||
});
|
||||
|
||||
// Update data
|
||||
var bars = $scope.vis.selectAll("rect")
|
||||
.data($scope.reportsPerDay);
|
||||
bars.attr("class", "update")
|
||||
.transition().duration(375)
|
||||
.attr("height", 0)
|
||||
.attr("y", function(d){return $scope.yScale(0);})
|
||||
.transition().delay(375).duration(1)
|
||||
.attr("x", function(d){return $scope.xScale($scope.dataDate(d));})
|
||||
.transition().delay(376).duration(374)
|
||||
.attr("y", function(d){return $scope.yScale($scope.dataValue(d));})
|
||||
.attr("height", function(d) { return $scope.metrics.height - $scope.metrics.padding - $scope.yScale($scope.dataValue(d));});
|
||||
|
||||
bars.enter().append("rect")
|
||||
.attr("class","enter")
|
||||
.attr("x", function(d){return $scope.xScale($scope.dataDate(d));})
|
||||
.attr("y", function(d){return $scope.yScale(0);})
|
||||
.attr("height", 0)
|
||||
.transition().duration(750)
|
||||
.attr("x", function(d){return $scope.xScale($scope.dataDate(d));})
|
||||
.attr("y", function(d){return $scope.yScale($scope.dataValue(d));})
|
||||
.attr("width", 1)
|
||||
.attr("height", function(d) { return $scope.metrics.height - $scope.metrics.padding - $scope.yScale($scope.dataValue(d)); });
|
||||
|
||||
bars.exit()
|
||||
.attr("class","exit")
|
||||
.transition().duration(750)
|
||||
.attr("height", 0)
|
||||
.attr("y", function(d){return $scope.yScale(0);})
|
||||
.remove();
|
||||
};
|
||||
|
||||
$scope.buildGraph();
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
|
||||
/* Pie charts */
|
||||
function PieChartsCtrl($scope, ReportsStore) {
|
||||
$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"}
|
||||
];
|
||||
$scope.fieldName = $scope.fieldNames[0];
|
||||
|
||||
$scope.reportsPerFieldName=[];
|
||||
|
||||
$scope.getData = function() {
|
||||
$.couch.session({
|
||||
success: function(session) {
|
||||
if(session.userCtx.roles.indexOf("reader") >= 0 || session.userCtx.roles.indexOf("_admin") >= 0) {
|
||||
console.log("You are authorized as a reader!");
|
||||
ReportsStore.reportsPerFieldName($scope.fieldName.name, function(data) {
|
||||
$scope.reportsPerFieldName = getBidimensionalArray(data.rows);
|
||||
var totalReports = 0;
|
||||
var i = 0;
|
||||
// Get total number of reports before calculating the ratio for each value.
|
||||
for(i = 0; i < $scope.reportsPerFieldName.length; i++) {
|
||||
totalReports += $scope.reportsPerFieldName[i][1];
|
||||
}
|
||||
for(i = 0; i < $scope.reportsPerFieldName.length; i++) {
|
||||
$scope.reportsPerFieldName[i][2] = $scope.reportsPerFieldName[i][1] / totalReports;
|
||||
}
|
||||
$scope.updateGraph();
|
||||
},
|
||||
function(response, getResonseHeaders){
|
||||
$scope.reportsPerFieldName=[[]];
|
||||
$scope.updateGraph();
|
||||
});
|
||||
}
|
||||
*/
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.mouseover = function() {
|
||||
d3.select(this).select("path").transition()
|
||||
|
||||
$scope.xScale = d3.time.scale()
|
||||
.domain([d3.min($scope.reportsPerDay, $scope.dataDate), new Date()])
|
||||
.range([$scope.metrics.padding, $scope.metrics.width - $scope.metrics.padding]); // map these the the chart width = total width minus padding at both sides
|
||||
|
||||
|
||||
// define the y scale (vertical)
|
||||
$scope.yScale = d3.scale.linear()
|
||||
.domain([0, d3.max($scope.reportsPerDay, $scope.dataValue)])
|
||||
.range([$scope.metrics.height - $scope.metrics.padding, $scope.metrics.padding]); // map these to the chart height, less padding.
|
||||
//REMEMBER: y axis range has the bigger number first because the y value of zero is at the top of chart and increases as you go down.
|
||||
|
||||
|
||||
// define the y axis
|
||||
$scope.yAxis = d3.svg.axis()
|
||||
.orient("left")
|
||||
.scale($scope.yScale);
|
||||
|
||||
// define the y axis
|
||||
$scope.xAxis = d3.svg.axis()
|
||||
.orient("bottom")
|
||||
.scale($scope.xScale);
|
||||
|
||||
// draw y axis with labels and move in from the size by the amount of padding
|
||||
$scope.vis.append("g")
|
||||
.attr("class", "yaxis") // give it a class so it can be used to select only xaxis labels below
|
||||
.attr("transform", "translate("+$scope.metrics.padding+",0)")
|
||||
.call($scope.yAxis);
|
||||
|
||||
// draw x axis with labels and move to the bottom of the chart area
|
||||
$scope.vis.append("g")
|
||||
.attr("class", "xaxis") // give it a class so it can be used to select only xaxis labels below
|
||||
.attr("transform", "translate(0," + ($scope.metrics.height - $scope.metrics.padding) + ")")
|
||||
.call($scope.xAxis);
|
||||
|
||||
};
|
||||
|
||||
|
||||
$scope.updateGraph = function updateGraph() {
|
||||
|
||||
$scope.xScale.domain([d3.min($scope.reportsPerDay, $scope.dataDate), new Date()]);
|
||||
$scope.yScale.domain([0, d3.max($scope.reportsPerDay, $scope.dataValue)]);
|
||||
$scope.vis.select(".xaxis")
|
||||
.transition().duration(750)
|
||||
.call($scope.xAxis);
|
||||
$scope.vis.select(".yaxis")
|
||||
.transition().duration(750)
|
||||
.call($scope.yAxis);
|
||||
|
||||
// now rotate text on x axis
|
||||
// solution based on idea here: https://groups.google.com/forum/?fromgroups#!topic/d3-js/heOBPQF3sAY
|
||||
// first move the text left so no longer centered on the tick
|
||||
// then rotate up to get 45 degrees.
|
||||
$scope.vis.selectAll(".xaxis text") // select all the text elements for the xaxis
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + this.getBBox().height*-2 + "," + this.getBBox().height + ")rotate(-45)";
|
||||
});
|
||||
|
||||
// Update data
|
||||
var bars = $scope.vis.selectAll("rect")
|
||||
.data($scope.reportsPerDay);
|
||||
bars.attr("class", "update")
|
||||
.transition().duration(375)
|
||||
.attr("height", 0)
|
||||
.attr("y", function(d){return $scope.yScale(0);})
|
||||
.transition().delay(375).duration(1)
|
||||
.attr("x", function(d){return $scope.xScale($scope.dataDate(d));})
|
||||
.transition().delay(376).duration(374)
|
||||
.attr("y", function(d){return $scope.yScale($scope.dataValue(d));})
|
||||
.attr("height", function(d) { return $scope.metrics.height - $scope.metrics.padding - $scope.yScale($scope.dataValue(d));});
|
||||
|
||||
bars.enter().append("rect")
|
||||
.attr("class","enter")
|
||||
.attr("x", function(d){return $scope.xScale($scope.dataDate(d));})
|
||||
.attr("y", function(d){return $scope.yScale(0);})
|
||||
.attr("height", 0)
|
||||
.transition().duration(750)
|
||||
.attr("x", function(d){return $scope.xScale($scope.dataDate(d));})
|
||||
.attr("y", function(d){return $scope.yScale($scope.dataValue(d));})
|
||||
.attr("width", 1)
|
||||
.attr("height", function(d) { return $scope.metrics.height - $scope.metrics.padding - $scope.yScale($scope.dataValue(d)); });
|
||||
|
||||
bars.exit()
|
||||
.attr("class","exit")
|
||||
.transition().duration(750)
|
||||
.attr("height", 0)
|
||||
.attr("y", function(d){return $scope.yScale(0);})
|
||||
.remove();
|
||||
};
|
||||
|
||||
$scope.buildGraph();
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
|
||||
/* Pie charts */
|
||||
function PieChartsCtrl($scope, ReportsStore) {
|
||||
$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"}
|
||||
];
|
||||
$scope.fieldName = $scope.fieldNames[0];
|
||||
|
||||
$scope.reportsPerFieldName=[];
|
||||
|
||||
$scope.getData = function() {
|
||||
$.couch.session({
|
||||
success: function(session) {
|
||||
if(session.userCtx.roles.indexOf("reader") >= 0 || session.userCtx.roles.indexOf("_admin") >= 0) {
|
||||
console.log("You are authorized as a reader!");
|
||||
ReportsStore.reportsPerFieldName($scope.fieldName.name, function(data) {
|
||||
$scope.reportsPerFieldName = getBidimensionalArray(data.rows);
|
||||
var totalReports = 0;
|
||||
var i = 0;
|
||||
// Get total number of reports before calculating the ratio for each value.
|
||||
for(i = 0; i < $scope.reportsPerFieldName.length; i++) {
|
||||
totalReports += $scope.reportsPerFieldName[i][1];
|
||||
}
|
||||
for(i = 0; i < $scope.reportsPerFieldName.length; i++) {
|
||||
$scope.reportsPerFieldName[i][2] = $scope.reportsPerFieldName[i][1] / totalReports;
|
||||
}
|
||||
$scope.updateGraph();
|
||||
},
|
||||
function(response, getResonseHeaders){
|
||||
$scope.reportsPerFieldName=[[]];
|
||||
$scope.updateGraph();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.mouseover = function() {
|
||||
d3.select(this).select("path").transition()
|
||||
.duration(350)
|
||||
//.attr("stroke","red")
|
||||
//.attr("stroke-width", 1.5)
|
||||
.attr("d", $scope.arcFinal3)
|
||||
;
|
||||
};
|
||||
;
|
||||
};
|
||||
|
||||
$scope.mouseout = function() {
|
||||
d3.select(this).select("path").transition()
|
||||
$scope.mouseout = function() {
|
||||
d3.select(this).select("path").transition()
|
||||
.duration(350)
|
||||
//.attr("stroke","blue")
|
||||
//.attr("stroke-width", 1.5)
|
||||
.attr("d", $scope.arcFinal)
|
||||
;
|
||||
};
|
||||
|
||||
$scope.up = function(d, i) {
|
||||
/* update bar chart when user selects piece of the pie chart */
|
||||
//updateBarChart(dataset[i].category);
|
||||
// updateBarChart(d.data.category, color(i));
|
||||
// updateLineChart(d.data.category, color(i));
|
||||
|
||||
};
|
||||
|
||||
$scope.buildGraph = function () {
|
||||
var container = $("#pie-charts");
|
||||
|
||||
var outerRad = Math.min(container.width(), container.height()) / 2;
|
||||
var innerRad = outerRad * 0.999;
|
||||
$scope.metrics = {
|
||||
width : container.width(),
|
||||
height : container.height(),
|
||||
padding : container.height() * 0.15,
|
||||
outerRadius : outerRad,
|
||||
outerRadiusSelected : outerRad * 1.05,
|
||||
innerRadius : innerRad,
|
||||
// for animation
|
||||
innerRadiusFinal : outerRad * 0.2,
|
||||
innerRadiusFinal3 : outerRad * 0.25,
|
||||
color : d3.scale.category20() //builtin range of colors
|
||||
;
|
||||
};
|
||||
|
||||
// create an svg container
|
||||
$scope.vis = d3.select("#pie-charts")
|
||||
$scope.up = function(d, i) {
|
||||
/* update bar chart when user selects piece of the pie chart */
|
||||
//updateBarChart(dataset[i].category);
|
||||
// updateBarChart(d.data.category, color(i));
|
||||
// updateLineChart(d.data.category, color(i));
|
||||
|
||||
};
|
||||
|
||||
$scope.buildGraph = function () {
|
||||
var container = $("#pie-charts");
|
||||
|
||||
var outerRad = Math.min(container.width(), container.height()) / 2;
|
||||
var innerRad = outerRad * 0.999;
|
||||
$scope.metrics = {
|
||||
width : container.width(),
|
||||
height : container.height(),
|
||||
padding : container.height() * 0.15,
|
||||
outerRadius : outerRad,
|
||||
outerRadiusSelected : outerRad * 1.05,
|
||||
innerRadius : innerRad,
|
||||
// for animation
|
||||
innerRadiusFinal : outerRad * 0.2,
|
||||
innerRadiusFinal3 : outerRad * 0.25,
|
||||
color : d3.scale.category20() //builtin range of colors
|
||||
};
|
||||
|
||||
// create an svg container
|
||||
$scope.vis = d3.select("#pie-charts")
|
||||
.append("svg:svg") //create the SVG element inside the <body>
|
||||
.data([$scope.reportsPerFieldName]) //associate our data with the document
|
||||
.attr("width", "95%")
|
||||
@ -364,114 +368,114 @@ function PieChartsCtrl($scope, ReportsStore) {
|
||||
.attr("preserveAspectRatio", "xMidYMid meet")
|
||||
.append("svg:g") //make a group to hold our pie chart
|
||||
.attr("transform", "translate(" + $scope.metrics.width / 2 + "," + $scope.metrics.height / 2 + ")") //move the center of the pie chart from 0, 0 to radius, radius
|
||||
;
|
||||
;
|
||||
|
||||
$scope.arc = d3.svg.arc() //this will create <path> elements for us using arc data
|
||||
$scope.arc = d3.svg.arc() //this will create <path> elements for us using arc data
|
||||
.outerRadius($scope.metrics.outerRadius).innerRadius($scope.metrics.innerRadius);
|
||||
|
||||
// for animation
|
||||
$scope.arcFinal = d3.svg.arc().innerRadius($scope.metrics.innerRadiusFinal).outerRadius($scope.metrics.outerRadius);
|
||||
$scope.arcFinal3 = d3.svg.arc().innerRadius($scope.metrics.innerRadiusFinal3).outerRadius($scope.metrics.outerRadiusSelected);
|
||||
// for animation
|
||||
$scope.arcFinal = d3.svg.arc().innerRadius($scope.metrics.innerRadiusFinal).outerRadius($scope.metrics.outerRadius);
|
||||
$scope.arcFinal3 = d3.svg.arc().innerRadius($scope.metrics.innerRadiusFinal3).outerRadius($scope.metrics.outerRadiusSelected);
|
||||
|
||||
$scope.pie = d3.layout.pie() //this will create arc data for us given a list of values
|
||||
$scope.pie = d3.layout.pie() //this will create arc data for us given a list of values
|
||||
.value(function(d) {
|
||||
return d[2];
|
||||
}); //we must tell it how to access the value of each element in our data array
|
||||
|
||||
// Computes the label angle of an arc, converting from radians to degrees.
|
||||
$scope.angle = function(d) {
|
||||
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
|
||||
return a > 90 ? a - 180 : a;
|
||||
}
|
||||
// Computes the label angle of an arc, converting from radians to degrees.
|
||||
$scope.angle = function(d) {
|
||||
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
|
||||
return a > 90 ? a - 180 : a;
|
||||
}
|
||||
|
||||
// Pie chart title
|
||||
/* $scope.chartTitle = $scope.vis.append("svg:text")
|
||||
// Pie chart title
|
||||
/* $scope.chartTitle = $scope.vis.append("svg:text")
|
||||
.attr("dy", ".35em")
|
||||
.attr("text-anchor", "middle")
|
||||
.text($scope.fieldName.label)
|
||||
.attr("class","title")
|
||||
*/ ;
|
||||
*/ ;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
$scope.updateGraph = function () {
|
||||
$scope.vis.data([$scope.reportsPerFieldName]);
|
||||
// $scope.chartTitle.text($scope.fieldName.label);
|
||||
$scope.updateGraph = function () {
|
||||
$scope.vis.data([$scope.reportsPerFieldName]);
|
||||
// $scope.chartTitle.text($scope.fieldName.label);
|
||||
|
||||
var arcs = $scope.vis.selectAll("g.slice").data($scope.pie);
|
||||
var arcs = $scope.vis.selectAll("g.slice").data($scope.pie);
|
||||
|
||||
// update
|
||||
arcs.select("path").attr("d", $scope.arcFinal);
|
||||
// update
|
||||
arcs.select("path").attr("d", $scope.arcFinal);
|
||||
|
||||
arcs.select(".pie-label").remove();
|
||||
arcs.select(".pie-label").remove();
|
||||
|
||||
arcs.filter(function(d) { return d.endAngle - d.startAngle > 0.2; })
|
||||
arcs.filter(function(d) { return d.endAngle - d.startAngle > 0.2; })
|
||||
.append("svg:text")
|
||||
.attr("class", "pie-label")
|
||||
.attr("dy", ".35em")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) { return "translate(" + $scope.arcFinal.centroid(d) + ")rotate(" + $scope.angle(d) + ")"; })
|
||||
.text(function(d) { return d.data[0] + " : " + formatAsPercentage(d.value); })
|
||||
;
|
||||
;
|
||||
|
||||
arcs.select("title")
|
||||
arcs.select("title")
|
||||
.text(function(d) { return d.data[0] + " : " + formatAsPercentage(d.value) + " (" + d.data[1] + " reports)"; });
|
||||
|
||||
arcs.exit().remove();
|
||||
arcs.exit().remove();
|
||||
|
||||
var newarcs = arcs.enter()
|
||||
var newarcs = arcs.enter()
|
||||
.append("svg:g")
|
||||
.attr("class", "slice")
|
||||
.on("mouseover", $scope.mouseover)
|
||||
.on("mouseout", $scope.mouseout)
|
||||
.on("click", $scope.up);
|
||||
|
||||
newarcs.append("svg:path")
|
||||
.attr("fill", function(d, i) { return $scope.metrics.color(i); } ) //set the color for each slice to be chosen from the color function defined above
|
||||
.attr("d", $scope.arcFinal) //this creates the actual SVG path using the associated data (pie) with the arc drawing function
|
||||
.append("svg:title") //mouseover title showing the figures
|
||||
.text(function(d) { return d.data[0] + " : " + formatAsPercentage(d.value) + " (" + d.data[1] + " reports)"; })
|
||||
;
|
||||
newarcs.append("svg:path")
|
||||
.attr("fill", function(d, i) { return $scope.metrics.color(i); } ) //set the color for each slice to be chosen from the color function defined above
|
||||
.attr("d", $scope.arcFinal) //this creates the actual SVG path using the associated data (pie) with the arc drawing function
|
||||
.append("svg:title") //mouseover title showing the figures
|
||||
.text(function(d) { return d.data[0] + " : " + formatAsPercentage(d.value) + " (" + d.data[1] + " reports)"; })
|
||||
;
|
||||
|
||||
newarcs.filter(function(d) { return d.endAngle - d.startAngle > 0.2; })
|
||||
newarcs.filter(function(d) { return d.endAngle - d.startAngle > 0.2; })
|
||||
.append("svg:text")
|
||||
.attr("class", "pie-label")
|
||||
.attr("dy", ".35em")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) { return "translate(" + $scope.arcFinal.centroid(d) + ")rotate(" + $scope.angle(d) + ")"; })
|
||||
.text(function(d) { return d.data[0] + " : " + formatAsPercentage(d.value); })
|
||||
;
|
||||
.attr("class", "pie-label")
|
||||
.attr("dy", ".35em")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) { return "translate(" + $scope.arcFinal.centroid(d) + ")rotate(" + $scope.angle(d) + ")"; })
|
||||
.text(function(d) { return d.data[0] + " : " + formatAsPercentage(d.value); })
|
||||
;
|
||||
|
||||
|
||||
/* d3.selectAll("g.slice").selectAll("path").transition()
|
||||
/* d3.selectAll("g.slice").selectAll("path").transition()
|
||||
.duration(750)
|
||||
.delay(10)
|
||||
.attr("d", $scope.arcFinal )
|
||||
;
|
||||
*/
|
||||
};
|
||||
;
|
||||
*/
|
||||
};
|
||||
|
||||
$scope.buildGraph();
|
||||
$scope.buildGraph();
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
|
||||
function DashboardCtrl($scope, $routeParams) {
|
||||
if($routeParams.app) {
|
||||
console.log("Dashboard: Direct access to app " + $routeParams.app);
|
||||
$scope.acralyzer.setApp($routeParams.app);
|
||||
} else {
|
||||
console.log("Dashboard: Access to default app " + acralyzerConfig.defaultApp);
|
||||
$scope.acralyzer.setApp(acralyzerConfig.defaultApp);
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.NEW_DATA, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
}
|
||||
|
||||
acralyzer.controller('ReportsPerDayCtrl',ReportsPerDayCtrl);
|
||||
acralyzer.controller('PieChartsCtrl',PieChartsCtrl);
|
||||
acralyzer.controller('DashboardCtrl', DashboardCtrl);
|
||||
acralyzer.controller('CrashReportsCtrl', CrashReportsCtrl);
|
||||
function DashboardCtrl($scope, $routeParams) {
|
||||
if($routeParams.app) {
|
||||
console.log("Dashboard: Direct access to app " + $routeParams.app);
|
||||
$scope.acralyzer.setApp($routeParams.app);
|
||||
} else {
|
||||
console.log("Dashboard: Access to default app " + acralyzerConfig.defaultApp);
|
||||
$scope.acralyzer.setApp(acralyzerConfig.defaultApp);
|
||||
}
|
||||
}
|
||||
|
||||
acralyzer.controller('ReportsPerDayCtrl',ReportsPerDayCtrl);
|
||||
acralyzer.controller('PieChartsCtrl',PieChartsCtrl);
|
||||
acralyzer.controller('DashboardCtrl', DashboardCtrl);
|
||||
acralyzer.controller('CrashReportsCtrl', CrashReportsCtrl);
|
||||
|
||||
})(window.acralyzerConfig,window.angular,window.acralyzer,window.acralyzerEvents,window.jQuery);
|
||||
|
@ -17,12 +17,12 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzer) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function NavigationCtrl($scope, $route, $dialog) {
|
||||
$scope.$route = $route;
|
||||
}
|
||||
function NavigationCtrl($scope, $route, $dialog) {
|
||||
$scope.$route = $route;
|
||||
}
|
||||
|
||||
acralyzer.controller('NavigationCtrl', NavigationCtrl);
|
||||
acralyzer.controller('NavigationCtrl', NavigationCtrl);
|
||||
|
||||
})(window.acralyzerConfig,window.angular,window.acralyzer);
|
||||
|
@ -17,21 +17,21 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzer) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function ReportDetailsCtrl($scope, $routeParams, ReportsStore) {
|
||||
$scope.acralyzer.setApp($routeParams.app);
|
||||
$scope.reportId = $routeParams.reportId;
|
||||
$scope.loadReport = function(reportId) {
|
||||
$scope.report = ReportsStore.reportDetails(reportId, function(data) {
|
||||
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
|
||||
data.formatedCrashDate = moment(data.USER_CRASH_DATE).format('LLL');
|
||||
data.formatedTimestamp = moment(data.timestamp).format('LLL');
|
||||
});
|
||||
};
|
||||
$scope.loadReport($scope.reportId);
|
||||
function ReportDetailsCtrl($scope, $routeParams, ReportsStore) {
|
||||
$scope.acralyzer.setApp($routeParams.app);
|
||||
$scope.reportId = $routeParams.reportId;
|
||||
$scope.loadReport = function(reportId) {
|
||||
$scope.report = ReportsStore.reportDetails(reportId, function(data) {
|
||||
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
|
||||
data.formatedCrashDate = moment(data.USER_CRASH_DATE).format('LLL');
|
||||
data.formatedTimestamp = moment(data.timestamp).format('LLL');
|
||||
});
|
||||
};
|
||||
$scope.loadReport($scope.reportId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
acralyzer.controller('ReportDetailsCtrl',ReportDetailsCtrl);
|
||||
acralyzer.controller('ReportDetailsCtrl',ReportDetailsCtrl);
|
||||
})(window.acralyzerConfig,window.angular,window.acralyzer);
|
||||
|
@ -17,134 +17,134 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzer,acralyzerEvents) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
function ReportsBrowserCtrl($scope, ReportsStore, $routeParams) {
|
||||
if($routeParams.app) {
|
||||
console.log("ReportsBrowser: Direct access to app " + $routeParams.app);
|
||||
$scope.acralyzer.setApp($routeParams.app);
|
||||
} else {
|
||||
console.log("ReportsBorwser: Access to default app " + acralyzerConfig.defaultApp);
|
||||
$scope.acralyzer.setApp(acralyzerConfig.defaultApp);
|
||||
}
|
||||
function ReportsBrowserCtrl($scope, ReportsStore, $routeParams) {
|
||||
if($routeParams.app) {
|
||||
console.log("ReportsBrowser: Direct access to app " + $routeParams.app);
|
||||
$scope.acralyzer.setApp($routeParams.app);
|
||||
} else {
|
||||
console.log("ReportsBorwser: Access to default app " + acralyzerConfig.defaultApp);
|
||||
$scope.acralyzer.setApp(acralyzerConfig.defaultApp);
|
||||
}
|
||||
|
||||
console.log("Init ReportsBrowserCtrl");
|
||||
$scope.reportsCount = 15;
|
||||
$scope.previousStartKeys = [];
|
||||
$scope.selectedReport = "";
|
||||
$scope.startKey = null;
|
||||
$scope.nextKey = null;
|
||||
$scope.startNumber = 1;
|
||||
$scope.endNumber = $scope.reportsCount;
|
||||
$scope.fullSearch = false;
|
||||
$scope.loading = true;
|
||||
$scope.noFilter = { value: "false", label: "No filter"};
|
||||
$scope.noFilterValue = { value: "false", label: "All values"};
|
||||
$scope.availableFilters = [
|
||||
$scope.noFilter,
|
||||
{value: "appver", label: "Application version"},
|
||||
{value: "androidver", label: "Android version"}
|
||||
];
|
||||
$scope.filterName = $scope.noFilter;
|
||||
$scope.filterValue = $scope.noFilterValue;
|
||||
|
||||
$scope.filterValues = [];
|
||||
|
||||
|
||||
$scope.getNextPage = function() {
|
||||
$scope.previousStartKeys.push($scope.startKey);
|
||||
$scope.startKey = $scope.nextKey;
|
||||
$scope.getData();
|
||||
};
|
||||
|
||||
$scope.getPreviousPage = function() {
|
||||
console.log("Init ReportsBrowserCtrl");
|
||||
$scope.reportsCount = 15;
|
||||
$scope.previousStartKeys = [];
|
||||
$scope.selectedReport = "";
|
||||
$scope.startKey = null;
|
||||
$scope.nextKey = null;
|
||||
$scope.startKey = $scope.previousStartKeys.pop();
|
||||
$scope.getData();
|
||||
};
|
||||
|
||||
$scope.getData = function() {
|
||||
$scope.startNumber = 1;
|
||||
$scope.endNumber = $scope.reportsCount;
|
||||
$scope.fullSearch = false;
|
||||
$scope.loading = true;
|
||||
var successHandler = function(data) {
|
||||
// Success Handler
|
||||
console.log("Refresh data for latest reports");
|
||||
$scope.reports = data.rows;
|
||||
$scope.totalReports = data.total_rows;
|
||||
for(var row = 0; row < $scope.reports.length; row++) {
|
||||
$scope.reports[row].displayDate = moment($scope.reports[row].key).fromNow();
|
||||
}
|
||||
$scope.noFilter = { value: "false", label: "No filter"};
|
||||
$scope.noFilterValue = { value: "false", label: "All values"};
|
||||
$scope.availableFilters = [
|
||||
$scope.noFilter,
|
||||
{value: "appver", label: "Application version"},
|
||||
{value: "androidver", label: "Android version"}
|
||||
];
|
||||
$scope.filterName = $scope.noFilter;
|
||||
$scope.filterValue = $scope.noFilterValue;
|
||||
|
||||
// If there are more rows, here is the key to the next page
|
||||
$scope.nextKey =data.next_row ? data.next_row.key : null;
|
||||
$scope.startNumber = ($scope.previousStartKeys.length * $scope.reportsCount) + 1;
|
||||
$scope.endNumber = $scope.startNumber + $scope.reports.length - 1;
|
||||
console.log($scope);
|
||||
$scope.loading = false;
|
||||
$scope.filterValues = [];
|
||||
|
||||
|
||||
$scope.getNextPage = function() {
|
||||
$scope.previousStartKeys.push($scope.startKey);
|
||||
$scope.startKey = $scope.nextKey;
|
||||
$scope.getData();
|
||||
};
|
||||
|
||||
var errorHandler = function(response, getResponseHeaders){
|
||||
$scope.getPreviousPage = function() {
|
||||
$scope.nextKey = null;
|
||||
$scope.startKey = $scope.previousStartKeys.pop();
|
||||
$scope.getData();
|
||||
};
|
||||
|
||||
$scope.getData = function() {
|
||||
$scope.loading = true;
|
||||
var successHandler = function(data) {
|
||||
// Success Handler
|
||||
console.log("Refresh data for latest reports");
|
||||
$scope.reports = data.rows;
|
||||
$scope.totalReports = data.total_rows;
|
||||
for(var row = 0; row < $scope.reports.length; row++) {
|
||||
$scope.reports[row].displayDate = moment($scope.reports[row].key).fromNow();
|
||||
}
|
||||
|
||||
// If there are more rows, here is the key to the next page
|
||||
$scope.nextKey =data.next_row ? data.next_row.key : null;
|
||||
$scope.startNumber = ($scope.previousStartKeys.length * $scope.reportsCount) + 1;
|
||||
$scope.endNumber = $scope.startNumber + $scope.reports.length - 1;
|
||||
console.log($scope);
|
||||
$scope.loading = false;
|
||||
};
|
||||
|
||||
var errorHandler = function(response, getResponseHeaders){
|
||||
// Error Handler
|
||||
$scope.reports=[];
|
||||
$scope.totalReports="";
|
||||
};
|
||||
|
||||
if($scope.filterName === $scope.noFilter || $scope.filterValue === $scope.noFilterValue) {
|
||||
ReportsStore.reportsList($scope.startKey, $scope.reportsCount, $scope.fullSearch, successHandler, errorHandler);
|
||||
} else {
|
||||
ReportsStore.filteredReportsList($scope.filterName.value, $scope.filterValue.value,$scope.startKey, $scope.reportsCount, $scope.fullSearch, successHandler, errorHandler);
|
||||
}
|
||||
};
|
||||
|
||||
if($scope.filterName === $scope.noFilter || $scope.filterValue === $scope.noFilterValue) {
|
||||
ReportsStore.reportsList($scope.startKey, $scope.reportsCount, $scope.fullSearch, successHandler, errorHandler);
|
||||
} else {
|
||||
ReportsStore.filteredReportsList($scope.filterName.value, $scope.filterValue.value,$scope.startKey, $scope.reportsCount, $scope.fullSearch, successHandler, errorHandler);
|
||||
}
|
||||
};
|
||||
$scope.changeFilterValues = function() {
|
||||
|
||||
$scope.changeFilterValues = function() {
|
||||
if($scope.filterName === $scope.noFilter) {
|
||||
$scope.filterValue = $scope.noFilterValue;
|
||||
$scope.filterValueSelected();
|
||||
} else {
|
||||
var getFilteredValues;
|
||||
if($scope.filterName.value === "androidver") {
|
||||
getFilteredValues = ReportsStore.androidVersionsList;
|
||||
} else if ($scope.filterName.value === "appver") {
|
||||
getFilteredValues = ReportsStore.appVersionsList;
|
||||
}
|
||||
|
||||
if($scope.filterName === $scope.noFilter) {
|
||||
$scope.filterValue = $scope.noFilterValue;
|
||||
$scope.filterValueSelected();
|
||||
} else {
|
||||
var getFilteredValues;
|
||||
if($scope.filterName.value === "androidver") {
|
||||
getFilteredValues = ReportsStore.androidVersionsList;
|
||||
} else if ($scope.filterName.value === "appver") {
|
||||
getFilteredValues = ReportsStore.appVersionsList;
|
||||
if(getFilteredValues) {
|
||||
getFilteredValues(function(data){
|
||||
console.log("Update filter values");
|
||||
$scope.filterValues.length = 0;
|
||||
$scope.filterValues.push($scope.noFilterValue);
|
||||
for(var row = 0; row < data.rows.length; row++) {
|
||||
$scope.filterValues.push({value:data.rows[row].key[0], label:data.rows[row].key[0]});
|
||||
}
|
||||
$scope.filterValues.sort();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(getFilteredValues) {
|
||||
getFilteredValues(function(data){
|
||||
console.log("Update filter values");
|
||||
$scope.filterValues.length = 0;
|
||||
$scope.filterValues.push($scope.noFilterValue);
|
||||
for(var row = 0; row < data.rows.length; row++) {
|
||||
$scope.filterValues.push({value:data.rows[row].key[0], label:data.rows[row].key[0]});
|
||||
}
|
||||
$scope.filterValues.sort();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.filterValueSelected = function() {
|
||||
// reset pagination
|
||||
$scope.startKey = null;
|
||||
$scope.nextKey = null;
|
||||
$scope.previousStartKeys.length = 0;
|
||||
$scope.getData();
|
||||
};
|
||||
|
||||
$scope.filterValueSelected = function() {
|
||||
// reset pagination
|
||||
$scope.startKey = null;
|
||||
$scope.nextKey = null;
|
||||
$scope.previousStartKeys.length = 0;
|
||||
$scope.loadReport = function(report) {
|
||||
$scope.selectedReport = ReportsStore.reportDetails(report.id, function(data) {
|
||||
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
|
||||
data.formatedCrashDate = moment(data.USER_CRASH_DATE).format('LLL');
|
||||
data.formatedTimestamp = moment(data.timestamp).format('LLL');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.getData();
|
||||
};
|
||||
|
||||
$scope.loadReport = function(report) {
|
||||
$scope.selectedReport = ReportsStore.reportDetails(report.id, function(data) {
|
||||
data.readableUptime = moment.duration(data.uptime, 'seconds').humanize();
|
||||
data.formatedCrashDate = moment(data.USER_CRASH_DATE).format('LLL');
|
||||
data.formatedTimestamp = moment(data.timestamp).format('LLL');
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
$scope.$on(acralyzerEvents.LOGGED_IN, $scope.getData);
|
||||
$scope.$on(acralyzerEvents.LOGGED_OUT, $scope.getData);
|
||||
$scope.getData();
|
||||
}
|
||||
|
||||
|
||||
acralyzer.controller('ReportsBrowserCtrl', ReportsBrowserCtrl);
|
||||
acralyzer.controller('ReportsBrowserCtrl', ReportsBrowserCtrl);
|
||||
|
||||
})(window.acralyzerConfig,window.angular,window.acralyzer,window.acralyzerEvents);
|
||||
|
@ -17,23 +17,23 @@
|
||||
along with Acralyzer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
(function(acralyzerConfig,angular,acralyzerEvents) {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
angular.module('acra-storage', ['ngResource']).
|
||||
angular.module('acra-storage', ['ngResource']).
|
||||
factory('ReportsStore', function ($resource, $http, $rootScope) {
|
||||
// ReportsStore service instance
|
||||
/** @namespace */
|
||||
var ReportsStore = {},
|
||||
lastseq = -1,
|
||||
continuePolling = true,
|
||||
dbName = "";
|
||||
lastseq = -1,
|
||||
continuePolling = true,
|
||||
dbName = "";
|
||||
|
||||
/**
|
||||
* Switch to another app, i.e. reports storage database.
|
||||
* @param newAppName The app name. The database name is determined by adding prefix set in
|
||||
* acralyzerConfig.appDBPrefix
|
||||
* @param cb callback to be executed after database changed.
|
||||
*/
|
||||
* Switch to another app, i.e. reports storage database.
|
||||
* @param newAppName The app name. The database name is determined by adding prefix set in
|
||||
* acralyzerConfig.appDBPrefix
|
||||
* @param cb callback to be executed after database changed.
|
||||
*/
|
||||
ReportsStore.setApp = function (newAppName, cb) {
|
||||
dbName = acralyzerConfig.appDBPrefix + newAppName;
|
||||
ReportsStore.views = $resource('/' + dbName + '/_design/acra-storage/_view/:view');
|
||||
@ -45,11 +45,11 @@ angular.module('acra-storage', ['ngResource']).
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the list of available apps for which we have crash reports databases.
|
||||
* Looks for all CouchDB databases starting with
|
||||
* @param cb : callback which will receive an array of strings (app names) as a parameter.
|
||||
* @param errorHandler : callback to be triggered if an error occurs.
|
||||
*/
|
||||
* Gets the list of available apps for which we have crash reports databases.
|
||||
* Looks for all CouchDB databases starting with
|
||||
* @param cb : callback which will receive an array of strings (app names) as a parameter.
|
||||
* @param errorHandler : callback to be triggered if an error occurs.
|
||||
*/
|
||||
ReportsStore.listApps = function(cb, errorHandler) {
|
||||
console.log("get _all_dbs");
|
||||
var filterDbsCallback = function(data) {
|
||||
@ -68,12 +68,12 @@ angular.module('acra-storage', ['ngResource']).
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the number of reports per unit of time.
|
||||
* @param grouplvl Grouping level: Year = 1, Month = 2, Day = 3, Hour = 4, Minute = 5, Second = 6.
|
||||
* @param cb Callback which receives the results.
|
||||
* @param errorHandler Called in case of error while retreiving data
|
||||
* @return Key: date/time, Value: quantity
|
||||
*/
|
||||
* Gets the number of reports per unit of time.
|
||||
* @param grouplvl Grouping level: Year = 1, Month = 2, Day = 3, Hour = 4, Minute = 5, Second = 6.
|
||||
* @param cb Callback which receives the results.
|
||||
* @param errorHandler Called in case of error while retreiving data
|
||||
* @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);
|
||||
};
|
||||
|
@ -29,7 +29,7 @@
|
||||
when('/reports-browser/:app', {templateUrl: 'partials/reports-browser.html', controller: 'ReportsBrowserCtrl', activetab: "reports-browser"}).
|
||||
when('/report-details/:app/:reportId', {templateUrl: 'partials/report-details.html', controller: 'ReportDetailsCtrl', activetab: "none"}).
|
||||
otherwise({redirectTo: '/dashboard'});
|
||||
}]);
|
||||
}]);
|
||||
|
||||
acralyzer.directive('prettyprint',function(){
|
||||
return {
|
||||
|
@ -42,7 +42,8 @@
|
||||
if (ret.username && ret.isAdmin && ret.hasAdminPath === undefined )
|
||||
{
|
||||
$.ajax({
|
||||
type: "GET", url: $.couch.urlPrefix + "/_config/admins/" + ret.username,
|
||||
type: "GET",
|
||||
url: $.couch.urlPrefix + "/_config/admins/" + ret.username,
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
},
|
||||
@ -98,7 +99,8 @@
|
||||
}
|
||||
if (ret.isAdmin && ret.hasAdminPath === true) {
|
||||
$.ajax({
|
||||
type: "PUT", url: $.couch.urlPrefix + "/_config/admins/" + ret.username,
|
||||
type: "PUT",
|
||||
url: $.couch.urlPrefix + "/_config/admins/" + ret.username,
|
||||
data: '"' + password + '"',
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
|
Loading…
Reference in New Issue
Block a user