Style with jscs.
This commit is contained in:
parent
655d72d4ae
commit
e5721b3573
35
.jscsrc
Normal file
35
.jscsrc
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"preset": "google",
|
||||||
|
"fileExtensions": [".js", "jscs"],
|
||||||
|
|
||||||
|
"requireSemicolons": true,
|
||||||
|
"requireParenthesesAroundIIFE": true,
|
||||||
|
"maximumLineLength": 120,
|
||||||
|
"validateLineBreaks": "LF",
|
||||||
|
"validateIndentation": 4,
|
||||||
|
"disallowTrailingComma": true,
|
||||||
|
"disallowUnusedParams": true,
|
||||||
|
|
||||||
|
"disallowSpacesInsideObjectBrackets": null,
|
||||||
|
"disallowImplicitTypeConversion": ["string"],
|
||||||
|
|
||||||
|
"safeContextKeyword": "_this",
|
||||||
|
|
||||||
|
"jsDoc": {
|
||||||
|
"checkAnnotations": "closurecompiler",
|
||||||
|
"checkParamNames": true,
|
||||||
|
"requireParamTypes": true,
|
||||||
|
"checkRedundantParams": true,
|
||||||
|
"checkReturnTypes": true,
|
||||||
|
"checkRedundantReturns": true,
|
||||||
|
"requireReturnTypes": true,
|
||||||
|
"checkTypes": "capitalizedNativeCase",
|
||||||
|
"checkRedundantAccess": true,
|
||||||
|
"requireNewlineAfterDescription": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"excludeFiles": [
|
||||||
|
"test/data/**",
|
||||||
|
"patterns/*"
|
||||||
|
]
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
// vim: set tw=80 ts=4 sw=4 sts=4:
|
||||||
/*
|
/*
|
||||||
This file is part of Accountant.
|
This file is part of Accountant.
|
||||||
|
|
||||||
@ -14,7 +15,6 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
// vim: set tw=80 ts=2 sw=2 sts=2:
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('accountant.accounts', [
|
angular.module('accountant.accounts', [
|
||||||
@ -66,92 +66,100 @@ angular.module('accountant.accounts', [
|
|||||||
* overdraft.
|
* overdraft.
|
||||||
*/
|
*/
|
||||||
$scope.rowClass = function(account) {
|
$scope.rowClass = function(account) {
|
||||||
if(!account || !account.authorized_overdraft || !account.current) {
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
return;
|
if (!account || !account.authorized_overdraft || !account.current) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
|
||||||
if(account.current < account.authorized_overdraft) {
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
return 'danger';
|
if (account.current < account.authorized_overdraft) {
|
||||||
} else if(account.current < 0) {
|
return 'danger';
|
||||||
return 'warning';
|
} else if (account.current < 0) {
|
||||||
}
|
return 'warning';
|
||||||
|
}
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the class for a value compared to account authorized overdraft.
|
* Return the class for a value compared to account authorized overdraft.
|
||||||
*/
|
*/
|
||||||
$scope.valueClass = function(account, value) {
|
$scope.valueClass = function(account, value) {
|
||||||
if(!account || !value) {
|
if (!account || !value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(value < account.authorized_overdraft) {
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
if (value < account.authorized_overdraft) {
|
||||||
return 'text-danger';
|
return 'text-danger';
|
||||||
} else if(value < 0) {
|
} else if (value < 0) {
|
||||||
return 'text-warning';
|
return 'text-warning';
|
||||||
}
|
}
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add an empty account.
|
* Add an empty account.
|
||||||
*/
|
*/
|
||||||
$scope.add = function() {
|
$scope.add = function() {
|
||||||
var account = new Account({
|
var account = new Account({
|
||||||
authorized_overdraft: 0
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
authorized_overdraft: 0
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
});
|
||||||
|
|
||||||
// Insert account at the begining of the array.
|
// Insert account at the begining of the array.
|
||||||
$scope.accounts.splice(0, 0, account);
|
$scope.accounts.splice(0, 0, account);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cancel account edition. Remove it from array if a new one.
|
* Cancel account edition. Remove it from array if a new one.
|
||||||
*/
|
*/
|
||||||
$scope.cancelEdit = function(rowform, account, $index) {
|
$scope.cancelEdit = function(rowform, account, $index) {
|
||||||
if(!account.id) {
|
if (!account.id) {
|
||||||
// Account not saved, just remove it from array.
|
// Account not saved, just remove it from array.
|
||||||
$scope.accounts.splice($index, 1);
|
$scope.accounts.splice($index, 1);
|
||||||
} else {
|
} else {
|
||||||
rowform.$cancel();
|
rowform.$cancel();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save account.
|
* Save account.
|
||||||
*/
|
*/
|
||||||
$scope.save = function(account) {
|
$scope.save = function(account) {
|
||||||
//var account = $scope.accounts[$index];
|
//var account = $scope.accounts[$index];
|
||||||
|
|
||||||
//account = angular.merge(account, $data);
|
//account = angular.merge(account, $data);
|
||||||
|
|
||||||
return account.$save().then(function(data) {
|
return account.$save().then(function(data) {
|
||||||
Notification.success('Account #' + data.id + ' saved.');
|
Notification.success('Account #' + data.id + ' saved.');
|
||||||
|
|
||||||
// TODO Alexis Lahouze 2016-03-08 Update solds
|
// TODO Alexis Lahouze 2016-03-08 Update solds
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete an account.
|
* Delete an account.
|
||||||
*/
|
*/
|
||||||
$scope.delete = function(account, $index) {
|
$scope.delete = function(account, $index) {
|
||||||
var id = account.id;
|
var id = account.id;
|
||||||
|
|
||||||
$ngBootbox.confirm(
|
$ngBootbox.confirm(
|
||||||
'Voulez-vous supprimer le compte \'' + account.name + '\' ?',
|
'Voulez-vous supprimer le compte \'' + account.name + '\' ?',
|
||||||
function(result) {
|
function(result) {
|
||||||
if(result) {
|
if (result) {
|
||||||
account.$delete().then(function() {
|
account.$delete().then(function() {
|
||||||
Notification.success('Account #' + id + ' deleted.');
|
Notification.success('Account #' + id + ' deleted.');
|
||||||
|
|
||||||
// Remove account from array.
|
// Remove account from array.
|
||||||
$scope.accounts.splice($index, 1);
|
$scope.accounts.splice($index, 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load accounts.
|
// Load accounts.
|
||||||
@ -169,46 +177,50 @@ angular.module('accountant.accounts', [
|
|||||||
link: function(scope, element) {
|
link: function(scope, element) {
|
||||||
var title = 'Account';
|
var title = 'Account';
|
||||||
|
|
||||||
if(scope.account && scope.account.id) {
|
if (scope.account && scope.account.id) {
|
||||||
title = title + ' #' + scope.account.id;
|
title = title + ' #' + scope.account.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.form = {};
|
scope.form = {};
|
||||||
|
|
||||||
scope.submitForm = function() {
|
scope.submitForm = function() {
|
||||||
// check to make sure the form is completely valid
|
// check to make sure the form is completely valid
|
||||||
if (!scope.form.$valid) {
|
if (!scope.form.$valid) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorized overdraft is a positive integer but data is a negative integer.
|
|
||||||
scope.data.authorized_overdraft = -scope.data.authorized_overdraft
|
|
||||||
|
|
||||||
angular.copy(scope.data, scope.account);
|
|
||||||
|
|
||||||
// Save account
|
|
||||||
console.log(scope.account);
|
|
||||||
return scope.account.$save().then(
|
|
||||||
function(data) {
|
|
||||||
Notification.success('Account #' + data.id + ' saved.');
|
|
||||||
|
|
||||||
scope.account.getSolds();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}, function(data) {
|
|
||||||
Notification.error('Error while saving account #' + data.id);
|
|
||||||
scope.account.getSolds();
|
|
||||||
console.log(data);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Authorized overdraft is a positive integer but data is a negative integer.
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
scope.data.authorized_overdraft = -scope.data.authorized_overdraft;
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
|
||||||
|
angular.copy(scope.data, scope.account);
|
||||||
|
|
||||||
|
// Save account
|
||||||
|
console.log(scope.account);
|
||||||
|
return scope.account.$save().then(
|
||||||
|
function(data) {
|
||||||
|
Notification.success('Account #' + data.id + ' saved.');
|
||||||
|
|
||||||
|
scope.account.getSolds();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}, function(data) {
|
||||||
|
Notification.error('Error while saving account #' + data.id);
|
||||||
|
scope.account.getSolds();
|
||||||
|
console.log(data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
element.on('click', function() {
|
element.on('click', function() {
|
||||||
// Create new account if not passed in ng-model.
|
// Create new account if not passed in ng-model.
|
||||||
if(!scope.account) {
|
if (!scope.account) {
|
||||||
scope.account = new Account({
|
scope.account = new Account({
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
authorized_overdraft: 0
|
authorized_overdraft: 0
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +228,9 @@ angular.module('accountant.accounts', [
|
|||||||
angular.copy(scope.account, scope.data);
|
angular.copy(scope.account, scope.data);
|
||||||
|
|
||||||
// Authorized overdraft must be positive in form.
|
// Authorized overdraft must be positive in form.
|
||||||
scope.data.authorized_overdraft = -scope.data.authorized_overdraft
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
scope.data.authorized_overdraft = -scope.data.authorized_overdraft;
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
|
||||||
// Open dialog with form.
|
// Open dialog with form.
|
||||||
$ngBootbox.customDialog({
|
$ngBootbox.customDialog({
|
||||||
@ -240,4 +254,5 @@ angular.module('accountant.accounts', [
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// vim: set tw=80 ts=4 sw=4 sts=4:
|
||||||
/*
|
/*
|
||||||
This file is part of Accountant.
|
This file is part of Accountant.
|
||||||
|
|
||||||
@ -14,7 +15,6 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
// vim: set tw=80 ts=2 sw=2 sts=2:
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('accountant', [
|
angular.module('accountant', [
|
||||||
@ -29,12 +29,12 @@ angular.module('accountant', [
|
|||||||
|
|
||||||
.factory('sessionInjector', ['$storage', function($storage) {
|
.factory('sessionInjector', ['$storage', function($storage) {
|
||||||
var sessionInjector = {
|
var sessionInjector = {
|
||||||
request : function(config) {
|
request: function(config) {
|
||||||
var token = $storage.get('token');
|
var token = $storage.get('token');
|
||||||
|
|
||||||
if(token) {
|
if (token) {
|
||||||
var token_type = $storage.get('token_type');
|
var tokenType = $storage.get('token_type');
|
||||||
var authorization = token_type + ' ' + token;
|
var authorization = tokenType + ' ' + token;
|
||||||
config.headers.Authorization = authorization;
|
config.headers.Authorization = authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,30 +53,29 @@ angular.module('accountant', [
|
|||||||
.config(['$routeProvider', function($routeProvider) {
|
.config(['$routeProvider', function($routeProvider) {
|
||||||
// Defining template and controller in function of route.
|
// Defining template and controller in function of route.
|
||||||
$routeProvider
|
$routeProvider
|
||||||
.when('/account/:accountId/operations', {
|
.when('/account/:accountId/operations', {
|
||||||
templateUrl: 'views/operations.html',
|
templateUrl: 'views/operations.html',
|
||||||
controller: 'OperationController',
|
controller: 'OperationController',
|
||||||
controllerAs: 'operationsCtrl'
|
controllerAs: 'operationsCtrl'
|
||||||
})
|
})
|
||||||
.when('/account/:accountId/scheduler', {
|
.when('/account/:accountId/scheduler', {
|
||||||
templateUrl: 'views/scheduler.html',
|
templateUrl: 'views/scheduler.html',
|
||||||
controller: 'SchedulerController',
|
controller: 'SchedulerController',
|
||||||
controllerAs: 'schedulerCtrl'
|
controllerAs: 'schedulerCtrl'
|
||||||
})
|
})
|
||||||
.when('/accounts', {
|
.when('/accounts', {
|
||||||
templateUrl: 'views/accounts.html',
|
templateUrl: 'views/accounts.html',
|
||||||
controller: 'AccountController',
|
controller: 'AccountController',
|
||||||
controllerAs: 'accountsCtrl'
|
controllerAs: 'accountsCtrl'
|
||||||
})
|
})
|
||||||
.otherwise({
|
.otherwise({
|
||||||
redirectTo: '/accounts'
|
redirectTo: '/accounts'
|
||||||
});
|
});
|
||||||
|
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.config(['$storageProvider', function($storageProvider) {
|
.config(['$storageProvider', function($storageProvider) {
|
||||||
// Configure storage
|
// Configure storage
|
||||||
// Set global prefix for stored keys
|
// Set global prefix for stored keys
|
||||||
$storageProvider.setPrefix('accountant');
|
$storageProvider.setPrefix('accountant');
|
||||||
|
|
||||||
// Change the default storage engine
|
// Change the default storage engine
|
||||||
@ -98,54 +97,58 @@ angular.module('accountant', [
|
|||||||
$scope.dialogShown = false;
|
$scope.dialogShown = false;
|
||||||
|
|
||||||
$scope.showLoginForm = function() {
|
$scope.showLoginForm = function() {
|
||||||
// First, if there are registered credentials, use them
|
// First, if there are registered credentials, use them
|
||||||
if($scope.dialogShown) {
|
if ($scope.dialogShown) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
$scope.dialogShown = true;
|
|
||||||
|
|
||||||
$storage.clear();
|
|
||||||
|
|
||||||
$ngBootbox.customDialog({
|
|
||||||
title: 'Authentification requise',
|
|
||||||
templateUrl: 'views/login.tmpl.html',
|
|
||||||
buttons: {
|
|
||||||
login: {
|
|
||||||
label: 'Login',
|
|
||||||
className: 'btn-primary',
|
|
||||||
callback: function() {
|
|
||||||
$scope.dialogShown = false;
|
|
||||||
|
|
||||||
var email = $('#email').val();
|
|
||||||
var password = $('#password').val();
|
|
||||||
$http.post(
|
|
||||||
'/api/user/login',
|
|
||||||
{
|
|
||||||
'email': email,
|
|
||||||
'password': password
|
|
||||||
}
|
|
||||||
).success(function(result) {
|
|
||||||
// TODO Alexis Lahouze 2015-08-28 Handle callback.
|
|
||||||
// Call to /api/login to retrieve the token
|
|
||||||
$storage.set('token_type', result.token_type);
|
|
||||||
$storage.set('token', result.token);
|
|
||||||
$storage.set('expiration_date', result.expiration_date);
|
|
||||||
|
|
||||||
authService.loginConfirmed();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
label: 'Annuler',
|
|
||||||
className: 'btn-default',
|
|
||||||
callback: function() {
|
|
||||||
authService.loginCancelled(null, 'Login cancelled by user action.');
|
|
||||||
$scope.dialogShown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
$scope.dialogShown = true;
|
||||||
|
|
||||||
|
$storage.clear();
|
||||||
|
|
||||||
|
$ngBootbox.customDialog({
|
||||||
|
title: 'Authentification requise',
|
||||||
|
templateUrl: 'views/login.tmpl.html',
|
||||||
|
buttons: {
|
||||||
|
login: {
|
||||||
|
label: 'Login',
|
||||||
|
className: 'btn-primary',
|
||||||
|
callback: function() {
|
||||||
|
$scope.dialogShown = false;
|
||||||
|
|
||||||
|
var email = $('#email').val();
|
||||||
|
var password = $('#password').val();
|
||||||
|
$http.post(
|
||||||
|
'/api/user/login',
|
||||||
|
{
|
||||||
|
'email': email,
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
).success(function(result) {
|
||||||
|
// TODO Alexis Lahouze 2015-08-28 Handle callback.
|
||||||
|
// Call to /api/login to retrieve the token
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
$storage.set('token_type', result.token_type);
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
$storage.set('token', result.token);
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
$storage.set('expiration_date', result.expiration_date);
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
|
||||||
|
authService.loginConfirmed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
label: 'Annuler',
|
||||||
|
className: 'btn-default',
|
||||||
|
callback: function() {
|
||||||
|
authService.loginCancelled(null, 'Login cancelled by user action.');
|
||||||
|
$scope.dialogShown = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$rootScope.$on('event:auth-loginRequired', $scope.showLoginForm);
|
$rootScope.$on('event:auth-loginRequired', $scope.showLoginForm);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// vim: set tw=80 ts=4 sw=4 sts=4:
|
||||||
/*
|
/*
|
||||||
This file is part of Accountant.
|
This file is part of Accountant.
|
||||||
|
|
||||||
@ -14,7 +15,6 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
// vim: set tw=80 ts=2 sw=2 sts=2:
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('accountant.operations', [
|
angular.module('accountant.operations', [
|
||||||
@ -24,7 +24,7 @@ angular.module('accountant.operations', [
|
|||||||
'ngBootbox',
|
'ngBootbox',
|
||||||
'ui-notification',
|
'ui-notification',
|
||||||
'mgcrea.ngStrap',
|
'mgcrea.ngStrap',
|
||||||
'highcharts-ng',
|
'highcharts-ng'
|
||||||
])
|
])
|
||||||
|
|
||||||
.config(['$resourceProvider', function($resourceProvider) {
|
.config(['$resourceProvider', function($resourceProvider) {
|
||||||
@ -32,7 +32,7 @@ angular.module('accountant.operations', [
|
|||||||
$resourceProvider.defaults.stripTrailingSlashes = false;
|
$resourceProvider.defaults.stripTrailingSlashes = false;
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.factory('Operation', [ '$resource', function($resource) {
|
.factory('Operation', ['$resource', function($resource) {
|
||||||
return $resource(
|
return $resource(
|
||||||
'/api/operation/:id', {
|
'/api/operation/:id', {
|
||||||
id: '@id'
|
id: '@id'
|
||||||
@ -40,29 +40,35 @@ angular.module('accountant.operations', [
|
|||||||
);
|
);
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.factory('OHLC', [ '$resource', '$routeParams',
|
.factory('OHLC', ['$resource', '$routeParams',
|
||||||
function($resource, $routeParams) {
|
function($resource, $routeParams) {
|
||||||
return $resource(
|
return $resource(
|
||||||
'/api/account/:account_id/ohlc', {
|
'/api/account/:account_id/ohlc', {
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
account_id: $routeParams.accountId
|
account_id: $routeParams.accountId
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.factory('Category', [ '$resource', '$routeParams',
|
.factory('Category', ['$resource', '$routeParams',
|
||||||
function($resource, $routeParams) {
|
function($resource, $routeParams) {
|
||||||
return $resource(
|
return $resource(
|
||||||
'/api/account/:account_id/category', {
|
'/api/account/:account_id/category', {
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
account_id: $routeParams.accountId
|
account_id: $routeParams.accountId
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.factory('Balance', [ '$resource', '$routeParams',
|
.factory('Balance', ['$resource', '$routeParams',
|
||||||
function($resource, $routeParams) {
|
function($resource, $routeParams) {
|
||||||
return $resource(
|
return $resource(
|
||||||
'/api/account/:account_id/balance', {
|
'/api/account/:account_id/balance', {
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
account_id: $routeParams.accountId
|
account_id: $routeParams.accountId
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}])
|
}])
|
||||||
@ -70,450 +76,457 @@ angular.module('accountant.operations', [
|
|||||||
/*
|
/*
|
||||||
* Controller for category chart.
|
* Controller for category chart.
|
||||||
*/
|
*/
|
||||||
.controller(
|
.controller('CategoryChartController', [
|
||||||
'CategoryChartController', [
|
|
||||||
'$rootScope', '$scope', '$http', 'Category', 'Balance',
|
'$rootScope', '$scope', '$http', 'Category', 'Balance',
|
||||||
function($rootScope, $scope, $http, Category, Balance) {
|
function($rootScope, $scope, $http, Category, Balance) {
|
||||||
|
var colors = Highcharts.getOptions().colors;
|
||||||
|
$scope.revenueColor = colors[2];
|
||||||
|
$scope.expenseColor = colors[3];
|
||||||
|
|
||||||
var colors = Highcharts.getOptions().colors;
|
// Configure pie chart for categories.
|
||||||
$scope.revenueColor = colors[2];
|
$scope.config = {
|
||||||
$scope.expenseColor = colors[3];
|
options: {
|
||||||
|
chart: {
|
||||||
|
type: 'pie',
|
||||||
|
animation: {
|
||||||
|
duration: 500
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
pie: {
|
||||||
|
startAngle: -90
|
||||||
|
},
|
||||||
|
series: {
|
||||||
|
allowPointSelect: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
valueDecimals: 2,
|
||||||
|
valueSuffix: '€'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
title: {
|
||||||
|
text: 'Categories'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: 'Répartition dépenses/recettes'
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: 'Value',
|
||||||
|
data: [],
|
||||||
|
innerSize: '33%',
|
||||||
|
size: '60%',
|
||||||
|
dataLabels: {
|
||||||
|
formatter: function() {
|
||||||
|
return this.point.name;
|
||||||
|
},
|
||||||
|
distance: -40
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
name: 'Value',
|
||||||
|
data: [],
|
||||||
|
innerSize: '66%',
|
||||||
|
size: '60%',
|
||||||
|
dataLabels: {
|
||||||
|
formatter: function() {
|
||||||
|
return this.point.name !== null && this.percentage >= 2.5 ? this.point.name : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
// Configure pie chart for categories.
|
$scope.brightenColor = function(color) {
|
||||||
$scope.config = {
|
var brightness = 0.2;
|
||||||
options: {
|
|
||||||
chart: {
|
|
||||||
type: 'pie',
|
|
||||||
animation: {
|
|
||||||
duration: 500
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plotOptions: {
|
|
||||||
pie: {
|
|
||||||
startAngle: -90
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
allowPointSelect: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
valueDecimals: 2,
|
|
||||||
valueSuffix: '€'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
title: {
|
|
||||||
text: 'Categories'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: 'Répartition dépenses/recettes'
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
name: 'Value',
|
|
||||||
data: [],
|
|
||||||
innerSize: '33%',
|
|
||||||
size: '60%',
|
|
||||||
dataLabels: {
|
|
||||||
formatter: function() {
|
|
||||||
return this.point.name;
|
|
||||||
},
|
|
||||||
distance: -40
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'Value',
|
|
||||||
data: [],
|
|
||||||
innerSize: '66%',
|
|
||||||
size: '60%',
|
|
||||||
dataLabels: {
|
|
||||||
formatter: function() {
|
|
||||||
return this.point.name !== null && this.percentage >= 2.5 ? this.point.name : null;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.brightenColor = function(color) {
|
return Highcharts.Color(color).brighten(brightness).get();
|
||||||
var brightness = 0.2;
|
};
|
||||||
|
|
||||||
return Highcharts.Color(color).brighten(brightness).get();
|
// Load categories, mainly to populate the pie chart.
|
||||||
};
|
$scope.load = function(begin, end) {
|
||||||
|
$scope.config.loading = true;
|
||||||
|
|
||||||
// Load categories, mainly to populate the pie chart.
|
Category.query({
|
||||||
$scope.load = function(begin, end) {
|
begin: begin.format('YYYY-MM-DD'),
|
||||||
$scope.config.loading = true;
|
end: end.format('YYYY-MM-DD')
|
||||||
|
}, function(data) {
|
||||||
|
var expenses = [];
|
||||||
|
var revenues = [];
|
||||||
|
|
||||||
Category.query({
|
var expenseColor = $scope.brightenColor($scope.expenseColor);
|
||||||
begin: begin.format('YYYY-MM-DD'),
|
var revenueColor = $scope.brightenColor($scope.revenueColor);
|
||||||
end: end.format('YYYY-MM-DD')
|
|
||||||
}, function(data) {
|
|
||||||
var expenses = [], revenues = [];
|
|
||||||
|
|
||||||
var expenseColor = $scope.brightenColor($scope.expenseColor);
|
angular.forEach(angular.fromJson(data), function(category) {
|
||||||
var revenueColor = $scope.brightenColor($scope.revenueColor);
|
expenses.push({
|
||||||
|
name: category.category,
|
||||||
|
y: -category.expenses,
|
||||||
|
color: expenseColor
|
||||||
|
});
|
||||||
|
|
||||||
angular.forEach(angular.fromJson(data), function(category) {
|
revenues.push({
|
||||||
expenses.push({
|
name: category.category,
|
||||||
name: category.category,
|
y: category.revenues,
|
||||||
y: -category.expenses,
|
color: revenueColor
|
||||||
color: expenseColor
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Note: expenses and revenues must be in the same order than in series[0].
|
||||||
|
$scope.config.series[1].data = revenues.concat(expenses);
|
||||||
|
|
||||||
|
$scope.config.loading = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get account balance.
|
||||||
|
*/
|
||||||
|
$scope.getBalance = function(begin, end) {
|
||||||
|
Balance.get({
|
||||||
|
begin: begin.format('YYYY-MM-DD'),
|
||||||
|
end: end.format('YYYY-MM-DD')
|
||||||
|
}, function(balance) {
|
||||||
|
// Update pie chart subtitle with Balance.
|
||||||
|
$scope.config.subtitle = {
|
||||||
|
text: 'Balance: ' + balance.balance
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.config.series[0].data = [{
|
||||||
|
name: 'Revenues',
|
||||||
|
y: balance.revenues,
|
||||||
|
color: $scope.revenueColor
|
||||||
|
}, {
|
||||||
|
name: 'Expenses',
|
||||||
|
y: -balance.expenses,
|
||||||
|
color: $scope.expenseColor
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reload categories and account status on range selection.
|
||||||
|
$rootScope.$on('rangeSelectedEvent', function(e, args) {
|
||||||
|
$scope.load(args.begin, args.end);
|
||||||
|
$scope.getBalance(args.begin, args.end);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
revenues.push({
|
])
|
||||||
name: category.category,
|
|
||||||
y: category.revenues,
|
|
||||||
color: revenueColor
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Note: expenses and revenues must be in the same order than in series[0].
|
|
||||||
$scope.config.series[1].data = revenues.concat(expenses);
|
|
||||||
|
|
||||||
$scope.config.loading = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get account balance.
|
|
||||||
*/
|
|
||||||
$scope.getBalance = function(begin, end) {
|
|
||||||
Balance.get({
|
|
||||||
begin: begin.format('YYYY-MM-DD'),
|
|
||||||
end: end.format('YYYY-MM-DD')
|
|
||||||
}, function(balance) {
|
|
||||||
// Update pie chart subtitle with Balance.
|
|
||||||
$scope.config.subtitle = {
|
|
||||||
text: 'Balance: ' + balance.balance
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.config.series[0].data = [{
|
|
||||||
name: 'Revenues',
|
|
||||||
y: balance.revenues,
|
|
||||||
color: $scope.revenueColor
|
|
||||||
}, {
|
|
||||||
name: 'Expenses',
|
|
||||||
y: -balance.expenses,
|
|
||||||
color: $scope.expenseColor,
|
|
||||||
}];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reload categories and account status on range selection.
|
|
||||||
$rootScope.$on('rangeSelectedEvent', function(e, args) {
|
|
||||||
$scope.load(args.begin, args.end);
|
|
||||||
$scope.getBalance(args.begin, args.end);
|
|
||||||
});
|
|
||||||
}])
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Controller for the sold chart.
|
* Controller for the sold chart.
|
||||||
*/
|
*/
|
||||||
.controller(
|
.controller('SoldChartController', [
|
||||||
'SoldChartController', [
|
|
||||||
'$rootScope', '$scope', '$http', 'OHLC',
|
'$rootScope', '$scope', '$http', 'OHLC',
|
||||||
function($rootScope, $scope, $http, OHLC) {
|
function($rootScope, $scope, $http, OHLC) {
|
||||||
// Configure chart for operations.
|
// Configure chart for operations.
|
||||||
$scope.config = {
|
$scope.config = {
|
||||||
options: {
|
options: {
|
||||||
chart: {
|
chart: {
|
||||||
zoomType: 'x'
|
zoomType: 'x'
|
||||||
},
|
},
|
||||||
rangeSelector: {
|
rangeSelector: {
|
||||||
buttons: [{
|
buttons: [{
|
||||||
type: 'month',
|
type: 'month',
|
||||||
count: 1,
|
count: 1,
|
||||||
text: '1m'
|
text: '1m'
|
||||||
}, {
|
}, {
|
||||||
type: 'month',
|
type: 'month',
|
||||||
count: 3,
|
count: 3,
|
||||||
text: '3m'
|
text: '3m'
|
||||||
}, {
|
}, {
|
||||||
type: 'month',
|
type: 'month',
|
||||||
count: 6,
|
count: 6,
|
||||||
text: '6m'
|
text: '6m'
|
||||||
}, {
|
}, {
|
||||||
type: 'year',
|
type: 'year',
|
||||||
count: 1,
|
count: 1,
|
||||||
text: '1y'
|
text: '1y'
|
||||||
}, {
|
}, {
|
||||||
type: 'all',
|
type: 'all',
|
||||||
text: 'All'
|
text: 'All'
|
||||||
}],
|
}],
|
||||||
selected: 0,
|
selected: 0
|
||||||
},
|
},
|
||||||
navigator: {
|
navigator: {
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
crosshairs: true,
|
crosshairs: true,
|
||||||
shared: true,
|
shared: true,
|
||||||
valueDecimals: 2,
|
valueDecimals: 2,
|
||||||
valueSuffix: '€'
|
valueSuffix: '€'
|
||||||
},
|
},
|
||||||
scrollbar: {
|
scrollbar: {
|
||||||
liveRedraw: false
|
liveRedraw: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
series: [{
|
series: [{
|
||||||
type: 'ohlc',
|
type: 'ohlc',
|
||||||
name: 'Sold',
|
name: 'Sold',
|
||||||
data: [],
|
data: [],
|
||||||
dataGrouping : {
|
dataGrouping: {
|
||||||
units : [[
|
units: [[
|
||||||
'week', // unit name
|
'week', // unit name
|
||||||
[1] // allowed multiples
|
[1] // allowed multiples
|
||||||
], [
|
], [
|
||||||
'month',
|
'month',
|
||||||
[1, 2, 3, 4, 6]
|
[1, 2, 3, 4, 6]
|
||||||
]]
|
]]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
title: {
|
title: {
|
||||||
text: 'Sold evolution'
|
text: 'Sold evolution'
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'datetime',
|
type: 'datetime',
|
||||||
dateTimeLabelFormats: {
|
dateTimeLabelFormats: {
|
||||||
month: '%e. %b',
|
month: '%e. %b',
|
||||||
year: '%Y'
|
year: '%Y'
|
||||||
},
|
},
|
||||||
minRange: 3600 * 1000 * 24 * 14, // 2 weeks
|
minRange: 3600 * 1000 * 24 * 14, // 2 weeks
|
||||||
events: {
|
events: {
|
||||||
afterSetExtremes: function(e) {
|
afterSetExtremes: function(e) {
|
||||||
$scope.$emit('rangeSelectedEvent', {
|
$scope.$emit('rangeSelectedEvent', {
|
||||||
begin: moment.utc(e.min), end: moment.utc(e.max)
|
begin: moment.utc(e.min), end: moment.utc(e.max)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
currentMin: moment.utc().startOf('month'),
|
currentMin: moment.utc().startOf('month'),
|
||||||
currentMax: moment.utc().endOf('month')
|
currentMax: moment.utc().endOf('month')
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
plotLines: [{
|
plotLines: [{
|
||||||
color: 'orange',
|
color: 'orange',
|
||||||
width: 2,
|
width: 2,
|
||||||
value: 0.0
|
value: 0.0
|
||||||
}, {
|
}, {
|
||||||
color: 'red',
|
color: 'red',
|
||||||
width: 2,
|
width: 2,
|
||||||
value: 0.0
|
value: 0.0
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
useHighStocks: true
|
useHighStocks: true
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.loadSolds = function() {
|
$scope.loadSolds = function() {
|
||||||
$scope.config.loading = true;
|
$scope.config.loading = true;
|
||||||
|
|
||||||
OHLC.query({}, function(data) {
|
OHLC.query({}, function(data) {
|
||||||
$scope.config.series[0].data = [];
|
$scope.config.series[0].data = [];
|
||||||
|
|
||||||
angular.forEach(data, function(operation) {
|
angular.forEach(data, function(operation) {
|
||||||
$scope.config.series[0].data.push([
|
$scope.config.series[0].data.push([
|
||||||
moment.utc(operation.operation_date).valueOf(),
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
operation.open, operation.high, operation.low, operation.close
|
moment.utc(operation.operation_date).valueOf(),
|
||||||
]);
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
operation.open, operation.high, operation.low, operation.close
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
$scope.$emit('rangeSelectedEvent', {
|
$scope.$emit('rangeSelectedEvent', {
|
||||||
begin: $scope.config.xAxis.currentMin,
|
begin: $scope.config.xAxis.currentMin,
|
||||||
end: $scope.config.xAxis.currentMax
|
end: $scope.config.xAxis.currentMax
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.config.loading = false;
|
$scope.config.loading = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reload solds when an operation is saved.
|
// Reload solds when an operation is saved.
|
||||||
$rootScope.$on('operationSavedEvent', function() {
|
$rootScope.$on('operationSavedEvent', function() {
|
||||||
$scope.loadSolds();
|
$scope.loadSolds();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reload solds when an operation is deleted.
|
// Reload solds when an operation is deleted.
|
||||||
$rootScope.$on('operationDeletedEvent', function() {
|
$rootScope.$on('operationDeletedEvent', function() {
|
||||||
$scope.loadSolds();
|
$scope.loadSolds();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update authorized overdraft on account loading.
|
// Update authorized overdraft on account loading.
|
||||||
$rootScope.$on('accountLoadedEvent', function(e, account) {
|
$rootScope.$on('accountLoadedEvent', function(e, account) {
|
||||||
$scope.config.yAxis.plotLines[1].value = account.authorized_overdraft;
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
$scope.config.yAxis.plotLines[1].value = account.authorized_overdraft;
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
});
|
||||||
|
|
||||||
// Select beginning and end of month.
|
// Select beginning and end of month.
|
||||||
$scope.loadSolds();
|
$scope.loadSolds();
|
||||||
}])
|
}
|
||||||
|
])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Controller for the operations.
|
* Controller for the operations.
|
||||||
*/
|
*/
|
||||||
.controller(
|
.controller('OperationController', [
|
||||||
'OperationController', [
|
'$scope', '$rootScope', '$routeParams', '$ngBootbox', 'Notification', 'Account', 'Operation',
|
||||||
'$scope', '$rootScope', '$routeParams', '$ngBootbox', 'Notification', 'Account', 'Operation',
|
function($scope, $rootScope, $routeParams, $ngBootbox, Notification, Account, Operation) {
|
||||||
function($scope, $rootScope, $routeParams, $ngBootbox, Notification, Account, Operation) {
|
// List of operations.
|
||||||
// List of operations.
|
$scope.operations = [];
|
||||||
$scope.operations = [];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add an empty operation.
|
* Add an empty operation.
|
||||||
*/
|
*/
|
||||||
$scope.add = function() {
|
$scope.add = function() {
|
||||||
var operation = new Operation({
|
var operation = new Operation({
|
||||||
account_id: $routeParams.accountId
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
account_id: $routeParams.accountId
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
});
|
||||||
|
|
||||||
$scope.operations.splice(0, 0, operation);
|
$scope.operations.splice(0, 0, operation);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load operations.
|
* Load operations.
|
||||||
*/
|
*/
|
||||||
$scope.load = function(begin, end) {
|
$scope.load = function(begin, end) {
|
||||||
$scope.operations = Operation.query({
|
$scope.operations = Operation.query({
|
||||||
account_id: $routeParams.accountId,
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
begin: begin.format('YYYY-MM-DD'),
|
account_id: $routeParams.accountId,
|
||||||
end: end.format('YYYY-MM-DD')
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
begin: begin.format('YYYY-MM-DD'),
|
||||||
};
|
end: end.format('YYYY-MM-DD')
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cancel edition.
|
* Cancel edition.
|
||||||
*/
|
*/
|
||||||
$scope.cancelEdit = function(operation, rowform, $index) {
|
$scope.cancelEdit = function(operation, rowform, $index) {
|
||||||
if(!operation.id) {
|
if (!operation.id) {
|
||||||
$scope.operations.splice($index, 1);
|
$scope.operations.splice($index, 1);
|
||||||
} else {
|
} else {
|
||||||
rowform.$cancel();
|
rowform.$cancel();
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Toggle pointed indicator for an operation.
|
|
||||||
*/
|
|
||||||
$scope.togglePointed = function(operation, rowform) {
|
|
||||||
operation.pointed = !operation.pointed;
|
|
||||||
|
|
||||||
// Save operation if not editing it.
|
|
||||||
if(!rowform.$visible) {
|
|
||||||
$scope.save(operation);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Toggle cancel indicator for an operation.
|
|
||||||
*/
|
|
||||||
$scope.toggleCanceled = function(operation) {
|
|
||||||
operation.canceled = !operation.canceled;
|
|
||||||
|
|
||||||
$scope.save(operation);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Save an operation and emit operationSavedEvent.
|
|
||||||
*/
|
|
||||||
$scope.save = function($data, $index) {
|
|
||||||
// Check if $data is already a resource.
|
|
||||||
var operation;
|
|
||||||
|
|
||||||
if($data.$save) {
|
|
||||||
operation = $data;
|
|
||||||
} else {
|
|
||||||
operation = $scope.operations[$index];
|
|
||||||
operation = angular.merge(operation, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
operation.confirmed = true;
|
|
||||||
|
|
||||||
return operation.$save().then(function(data) {
|
|
||||||
Notification.success('Operation #' + data.id + ' saved.');
|
|
||||||
|
|
||||||
$scope.$emit('operationSavedEvent', data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete an operation and emit operationDeletedEvent.
|
|
||||||
*/
|
|
||||||
$scope.delete = function(operation, $index) {
|
|
||||||
var id = operation.id;
|
|
||||||
|
|
||||||
$ngBootbox.confirm(
|
|
||||||
'Voulez-vous supprimer l\'opération \\\'' + operation.label + '\\\' ?',
|
|
||||||
function(result) {
|
|
||||||
if(result) {
|
|
||||||
operation.$delete().then(function() {
|
|
||||||
Notification.success('Operation #' + id + ' deleted.');
|
|
||||||
|
|
||||||
// Remove operation from array.
|
|
||||||
$scope.operation.splice($index, 1);
|
|
||||||
|
|
||||||
$scope.$emit('operationDeletedEvent', operation);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.account = Account.get({
|
|
||||||
id: $routeParams.accountId
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reload operations on rangeSelectedEvent.
|
|
||||||
*/
|
|
||||||
$rootScope.$on('rangeSelectedEvent', function(e, args) {
|
|
||||||
$scope.load(args.begin, args.end);
|
|
||||||
});
|
|
||||||
}])
|
|
||||||
|
|
||||||
.directive(
|
|
||||||
'operationFormDialog', function($ngBootbox) {
|
|
||||||
return {
|
|
||||||
restrict: 'A',
|
|
||||||
scope: {
|
|
||||||
operation: '=ngModel'
|
|
||||||
},
|
|
||||||
link: function(scope, element) {
|
|
||||||
var title = 'Operation';
|
|
||||||
|
|
||||||
if(scope.operation && scope.operation.id) {
|
|
||||||
title = title + ' #' + scope.operation.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.form = {};
|
|
||||||
|
|
||||||
element.on('click', function() {
|
|
||||||
scope.data = {};
|
|
||||||
angular.copy(scope.operation, scope.data);
|
|
||||||
|
|
||||||
// Open dialog with form.
|
|
||||||
$ngBootbox.customDialog({
|
|
||||||
scope: scope,
|
|
||||||
title: title,
|
|
||||||
templateUrl: 'views/operation.form.tmpl.html',
|
|
||||||
onEscape: true,
|
|
||||||
buttons: {
|
|
||||||
save: {
|
|
||||||
label: 'Save',
|
|
||||||
className: 'btn-success',
|
|
||||||
callback: function() {
|
|
||||||
// Validate form
|
|
||||||
console.log(scope.form);
|
|
||||||
|
|
||||||
// Save operation
|
|
||||||
console.log(scope.operation);
|
|
||||||
|
|
||||||
// TODO Alexis Lahouze 2016-05-24 Save operation, handle return.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
label: 'Cancel',
|
|
||||||
className: 'btn-default',
|
|
||||||
callback: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle pointed indicator for an operation.
|
||||||
|
*/
|
||||||
|
$scope.togglePointed = function(operation, rowform) {
|
||||||
|
operation.pointed = !operation.pointed;
|
||||||
|
|
||||||
|
// Save operation if not editing it.
|
||||||
|
if (!rowform.$visible) {
|
||||||
|
$scope.save(operation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle cancel indicator for an operation.
|
||||||
|
*/
|
||||||
|
$scope.toggleCanceled = function(operation) {
|
||||||
|
operation.canceled = !operation.canceled;
|
||||||
|
|
||||||
|
$scope.save(operation);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save an operation and emit operationSavedEvent.
|
||||||
|
*/
|
||||||
|
$scope.save = function($data, $index) {
|
||||||
|
// Check if $data is already a resource.
|
||||||
|
var operation;
|
||||||
|
|
||||||
|
if ($data.$save) {
|
||||||
|
operation = $data;
|
||||||
|
} else {
|
||||||
|
operation = $scope.operations[$index];
|
||||||
|
operation = angular.merge(operation, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
operation.confirmed = true;
|
||||||
|
|
||||||
|
return operation.$save().then(function(data) {
|
||||||
|
Notification.success('Operation #' + data.id + ' saved.');
|
||||||
|
|
||||||
|
$scope.$emit('operationSavedEvent', data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete an operation and emit operationDeletedEvent.
|
||||||
|
*/
|
||||||
|
$scope.delete = function(operation, $index) {
|
||||||
|
var id = operation.id;
|
||||||
|
|
||||||
|
$ngBootbox.confirm(
|
||||||
|
'Voulez-vous supprimer l\'opération \\\'' + operation.label + '\\\' ?',
|
||||||
|
function(result) {
|
||||||
|
if (result) {
|
||||||
|
operation.$delete().then(function() {
|
||||||
|
Notification.success('Operation #' + id + ' deleted.');
|
||||||
|
|
||||||
|
// Remove operation from array.
|
||||||
|
$scope.operation.splice($index, 1);
|
||||||
|
|
||||||
|
$scope.$emit('operationDeletedEvent', operation);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.account = Account.get({
|
||||||
|
id: $routeParams.accountId
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reload operations on rangeSelectedEvent.
|
||||||
|
*/
|
||||||
|
$rootScope.$on('rangeSelectedEvent', function(e, args) {
|
||||||
|
$scope.load(args.begin, args.end);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.directive('operationFormDialog', function($ngBootbox) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
scope: {
|
||||||
|
operation: '=ngModel'
|
||||||
|
},
|
||||||
|
link: function(scope, element) {
|
||||||
|
var title = 'Operation';
|
||||||
|
|
||||||
|
if (scope.operation && scope.operation.id) {
|
||||||
|
title = title + ' #' + scope.operation.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.form = {};
|
||||||
|
|
||||||
|
element.on('click', function() {
|
||||||
|
scope.data = {};
|
||||||
|
angular.copy(scope.operation, scope.data);
|
||||||
|
|
||||||
|
// Open dialog with form.
|
||||||
|
$ngBootbox.customDialog({
|
||||||
|
scope: scope,
|
||||||
|
title: title,
|
||||||
|
templateUrl: 'views/operation.form.tmpl.html',
|
||||||
|
onEscape: true,
|
||||||
|
buttons: {
|
||||||
|
save: {
|
||||||
|
label: 'Save',
|
||||||
|
className: 'btn-success',
|
||||||
|
callback: function() {
|
||||||
|
// Validate form
|
||||||
|
console.log(scope.form);
|
||||||
|
|
||||||
|
// Save operation
|
||||||
|
console.log(scope.operation);
|
||||||
|
|
||||||
|
// TODO Alexis Lahouze 2016-05-24 Save operation, handle return.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
label: 'Cancel',
|
||||||
|
className: 'btn-default',
|
||||||
|
callback: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// vim: set tw=80 ts=4 sw=4 sts=4:
|
||||||
/*
|
/*
|
||||||
This file is part of Accountant.
|
This file is part of Accountant.
|
||||||
|
|
||||||
@ -14,7 +15,6 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
// vim: set tw=80 ts=2 sw=2 sts=2:
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('accountant.scheduler', [
|
angular.module('accountant.scheduler', [
|
||||||
@ -38,84 +38,88 @@ angular.module('accountant.scheduler', [
|
|||||||
);
|
);
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.controller(
|
.controller('SchedulerController', [
|
||||||
'SchedulerController', [
|
'$scope', '$rootScope', '$routeParams', '$ngBootbox', 'Notification', 'ScheduledOperation',
|
||||||
'$scope', '$rootScope', '$routeParams', '$ngBootbox', 'Notification', 'ScheduledOperation',
|
function($scope, $rootScope, $routeParams, $ngBootbox, Notification, ScheduledOperation) {
|
||||||
function($scope, $rootScope, $routeParams, $ngBootbox, Notification, ScheduledOperation) {
|
// Operation store.
|
||||||
// Operation store.
|
$scope.operations = [];
|
||||||
$scope.operations = [];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new operation at the beginning of th array.
|
* Add a new operation at the beginning of th array.
|
||||||
*/
|
*/
|
||||||
$scope.add = function() {
|
$scope.add = function() {
|
||||||
var operation = new ScheduledOperation({
|
var operation = new ScheduledOperation({
|
||||||
account_id: $routeParams.accountId
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
});
|
account_id: $routeParams.accountId
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
// Insert new operation at the beginning of the array.
|
|
||||||
$scope.operations.splice(0, 0, operation);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load operations.
|
|
||||||
*/
|
|
||||||
$scope.load = function() {
|
|
||||||
$scope.operations = ScheduledOperation.query({
|
|
||||||
account_id: $routeParams.accountId
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Save operation.
|
|
||||||
*/
|
|
||||||
$scope.save = function($data, $index) {
|
|
||||||
var operation;
|
|
||||||
|
|
||||||
if($data.$save) {
|
|
||||||
operation = $data;
|
|
||||||
} else {
|
|
||||||
operation = $scope.operations[$index];
|
|
||||||
operation = angular.merge(operation, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return operation.$save().then(function(data) {
|
|
||||||
Notification.success('Operation #' + data.id + ' saved.');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cancel operation edition. Delete if new.
|
|
||||||
*/
|
|
||||||
$scope.cancelEdit = function(operation, rowform, $index) {
|
|
||||||
if(!operation.id) {
|
|
||||||
$scope.operations.splice($index, 1);
|
|
||||||
} else {
|
|
||||||
rowform.$cancel();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete operation.
|
|
||||||
*/
|
|
||||||
$scope.delete = function(operation, $index) {
|
|
||||||
var id = operation.id;
|
|
||||||
|
|
||||||
$ngBootbox.confirm(
|
|
||||||
'Voulez-vous supprimer l\'operation planifiée \\\'' + operation.label + '\\\' ?',
|
|
||||||
function(result) {
|
|
||||||
if(result) {
|
|
||||||
operation.$delete().then(function() {
|
|
||||||
Notification.success('Operation #' + id + ' deleted.');
|
|
||||||
|
|
||||||
// Remove account from array.
|
|
||||||
$scope.operations.splice($index, 1);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load operations on controller initialization.
|
// Insert new operation at the beginning of the array.
|
||||||
$scope.load();
|
$scope.operations.splice(0, 0, operation);
|
||||||
}]);
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load operations.
|
||||||
|
*/
|
||||||
|
$scope.load = function() {
|
||||||
|
$scope.operations = ScheduledOperation.query({
|
||||||
|
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
account_id: $routeParams.accountId
|
||||||
|
// jscs:enable requireCamelCaseOrUpperCaseIdentifiers
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save operation.
|
||||||
|
*/
|
||||||
|
$scope.save = function($data, $index) {
|
||||||
|
var operation;
|
||||||
|
|
||||||
|
if ($data.$save) {
|
||||||
|
operation = $data;
|
||||||
|
} else {
|
||||||
|
operation = $scope.operations[$index];
|
||||||
|
operation = angular.merge(operation, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return operation.$save().then(function(data) {
|
||||||
|
Notification.success('Operation #' + data.id + ' saved.');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel operation edition. Delete if new.
|
||||||
|
*/
|
||||||
|
$scope.cancelEdit = function(operation, rowform, $index) {
|
||||||
|
if (!operation.id) {
|
||||||
|
$scope.operations.splice($index, 1);
|
||||||
|
} else {
|
||||||
|
rowform.$cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete operation.
|
||||||
|
*/
|
||||||
|
$scope.delete = function(operation, $index) {
|
||||||
|
var id = operation.id;
|
||||||
|
|
||||||
|
$ngBootbox.confirm(
|
||||||
|
'Voulez-vous supprimer l\'operation planifiée \\\'' + operation.label + '\\\' ?',
|
||||||
|
function(result) {
|
||||||
|
if (result) {
|
||||||
|
operation.$delete().then(function() {
|
||||||
|
Notification.success('Operation #' + id + ' deleted.');
|
||||||
|
|
||||||
|
// Remove account from array.
|
||||||
|
$scope.operations.splice($index, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load operations on controller initialization.
|
||||||
|
$scope.load();
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
options: {
|
options: {
|
||||||
config: '.jscsrc',
|
config: '.jscsrc'
|
||||||
verbose: true
|
|
||||||
},
|
},
|
||||||
frontend_js: [
|
frontend_js: [
|
||||||
'<%= accountant.frontend.src %>/js/*.js'
|
'<%= accountant.frontend.src %>/js/*.js'
|
||||||
|
Loading…
Reference in New Issue
Block a user