Move up all sources in src directory.
This commit is contained in:
50
src/accounts/account.form.tmpl.html
Normal file
50
src/accounts/account.form.tmpl.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!-- vim: set tw=80 ts=2 sw=2 sts=2: -->
|
||||
<!--
|
||||
This file is part of Accountant.
|
||||
|
||||
Accountant is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Accountant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<form class="form-horizontal" ng-submit="submitForm()" name="form" novalidate>
|
||||
<div class="form-group" ng-class="{ 'has-error' : form.name.$invalid && !form.name.$pristine }">
|
||||
<label class="col-sm-4 control-label" for="name">Account name</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" id="name" name="name"
|
||||
ng-model="data.name"
|
||||
type="text" placeholder="Account name"
|
||||
required />
|
||||
<div class="help-block" ng-messages="form.name.$error" ng-if="form.name.$invalid">
|
||||
<p ng-message="required">The account name is required.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error' : form.authorized_overdraft.$invalid && !form.authorized_overdraft.$pristine }">
|
||||
<label class="col-sm-4 control-label" for="authorized-overdraft">Authorized overdraft</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">-</div>
|
||||
<input class="form-control" id="authorized-overdraft"
|
||||
name="authorized_overdraft"
|
||||
ng-model="data.authorized_overdraft"
|
||||
type="number" placeholder="Authorized overdraft"
|
||||
required min="0"/>
|
||||
<div class="input-group-addon">.00€</div>
|
||||
</div>
|
||||
<div class="help-block" ng-messages="form.authorized_overdraft.$error" ng-if="form.authorized_overdraft.$invalid">
|
||||
<p ng-message="required">The authorized overdraft is required.</p>
|
||||
<p ng-message="min">The authorized overdraft must be equal or greater than 0.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
94
src/accounts/accounts.html
Normal file
94
src/accounts/accounts.html
Normal file
@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- vim: set tw=80 ts=2 sw=2 sts=2: -->
|
||||
<!--
|
||||
This file is part of Accountant.
|
||||
|
||||
Accountant is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Accountant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<div class="row">
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nom du compte</th>
|
||||
<th class="col-md-1">Solde courant</th>
|
||||
<th class="col-md-1">Solde pointé</th>
|
||||
<th class="col-md-1">Découvert autorisé</th>
|
||||
<th class="col-md-1">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<button class="btn btn-success" account-form-dialog>
|
||||
Ajouter
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr id="{{ account.id }}"
|
||||
class="form-inline" ng-class="rowClass(account)"
|
||||
ng-repeat="account in accountsCtrl.accounts | orderBy:'name'" ng-init="account.getSolds()">
|
||||
<td>
|
||||
<a href="#!/account/{{ account.id }}/operations">{{ account.name }}</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span ng-class="accountsCtrl.valueClass(account, account.solds.current)">
|
||||
{{ account.solds.current | currency : "€" }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span ng-class="accountsCtrl.valueClass(account, account.solds.pointed)">
|
||||
{{ account.solds.pointed | currency : "€" }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ account.authorized_overdraft | currency : "€" }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="btn-group btn-group-xs">
|
||||
<!-- Edit account. -->
|
||||
<button type="button" class="btn btn-success"
|
||||
account-form-dialog ng-model="accountsCtrl.account">
|
||||
<span class="fa fa-pencil-square-o"></span>
|
||||
</button>
|
||||
|
||||
<!-- Cancel account edition. -->
|
||||
<button type="button" class="btn btn-default"
|
||||
ng-click="accountsCtrl.cancelEdit(rowform, account, $index)">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
|
||||
<!-- Delete account, with confirm. -->
|
||||
<button type="button" class="btn btn-default"
|
||||
ng-click="accountsCtrl.delete(account, $index)">
|
||||
<span class="fa fa-trash-o"></span>
|
||||
</button>
|
||||
|
||||
<!-- Open account scheduler. -->
|
||||
<a class="btn btn-default"
|
||||
ng-if="account.id"
|
||||
href="#!/account/{{ account.id }}/scheduler">
|
||||
<span class="fa fa-clock-o"></span>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
262
src/accounts/index.js
Normal file
262
src/accounts/index.js
Normal file
@ -0,0 +1,262 @@
|
||||
// vim: set tw=80 ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of Accountant.
|
||||
|
||||
Accountant is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Accountant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* jshint node: true */
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular');
|
||||
|
||||
var ngResource = require('angular-resource'),
|
||||
ngMessages = require('angular-messages'),
|
||||
ngUiNotification = require('angular-ui-notification'),
|
||||
ngBootbox = require('ngbootbox');
|
||||
|
||||
// Note: ngBootbox seems to have no module.exports.
|
||||
ngBootbox = 'ngBootbox';
|
||||
|
||||
var accountFormTmpl = require('./account.form.tmpl.html');
|
||||
|
||||
var accountModule = angular.module('accountant.accounts', [
|
||||
ngResource,
|
||||
ngMessages,
|
||||
ngUiNotification,
|
||||
ngBootbox
|
||||
])
|
||||
|
||||
.config(function($resourceProvider) {
|
||||
// Keep trailing slashes to avoid redirect by flask..
|
||||
$resourceProvider.defaults.stripTrailingSlashes = false;
|
||||
})
|
||||
|
||||
.factory('Account', function($resource) {
|
||||
var Account = $resource(
|
||||
'/api/account/:id', {
|
||||
id: '@id'
|
||||
}
|
||||
);
|
||||
|
||||
Account.prototype.getSolds = function() {
|
||||
var Solds = $resource('/api/account/:id/balances', {id: this.id});
|
||||
|
||||
this.solds = Solds.get();
|
||||
};
|
||||
|
||||
Account.prototype.getBalance = function(begin, end) {
|
||||
var Balance = $resource(
|
||||
'/api/account/:id/balance', {
|
||||
id: this.id,
|
||||
begin: begin.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD')
|
||||
});
|
||||
|
||||
this.balance = Balance.get();
|
||||
};
|
||||
|
||||
return Account;
|
||||
})
|
||||
|
||||
.controller('AccountController', function($ngBootbox, Account, Notification) {
|
||||
var vm = this;
|
||||
|
||||
/*
|
||||
* Return the class for an account current value compared to authorized
|
||||
* overdraft.
|
||||
*/
|
||||
vm.rowClass = function(account) {
|
||||
// eslint-disable-next-line camelcase
|
||||
if (!account || !account.authorized_overdraft || !account.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
if (account.current < account.authorized_overdraft) {
|
||||
return 'danger';
|
||||
} else if (account.current < 0) {
|
||||
return 'warning';
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the class for a value compared to account authorized overdraft.
|
||||
*/
|
||||
vm.valueClass = function(account, value) {
|
||||
if (!account || !value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
if (value < account.authorized_overdraft) {
|
||||
return 'text-danger';
|
||||
} else if (value < 0) {
|
||||
return 'text-warning';
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Add an empty account.
|
||||
*/
|
||||
vm.add = function() {
|
||||
var account = new Account({
|
||||
// eslint-disable-next-line camelcase
|
||||
authorized_overdraft: 0
|
||||
});
|
||||
|
||||
// Insert account at the begining of the array.
|
||||
vm.accounts.splice(0, 0, account);
|
||||
};
|
||||
|
||||
/*
|
||||
* Cancel account edition. Remove it from array if a new one.
|
||||
*/
|
||||
vm.cancelEdit = function(rowform, account, $index) {
|
||||
if (account.id) {
|
||||
rowform.$cancel();
|
||||
} else {
|
||||
// Account not saved, just remove it from array.
|
||||
vm.accounts.splice($index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Save account.
|
||||
*/
|
||||
vm.save = function(account) {
|
||||
// var account = vm.accounts[$index];
|
||||
|
||||
// account = angular.merge(account, $data);
|
||||
|
||||
return account.$save().then(function(data) {
|
||||
Notification.success('Account #' + data.id + ' saved.');
|
||||
|
||||
// TODO Alexis Lahouze 2016-03-08 Update solds
|
||||
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Delete an account.
|
||||
*/
|
||||
vm.delete = function(account, $index) {
|
||||
var id = account.id;
|
||||
|
||||
$ngBootbox.confirm(
|
||||
'Voulez-vous supprimer le compte \'' + account.name + '\' ?',
|
||||
function(result) {
|
||||
if (result) {
|
||||
account.$delete().then(function() {
|
||||
Notification.success('Account #' + id + ' deleted.');
|
||||
|
||||
// Remove account from array.
|
||||
vm.accounts.splice($index, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// Load accounts.
|
||||
vm.accounts = Account.query();
|
||||
})
|
||||
|
||||
.directive('accountFormDialog', function(Account, $ngBootbox, Notification, $log) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
account: '=ngModel'
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var title = 'Account';
|
||||
|
||||
if (scope.account && scope.account.id) {
|
||||
title = title + ' #' + scope.account.id;
|
||||
}
|
||||
|
||||
scope.form = {};
|
||||
|
||||
scope.submitForm = function() {
|
||||
// check to make sure the form is completely valid
|
||||
if (!scope.form.$valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Authorized overdraft is a positive integer but data is a negative integer.
|
||||
// eslint-disable-next-line camelcase
|
||||
scope.data.authorized_overdraft = -scope.data.authorized_overdraft;
|
||||
|
||||
angular.copy(scope.data, scope.account);
|
||||
|
||||
// Save account
|
||||
$log.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();
|
||||
$log.log(data);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
element.on('click', function() {
|
||||
// Create new account if not passed in ng-model.
|
||||
if (!scope.account) {
|
||||
scope.account = new Account({
|
||||
// eslint-disable-next-line camelcase
|
||||
authorized_overdraft: 0
|
||||
});
|
||||
}
|
||||
|
||||
scope.data = {};
|
||||
angular.copy(scope.account, scope.data);
|
||||
|
||||
// Authorized overdraft must be positive in form.
|
||||
// eslint-disable-next-line camelcase
|
||||
scope.data.authorized_overdraft = -scope.data.authorized_overdraft;
|
||||
|
||||
// Open dialog with form.
|
||||
$ngBootbox.customDialog({
|
||||
scope: scope,
|
||||
title: title,
|
||||
templateUrl: accountFormTmpl,
|
||||
onEscape: true,
|
||||
buttons: {
|
||||
save: {
|
||||
label: 'Save',
|
||||
className: 'btn-success',
|
||||
callback: scope.submitForm
|
||||
},
|
||||
cancel: {
|
||||
label: 'Cancel',
|
||||
className: 'btn-default',
|
||||
callback: true
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = accountModule;
|
Reference in New Issue
Block a user