mirror of
https://github.com/gwenhael-le-moine/ledgerrb.git
synced 2024-12-26 09:59:18 +01:00
promises
This commit is contained in:
parent
50eb9da406
commit
ad136ee08c
3 changed files with 300 additions and 287 deletions
|
@ -18,8 +18,8 @@ app.config(['$stateProvider', '$urlRouterProvider',
|
|||
}
|
||||
]);
|
||||
app.component('dashboard', {
|
||||
controller: ['$filter', 'API',
|
||||
function ($filter, API) {
|
||||
controller: ['$filter', '$q', 'API',
|
||||
function ($filter, $q, API) {
|
||||
var ctrl = this;
|
||||
ctrl.xFunction = function () {
|
||||
return function (d) {
|
||||
|
@ -160,13 +160,14 @@ app.component('dashboard', {
|
|||
};
|
||||
ctrl.depth = 99;
|
||||
var retrieve_period_detailed_data = function () {
|
||||
console.log(ctrl.period);
|
||||
ctrl.balance = {
|
||||
buckets: [new Bucket('Expenses Liabilities Equity Income', ctrl.period),
|
||||
new Bucket('Assets', null)],
|
||||
details: {}
|
||||
};
|
||||
_(ctrl.balance.buckets).each(function (bucket) {
|
||||
API.balance({
|
||||
return $q.all(_(ctrl.balance.buckets).map(function (bucket) {
|
||||
return API.balance({
|
||||
period: bucket.period,
|
||||
categories: bucket.categories,
|
||||
depth: ctrl.depth
|
||||
|
@ -192,18 +193,19 @@ app.component('dashboard', {
|
|||
bucket.accounts_selected = bucket.raw_data;
|
||||
ctrl.filter_data();
|
||||
});
|
||||
});
|
||||
}));
|
||||
};
|
||||
var retrieve_accounts = function () {
|
||||
API.accounts()
|
||||
return $q.when(API.accounts()
|
||||
.then(function (response) {
|
||||
ctrl.accounts = response.data.map(function (account_ary) {
|
||||
return account_ary.join(':');
|
||||
});
|
||||
});
|
||||
}));
|
||||
};
|
||||
var retrieve_graph_values = function (params) {
|
||||
API.graph_values(params).then(function (response) {
|
||||
return $q.when(API.graph_values(params)
|
||||
.then(function (response) {
|
||||
ctrl.periods = [];
|
||||
var largest_cat = _(response.data).reduce(function (memo, cat) {
|
||||
return cat.length > memo.length ? cat : memo;
|
||||
|
@ -278,13 +280,17 @@ app.component('dashboard', {
|
|||
};
|
||||
ctrl.periods = _.chain(ctrl.periods).uniq().sort().reverse().value();
|
||||
ctrl.period = _(ctrl.periods).first();
|
||||
});
|
||||
}));
|
||||
};
|
||||
ctrl.graphed_accounts = ['Expenses', 'Income'];
|
||||
retrieve_accounts();
|
||||
retrieve_period_detailed_data();
|
||||
retrieve_graph_values({ period: '',
|
||||
categories: ctrl.graphed_accounts.join(' ') });
|
||||
retrieve_accounts().then(function (response) {
|
||||
retrieve_graph_values({
|
||||
period: '',
|
||||
categories: ctrl.graphed_accounts.join(' ')
|
||||
}).then(function (response) {
|
||||
retrieve_period_detailed_data();
|
||||
});
|
||||
});
|
||||
}
|
||||
],
|
||||
template: "\n<md-content flex=\"100\" layout=\"column\">\n <md-card flex=\"100\" layout=\"row\">\n <md-card flex=\"20\">\n <select style=\"height: 100%;\" multiple ng:model=\"$ctrl.graphed_accounts\">\n <option ng:repeat=\"account in $ctrl.accounts\">{{account}}</option>\n </select>\n </md-card>\n <md-card flex=\"81\">\n <nvd3 data=\"$ctrl.graphiques.monthly_values.data\"\n options=\"$ctrl.graphiques.monthly_values.options\"></nvd3>\n </md-card>\n </md-card>\n <h1 style=\"text-align: center;\">{{$ctrl.period | amDateFormat:'MMMM YYYY'}}</h1>\n <md-card flex=\"100\" layout=\"column\"\n ng:repeat=\"bucket in $ctrl.balance.buckets\">\n <md-toolbar>\n <span ng:repeat=\"account in bucket.total_detailed\">{{account.account}} = {{account.amount | number:2}} \u20AC</span>\n </md-toolbar>\n <md-content layout=\"row\">\n <md-card flex=\"20\">\n <select style=\"height: 100%;\" multiple\n ng:model=\"bucket.accounts_selected\"\n ng:options=\"account.account for account in bucket.raw_data | orderBy:'account'\"\n ng:change=\"filter_data()\">\n <option value=''>...</option>\n </select>\n </md-card>\n <md-card flex=\"78\">\n <nvd3 data=\"bucket.data\"\n options=\"bucket.pie_graph_options\" >\n </nvd3>\n </md-card>\n <!-- <md-card flex=\"56\">\n <table class=\"table\">\n <thead>\n <tr>\n <th><md-buton ng:click=\"bucket.order_by( 'account' )\">account</md-buton></th>\n <th><md-buton ng:click=\"bucket.order_by( 'amount' )\">amount</md-buton></th>\n <th><md-buton ng:click=\"bucket.order_by( 'score' )\">score</md-buton></th>\n </tr>\n </thead>\n <tbody>\n <tr ng:repeat=\"account in bucket.data | orderBy:bucket.orderBy:bucket.orderDesc\"\n ng:class=\"{'even': $even, 'odd': $odd}\"\n style=\"border-left:10px solid {{coloring_score( account.score )}};border-right:10px solid {{coloring_score( account.score )}}\">\n <td style=\"border-bottom:1px solid {{coloring_score( account.score )}}\">\n {{account.account}}\n </td>\n <td style=\"text-align:right;border-bottom:1px solid {{coloring_score( account.score )}}\">\n {{account.amount | number:2}} \u20AC\n </td>\n <td style=\"text-align:right;border-bottom:1px solid {{coloring_score( account.score )}}\">\n {{account.score}}\n </td>\n </tr>\n </tbody>\n </table>\n </md-card> -->\n </md-content>\n </md-card>\n</md-content>\n"
|
||||
|
|
24
public/app/js/app.min.js
vendored
24
public/app/js/app.min.js
vendored
|
@ -1,17 +1,17 @@
|
|||
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,c,b){a!=Array.prototype&&a!=Object.prototype&&(a[c]=b.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
|
||||
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,c,d){a!=Array.prototype&&a!=Object.prototype&&(a[c]=d.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
|
||||
$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.Symbol=function(){var a=0;return function(c){return $jscomp.SYMBOL_PREFIX+(c||"")+a++}}();
|
||||
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(a){var c=0;return $jscomp.iteratorPrototype(function(){return c<a.length?{done:!1,value:a[c++]}:{done:!0}})};
|
||||
$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};$jscomp.iteratorFromArray=function(a,c){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var b=0,e={next:function(){if(b<a.length){var d=b++;return{value:c(d,a[d]),done:!1}}e.next=function(){return{done:!0,value:void 0}};return e.next()}};e[Symbol.iterator]=function(){return e};return e};
|
||||
$jscomp.polyfill=function(a,c,b,e){if(c){b=$jscomp.global;a=a.split(".");for(e=0;e<a.length-1;e++){var d=a[e];d in b||(b[d]={});b=b[d]}a=a[a.length-1];e=b[a];c=c(e);c!=e&&null!=c&&$jscomp.defineProperty(b,a,{configurable:!0,writable:!0,value:c})}};$jscomp.polyfill("Array.prototype.keys",function(a){return a?a:function(){return $jscomp.iteratorFromArray(this,function(a){return a})}},"es6","es3");
|
||||
$jscomp.findInternal=function(a,c,b){a instanceof String&&(a=String(a));for(var e=a.length,d=0;d<e;d++){var g=a[d];if(c.call(b,g,d,a))return{i:d,v:g}}return{i:-1,v:void 0}};$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(a,b){return $jscomp.findInternal(this,a,b).v}},"es6","es3");var app=angular.module("app",["ui.router","nvd3","angularMoment","chieffancypants.loadingBar","ngMaterial"]);app.config(["$stateProvider","$urlRouterProvider",function(a,c){a.state("app",{url:"",views:{main:{component:"dashboard"}}})}]);
|
||||
app.component("dashboard",{controller:["$filter","API",function(a,c){var b=this;b.xFunction=function(){return function(a){return a.account}};b.yFunction=function(){return function(a){return a.amount}};b.toolTipContentFunction=function(){return function(f,c,h,k,e){return"\x3cmd-content\x3e\x3ch3\x3e"+f+"\x3c/h3\x3e\x3ctable\x3e"+_(b.balance.details[f]).map(function(f){return"\x3ctr\x3e\x3ctd\x3e"+f.date+"\x3c/td\x3e\x3ctd\x3e"+f.payee+'\x3c/td\x3e\x3ctd style\x3d"text-align: right"\x3e'+a("number")(f.amount,
|
||||
$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};$jscomp.iteratorFromArray=function(a,c){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var d=0,b={next:function(){if(d<a.length){var e=d++;return{value:c(e,a[e]),done:!1}}b.next=function(){return{done:!0,value:void 0}};return b.next()}};b[Symbol.iterator]=function(){return b};return b};
|
||||
$jscomp.polyfill=function(a,c,d,b){if(c){d=$jscomp.global;a=a.split(".");for(b=0;b<a.length-1;b++){var e=a[b];e in d||(d[e]={});d=d[e]}a=a[a.length-1];b=d[a];c=c(b);c!=b&&null!=c&&$jscomp.defineProperty(d,a,{configurable:!0,writable:!0,value:c})}};$jscomp.polyfill("Array.prototype.keys",function(a){return a?a:function(){return $jscomp.iteratorFromArray(this,function(a){return a})}},"es6","es3");
|
||||
$jscomp.findInternal=function(a,c,d){a instanceof String&&(a=String(a));for(var b=a.length,e=0;e<b;e++){var g=a[e];if(c.call(d,g,e,a))return{i:e,v:g}}return{i:-1,v:void 0}};$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(a,d){return $jscomp.findInternal(this,a,d).v}},"es6","es3");var app=angular.module("app",["ui.router","nvd3","angularMoment","chieffancypants.loadingBar","ngMaterial"]);app.config(["$stateProvider","$urlRouterProvider",function(a,c){a.state("app",{url:"",views:{main:{component:"dashboard"}}})}]);
|
||||
app.component("dashboard",{controller:["$filter","$q","API",function(a,c,d){var b=this;b.xFunction=function(){return function(a){return a.account}};b.yFunction=function(){return function(a){return a.amount}};b.toolTipContentFunction=function(){return function(f,c,l,m,d){return"\x3cmd-content\x3e\x3ch3\x3e"+f+"\x3c/h3\x3e\x3ctable\x3e"+_(b.balance.details[f]).map(function(f){return"\x3ctr\x3e\x3ctd\x3e"+f.date+"\x3c/td\x3e\x3ctd\x3e"+f.payee+'\x3c/td\x3e\x3ctd style\x3d"text-align: right"\x3e'+a("number")(f.amount,
|
||||
2)+" "+f.currency+"\x3c/td\x3e\x3c/tr\x3e"}).join("")+"\x3ctr\x3e\x3cth\x3e\x3c/th\x3e\x3cth\x3eTotal :\x3c/th\x3e\x3cth\x3e"+c+" \u20ac\x3c/th\x3e\x3c/tr\x3e\x3c/table\x3e\x3c/md-content\x3e"}};var e=function(a){return a.match(/^Income/)?-10:a.match(/^Expenses:(courses|Hang)$/)?1:a.match(/^Expenses:Home/)?1:a.match(/^Expenses:Health/)?1:a.match(/^Expenses:Car/)?4:a.match(/^Expenses:(Food|Transport)/)?5:a.match(/^Expenses:(Shopping|Leisure)/)?9:a.match(/^Expenses:Gadgets/)?10:a.match(/^Liabilities/)?
|
||||
0:a.match(/^Assets/)?-100:0};b.coloring_score=function(a){var b=a,c="#99f #0f0 #3f0 #6f0 #9f0 #cf0 #fc0 #f90 #f60 #f30 #f00".split(" ");-100>=a?(b=-1*a-100,c=["#f0f"]):-10>=a&&(b=-1*a-10,c=["#360"]);return c[b]};b.color=function(){return function(a,c){return b.coloring_score(e(a.data.account))}};b.filter_data=function(){_(b.balance.buckets).each(function(b){b.data=[];_(b.accounts_selected).isEmpty()&&0===b.score_threshold?b.data=b.raw_data:_(b.accounts_selected).each(function(c){b.data=b.data.concat(a("filter")(b.raw_data,
|
||||
c,!0))});b.total_detailed=_.chain(b.data).groupBy(function(a){return a.account.split(":")[0]}).each(function(a){a.total=_(a).reduce(function(a,b){return a+b.amount},0)}).value();b.total_detailed=_.chain(b.total_detailed).keys().map(function(a){return{account:a,amount:b.total_detailed[a].total}}).value()})};var d=function(a,b){var c=this;this.categories=a;this.period=b;this.score_threshold=0;this.orderBy="amount";this.orderDesc=!1;this.order_by=function(a){c.orderBy==a?c.orderDesc=!c.orderDesc:c.orderBy=
|
||||
a};this.pie_graph_options={chart:{type:"pieChart",donut:!0,donutRatio:.25,height:300,x:function(a){return a.account},y:function(a){return a.amount},showLabels:!1,showLegend:!0,legendPosition:"right",showTooltipPercent:!0,duration:500,labelThreshold:.01,labelSunbeamLayout:!0,labelsOutside:!0}}};b.depth=99;var g=function(){b.balance={buckets:[new d("Expenses Liabilities Equity Income",b.period),new d("Assets",null)],details:{}};_(b.balance.buckets).each(function(a){c.balance({period:a.period,categories:a.categories,
|
||||
depth:b.depth}).then(function(c){a.raw_data=_.chain(c.data).map(function(a){a.amount=0>a.amount?-1*a.amount:a.amount;a.score=e(a.account);return a}).sortBy(function(a){return 1/a.amount}).sortBy(function(a){return a.account.split(":")[0]}).value().reverse();a.raw_total=_(c.data).reduce(function(a,b){return a+b.amount},0);a.accounts_selected=a.raw_data;b.filter_data()})})};b.graphed_accounts=["Expenses","Income"];(function(){c.accounts().then(function(a){b.accounts=a.data.map(function(a){return a.join(":")})})})();
|
||||
g();(function(a){c.graph_values(a).then(function(a){b.periods=[];var c=_(a.data).reduce(function(a,b){return b.length>a.length?b:a},[]);_.chain(c).pluck("date").each(function(b){_(a.data).each(function(a){var c=_(a).find({date:b});_(c).isUndefined()&&a.push({date:b,amount:0,currency:_(a).first().currency})})});_(a.data).each(function(a){a=_(a).sortBy(function(a){return a.date})});b.graphiques={monthly_values:{options:{chart:{type:"multiBarChart",height:300,showControls:!1,showLegend:!0,showLabels:!0,
|
||||
stacked:!1,duration:500,reduceXTicks:!1,rotateLabels:67,labelSunbeamLayout:!0,useInteractiveGuideline:!1,multibar:{dispatch:{elementClick:function(a){b.period=a.data.x;g()}}}}},data:_.chain(a.data).keys().reverse().map(function(c){var e="Income"==c?-1:1;return{key:c,values:_.chain(a.data[c]).map(function(a){var d=new Date(a.date);d=d.getFullYear()+"-"+(9>d.getMonth()?"0":"")+(d.getMonth()+1);b.periods.push(d);return{key:c,x:d,y:parseInt(a.amount)*e}}).sortBy(function(a){return a.x}).value()}}).value()}};
|
||||
b.periods=_.chain(b.periods).uniq().sort().reverse().value();b.period=_(b.periods).first()})})({period:"",categories:b.graphed_accounts.join(" ")})}],template:'\n\x3cmd-content flex\x3d"100" layout\x3d"column"\x3e\n \x3cmd-card flex\x3d"100" layout\x3d"row"\x3e\n \x3cmd-card flex\x3d"20"\x3e\n \x3cselect style\x3d"height: 100%;" multiple ng:model\x3d"$ctrl.graphed_accounts"\x3e\n \x3coption ng:repeat\x3d"account in $ctrl.accounts"\x3e{{account}}\x3c/option\x3e\n \x3c/select\x3e\n \x3c/md-card\x3e\n \x3cmd-card flex\x3d"81"\x3e\n \x3cnvd3 data\x3d"$ctrl.graphiques.monthly_values.data"\n options\x3d"$ctrl.graphiques.monthly_values.options"\x3e\x3c/nvd3\x3e\n \x3c/md-card\x3e\n \x3c/md-card\x3e\n \x3ch1 style\x3d"text-align: center;"\x3e{{$ctrl.period | amDateFormat:\'MMMM YYYY\'}}\x3c/h1\x3e\n \x3cmd-card flex\x3d"100" layout\x3d"column"\n ng:repeat\x3d"bucket in $ctrl.balance.buckets"\x3e\n \x3cmd-toolbar\x3e\n \x3cspan ng:repeat\x3d"account in bucket.total_detailed"\x3e{{account.account}} \x3d {{account.amount | number:2}} \u20ac\x3c/span\x3e\n \x3c/md-toolbar\x3e\n \x3cmd-content layout\x3d"row"\x3e\n \x3cmd-card flex\x3d"20"\x3e\n \x3cselect style\x3d"height: 100%;" multiple\n ng:model\x3d"bucket.accounts_selected"\n ng:options\x3d"account.account for account in bucket.raw_data | orderBy:\'account\'"\n ng:change\x3d"filter_data()"\x3e\n \x3coption value\x3d\'\'\x3e...\x3c/option\x3e\n \x3c/select\x3e\n \x3c/md-card\x3e\n \x3cmd-card flex\x3d"78"\x3e\n \x3cnvd3 data\x3d"bucket.data"\n options\x3d"bucket.pie_graph_options" \x3e\n \x3c/nvd3\x3e\n \x3c/md-card\x3e\n \x3c!-- \x3cmd-card flex\x3d"56"\x3e\n \x3ctable class\x3d"table"\x3e\n \x3cthead\x3e\n \x3ctr\x3e\n \x3cth\x3e\x3cmd-buton ng:click\x3d"bucket.order_by( \'account\' )"\x3eaccount\x3c/md-buton\x3e\x3c/th\x3e\n \x3cth\x3e\x3cmd-buton ng:click\x3d"bucket.order_by( \'amount\' )"\x3eamount\x3c/md-buton\x3e\x3c/th\x3e\n \x3cth\x3e\x3cmd-buton ng:click\x3d"bucket.order_by( \'score\' )"\x3escore\x3c/md-buton\x3e\x3c/th\x3e\n \x3c/tr\x3e\n \x3c/thead\x3e\n \x3ctbody\x3e\n \x3ctr ng:repeat\x3d"account in bucket.data | orderBy:bucket.orderBy:bucket.orderDesc"\n ng:class\x3d"{\'even\': $even, \'odd\': $odd}"\n style\x3d"border-left:10px solid {{coloring_score( account.score )}};border-right:10px solid {{coloring_score( account.score )}}"\x3e\n \x3ctd style\x3d"border-bottom:1px solid {{coloring_score( account.score )}}"\x3e\n {{account.account}}\n \x3c/td\x3e\n \x3ctd style\x3d"text-align:right;border-bottom:1px solid {{coloring_score( account.score )}}"\x3e\n {{account.amount | number:2}} \u20ac\n \x3c/td\x3e\n \x3ctd style\x3d"text-align:right;border-bottom:1px solid {{coloring_score( account.score )}}"\x3e\n {{account.score}}\n \x3c/td\x3e\n \x3c/tr\x3e\n \x3c/tbody\x3e\n \x3c/table\x3e\n \x3c/md-card\x3e --\x3e\n \x3c/md-content\x3e\n \x3c/md-card\x3e\n\x3c/md-content\x3e\n'});
|
||||
0:a.match(/^Assets/)?-100:0};b.coloring_score=function(a){var b=a,f="#99f #0f0 #3f0 #6f0 #9f0 #cf0 #fc0 #f90 #f60 #f30 #f00".split(" ");-100>=a?(b=-1*a-100,f=["#f0f"]):-10>=a&&(b=-1*a-10,f=["#360"]);return f[b]};b.color=function(){return function(a,c){return b.coloring_score(e(a.data.account))}};b.filter_data=function(){_(b.balance.buckets).each(function(b){b.data=[];_(b.accounts_selected).isEmpty()&&0===b.score_threshold?b.data=b.raw_data:_(b.accounts_selected).each(function(c){b.data=b.data.concat(a("filter")(b.raw_data,
|
||||
c,!0))});b.total_detailed=_.chain(b.data).groupBy(function(a){return a.account.split(":")[0]}).each(function(a){a.total=_(a).reduce(function(a,b){return a+b.amount},0)}).value();b.total_detailed=_.chain(b.total_detailed).keys().map(function(a){return{account:a,amount:b.total_detailed[a].total}}).value()})};var g=function(a,b){var c=this;this.categories=a;this.period=b;this.score_threshold=0;this.orderBy="amount";this.orderDesc=!1;this.order_by=function(a){c.orderBy==a?c.orderDesc=!c.orderDesc:c.orderBy=
|
||||
a};this.pie_graph_options={chart:{type:"pieChart",donut:!0,donutRatio:.25,height:300,x:function(a){return a.account},y:function(a){return a.amount},showLabels:!1,showLegend:!0,legendPosition:"right",showTooltipPercent:!0,duration:500,labelThreshold:.01,labelSunbeamLayout:!0,labelsOutside:!0}}};b.depth=99;var h=function(){console.log(b.period);b.balance={buckets:[new g("Expenses Liabilities Equity Income",b.period),new g("Assets",null)],details:{}};return c.all(_(b.balance.buckets).map(function(a){return d.balance({period:a.period,
|
||||
categories:a.categories,depth:b.depth}).then(function(c){a.raw_data=_.chain(c.data).map(function(a){a.amount=0>a.amount?-1*a.amount:a.amount;a.score=e(a.account);return a}).sortBy(function(a){return 1/a.amount}).sortBy(function(a){return a.account.split(":")[0]}).value().reverse();a.raw_total=_(c.data).reduce(function(a,b){return a+b.amount},0);a.accounts_selected=a.raw_data;b.filter_data()})}))},k=function(a){return c.when(d.graph_values(a).then(function(a){b.periods=[];var c=_(a.data).reduce(function(a,
|
||||
b){return b.length>a.length?b:a},[]);_.chain(c).pluck("date").each(function(b){_(a.data).each(function(a){var c=_(a).find({date:b});_(c).isUndefined()&&a.push({date:b,amount:0,currency:_(a).first().currency})})});_(a.data).each(function(a){a=_(a).sortBy(function(a){return a.date})});b.graphiques={monthly_values:{options:{chart:{type:"multiBarChart",height:300,showControls:!1,showLegend:!0,showLabels:!0,stacked:!1,duration:500,reduceXTicks:!1,rotateLabels:67,labelSunbeamLayout:!0,useInteractiveGuideline:!1,
|
||||
multibar:{dispatch:{elementClick:function(a){b.period=a.data.x;h()}}}}},data:_.chain(a.data).keys().reverse().map(function(c){var d="Income"==c?-1:1;return{key:c,values:_.chain(a.data[c]).map(function(a){var e=new Date(a.date);e=e.getFullYear()+"-"+(9>e.getMonth()?"0":"")+(e.getMonth()+1);b.periods.push(e);return{key:c,x:e,y:parseInt(a.amount)*d}}).sortBy(function(a){return a.x}).value()}}).value()}};b.periods=_.chain(b.periods).uniq().sort().reverse().value();b.period=_(b.periods).first()}))};b.graphed_accounts=
|
||||
["Expenses","Income"];(function(){return c.when(d.accounts().then(function(a){b.accounts=a.data.map(function(a){return a.join(":")})}))})().then(function(a){k({period:"",categories:b.graphed_accounts.join(" ")}).then(function(a){h()})})}],template:'\n\x3cmd-content flex\x3d"100" layout\x3d"column"\x3e\n \x3cmd-card flex\x3d"100" layout\x3d"row"\x3e\n \x3cmd-card flex\x3d"20"\x3e\n \x3cselect style\x3d"height: 100%;" multiple ng:model\x3d"$ctrl.graphed_accounts"\x3e\n \x3coption ng:repeat\x3d"account in $ctrl.accounts"\x3e{{account}}\x3c/option\x3e\n \x3c/select\x3e\n \x3c/md-card\x3e\n \x3cmd-card flex\x3d"81"\x3e\n \x3cnvd3 data\x3d"$ctrl.graphiques.monthly_values.data"\n options\x3d"$ctrl.graphiques.monthly_values.options"\x3e\x3c/nvd3\x3e\n \x3c/md-card\x3e\n \x3c/md-card\x3e\n \x3ch1 style\x3d"text-align: center;"\x3e{{$ctrl.period | amDateFormat:\'MMMM YYYY\'}}\x3c/h1\x3e\n \x3cmd-card flex\x3d"100" layout\x3d"column"\n ng:repeat\x3d"bucket in $ctrl.balance.buckets"\x3e\n \x3cmd-toolbar\x3e\n \x3cspan ng:repeat\x3d"account in bucket.total_detailed"\x3e{{account.account}} \x3d {{account.amount | number:2}} \u20ac\x3c/span\x3e\n \x3c/md-toolbar\x3e\n \x3cmd-content layout\x3d"row"\x3e\n \x3cmd-card flex\x3d"20"\x3e\n \x3cselect style\x3d"height: 100%;" multiple\n ng:model\x3d"bucket.accounts_selected"\n ng:options\x3d"account.account for account in bucket.raw_data | orderBy:\'account\'"\n ng:change\x3d"filter_data()"\x3e\n \x3coption value\x3d\'\'\x3e...\x3c/option\x3e\n \x3c/select\x3e\n \x3c/md-card\x3e\n \x3cmd-card flex\x3d"78"\x3e\n \x3cnvd3 data\x3d"bucket.data"\n options\x3d"bucket.pie_graph_options" \x3e\n \x3c/nvd3\x3e\n \x3c/md-card\x3e\n \x3c!-- \x3cmd-card flex\x3d"56"\x3e\n \x3ctable class\x3d"table"\x3e\n \x3cthead\x3e\n \x3ctr\x3e\n \x3cth\x3e\x3cmd-buton ng:click\x3d"bucket.order_by( \'account\' )"\x3eaccount\x3c/md-buton\x3e\x3c/th\x3e\n \x3cth\x3e\x3cmd-buton ng:click\x3d"bucket.order_by( \'amount\' )"\x3eamount\x3c/md-buton\x3e\x3c/th\x3e\n \x3cth\x3e\x3cmd-buton ng:click\x3d"bucket.order_by( \'score\' )"\x3escore\x3c/md-buton\x3e\x3c/th\x3e\n \x3c/tr\x3e\n \x3c/thead\x3e\n \x3ctbody\x3e\n \x3ctr ng:repeat\x3d"account in bucket.data | orderBy:bucket.orderBy:bucket.orderDesc"\n ng:class\x3d"{\'even\': $even, \'odd\': $odd}"\n style\x3d"border-left:10px solid {{coloring_score( account.score )}};border-right:10px solid {{coloring_score( account.score )}}"\x3e\n \x3ctd style\x3d"border-bottom:1px solid {{coloring_score( account.score )}}"\x3e\n {{account.account}}\n \x3c/td\x3e\n \x3ctd style\x3d"text-align:right;border-bottom:1px solid {{coloring_score( account.score )}}"\x3e\n {{account.amount | number:2}} \u20ac\n \x3c/td\x3e\n \x3ctd style\x3d"text-align:right;border-bottom:1px solid {{coloring_score( account.score )}}"\x3e\n {{account.score}}\n \x3c/td\x3e\n \x3c/tr\x3e\n \x3c/tbody\x3e\n \x3c/table\x3e\n \x3c/md-card\x3e --\x3e\n \x3c/md-content\x3e\n \x3c/md-card\x3e\n\x3c/md-content\x3e\n'});
|
||||
app.service("API",["$http",function(a){this.balance=function(c){return a.get("/api/ledger/balance",{params:{period:c.period,categories:c.categories,depth:c.depth}})};this.register=function(c){return a.get("/api/ledger/register",{params:{period:c.period,categories:c.categories}})};this.graph_values=function(c){return a.get("/api/ledger/graph_values",{params:{period:c.period,categories:c.categories}})};this.budget=function(c){return a.get("/api/ledger/budget",{params:{period:c.period,categories:c.categories}})};
|
||||
this.dates_salaries=function(){return a.get("/api/ledger/dates_salaries")};this.accounts=function(){return a.get("/api/ledger/accounts")};this.cleared=function(){return a.get("/api/ledger/cleared")}}]);
|
||||
|
|
|
@ -1,289 +1,296 @@
|
|||
app.component('dashboard',
|
||||
{
|
||||
controller: ['$filter', 'API',
|
||||
function($filter, API) {
|
||||
let ctrl = this;
|
||||
{
|
||||
controller: ['$filter', '$q', 'API',
|
||||
function($filter, $q, API) {
|
||||
let ctrl = this;
|
||||
|
||||
ctrl.xFunction = function() {
|
||||
return function(d) {
|
||||
return d.account;
|
||||
};
|
||||
};
|
||||
ctrl.yFunction = function() {
|
||||
return function(d) {
|
||||
return d.amount;
|
||||
};
|
||||
};
|
||||
ctrl.toolTipContentFunction = function() {
|
||||
return function(key, x, y, e, graph) {
|
||||
let details = ctrl.balance.details[key];
|
||||
return '<md-content><h3>' + key + '</h3>' + '<table>' + _(details).map(function(transaction) {
|
||||
return '<tr><td>' + transaction.date + '</td><td>' + transaction.payee + '</td><td style="text-align: right">' + $filter('number')(transaction.amount, 2) + ' ' + transaction.currency + '</td></tr>';
|
||||
}).join('') + '<tr><th></th><th>Total :</th><th>' + x + ' €</th></tr>' + '</table></md-content>';
|
||||
};
|
||||
};
|
||||
ctrl.xFunction = function() {
|
||||
return function(d) {
|
||||
return d.account;
|
||||
};
|
||||
};
|
||||
ctrl.yFunction = function() {
|
||||
return function(d) {
|
||||
return d.amount;
|
||||
};
|
||||
};
|
||||
ctrl.toolTipContentFunction = function() {
|
||||
return function(key, x, y, e, graph) {
|
||||
let details = ctrl.balance.details[key];
|
||||
return '<md-content><h3>' + key + '</h3>' + '<table>' + _(details).map(function(transaction) {
|
||||
return '<tr><td>' + transaction.date + '</td><td>' + transaction.payee + '</td><td style="text-align: right">' + $filter('number')(transaction.amount, 2) + ' ' + transaction.currency + '</td></tr>';
|
||||
}).join('') + '<tr><th></th><th>Total :</th><th>' + x + ' €</th></tr>' + '</table></md-content>';
|
||||
};
|
||||
};
|
||||
|
||||
// compute an account's score: from 1 (good) to 10 (bad), 0 is neutral/undecided
|
||||
let score_account = function(account) {
|
||||
if (account.match(/^Income/)) {
|
||||
return -10;
|
||||
} else if (account.match(/^Expenses:(courses|Hang)$/)) {
|
||||
return 1;
|
||||
} else if (account.match(/^Expenses:Home/)) {
|
||||
return 1;
|
||||
} else if (account.match(/^Expenses:Health/)) {
|
||||
return 1;
|
||||
} else if (account.match(/^Expenses:Car/)) {
|
||||
return 4;
|
||||
} else if (account.match(/^Expenses:(Food|Transport)/)) {
|
||||
return 5;
|
||||
} else if (account.match(/^Expenses:(Shopping|Leisure)/)) {
|
||||
return 9;
|
||||
} else if (account.match(/^Expenses:Gadgets/)) {
|
||||
return 10;
|
||||
} else if (account.match(/^Liabilities/)) {
|
||||
return 0;
|
||||
} else if (account.match(/^Assets/)) {
|
||||
return -100;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
// compute an account's score: from 1 (good) to 10 (bad), 0 is neutral/undecided
|
||||
let score_account = function(account) {
|
||||
if (account.match(/^Income/)) {
|
||||
return -10;
|
||||
} else if (account.match(/^Expenses:(courses|Hang)$/)) {
|
||||
return 1;
|
||||
} else if (account.match(/^Expenses:Home/)) {
|
||||
return 1;
|
||||
} else if (account.match(/^Expenses:Health/)) {
|
||||
return 1;
|
||||
} else if (account.match(/^Expenses:Car/)) {
|
||||
return 4;
|
||||
} else if (account.match(/^Expenses:(Food|Transport)/)) {
|
||||
return 5;
|
||||
} else if (account.match(/^Expenses:(Shopping|Leisure)/)) {
|
||||
return 9;
|
||||
} else if (account.match(/^Expenses:Gadgets/)) {
|
||||
return 10;
|
||||
} else if (account.match(/^Liabilities/)) {
|
||||
return 0;
|
||||
} else if (account.match(/^Assets/)) {
|
||||
return -100;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
ctrl.coloring_score = function(score) {
|
||||
let adjusted_score = score;
|
||||
let color_scale = ['#99f', '#0f0', '#3f0', '#6f0', '#9f0', '#cf0', '#fc0', '#f90', '#f60', '#f30', '#f00'];
|
||||
ctrl.coloring_score = function(score) {
|
||||
let adjusted_score = score;
|
||||
let color_scale = ['#99f', '#0f0', '#3f0', '#6f0', '#9f0', '#cf0', '#fc0', '#f90', '#f60', '#f30', '#f00'];
|
||||
|
||||
if (score <= -100) {
|
||||
// Assets
|
||||
adjusted_score = (score * -1) - 100;
|
||||
color_scale = ['#f0f'];
|
||||
} else if (score <= -10) {
|
||||
// Income
|
||||
adjusted_score = (score * -1) - 10;
|
||||
color_scale = ['#360'];
|
||||
}
|
||||
if (score <= -100) {
|
||||
// Assets
|
||||
adjusted_score = (score * -1) - 100;
|
||||
color_scale = ['#f0f'];
|
||||
} else if (score <= -10) {
|
||||
// Income
|
||||
adjusted_score = (score * -1) - 10;
|
||||
color_scale = ['#360'];
|
||||
}
|
||||
|
||||
return color_scale[adjusted_score];
|
||||
};
|
||||
return color_scale[adjusted_score];
|
||||
};
|
||||
|
||||
ctrl.color = function() {
|
||||
return function(d, i) {
|
||||
return ctrl.coloring_score(score_account(d.data.account));
|
||||
};
|
||||
};
|
||||
ctrl.color = function() {
|
||||
return function(d, i) {
|
||||
return ctrl.coloring_score(score_account(d.data.account));
|
||||
};
|
||||
};
|
||||
|
||||
ctrl.filter_data = function() {
|
||||
_(ctrl.balance.buckets).each(function(bucket) {
|
||||
bucket.data = [];
|
||||
ctrl.filter_data = function() {
|
||||
_(ctrl.balance.buckets).each(function(bucket) {
|
||||
bucket.data = [];
|
||||
|
||||
if (_(bucket.accounts_selected).isEmpty() && bucket.score_threshold === 0) {
|
||||
bucket.data = bucket.raw_data;
|
||||
} else {
|
||||
_(bucket.accounts_selected).each(function(account_selected) {
|
||||
bucket.data = bucket.data.concat($filter('filter')(bucket.raw_data, account_selected, true));
|
||||
});
|
||||
}
|
||||
if (_(bucket.accounts_selected).isEmpty() && bucket.score_threshold === 0) {
|
||||
bucket.data = bucket.raw_data;
|
||||
} else {
|
||||
_(bucket.accounts_selected).each(function(account_selected) {
|
||||
bucket.data = bucket.data.concat($filter('filter')(bucket.raw_data, account_selected, true));
|
||||
});
|
||||
}
|
||||
|
||||
bucket.total_detailed = _.chain(bucket.data)
|
||||
.groupBy(function(account) {
|
||||
return account.account.split(':')[0];
|
||||
})
|
||||
.each(function(category) {
|
||||
category.total = _(category).reduce(function(memo, account) {
|
||||
return memo + account.amount;
|
||||
}, 0);
|
||||
})
|
||||
.value();
|
||||
bucket.total_detailed = _.chain(bucket.total_detailed)
|
||||
.keys()
|
||||
.map(function(key) {
|
||||
return {
|
||||
account: key,
|
||||
amount: bucket.total_detailed[key].total
|
||||
};
|
||||
})
|
||||
.value();
|
||||
bucket.total_detailed = _.chain(bucket.data)
|
||||
.groupBy(function(account) {
|
||||
return account.account.split(':')[0];
|
||||
})
|
||||
.each(function(category) {
|
||||
category.total = _(category).reduce(function(memo, account) {
|
||||
return memo + account.amount;
|
||||
}, 0);
|
||||
})
|
||||
.value();
|
||||
bucket.total_detailed = _.chain(bucket.total_detailed)
|
||||
.keys()
|
||||
.map(function(key) {
|
||||
return {
|
||||
account: key,
|
||||
amount: bucket.total_detailed[key].total
|
||||
};
|
||||
})
|
||||
.value();
|
||||
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
let Bucket = function(categories, period) {
|
||||
let _this = this;
|
||||
this.categories = categories;
|
||||
this.period = period;
|
||||
this.score_threshold = 0;
|
||||
this.orderBy = 'amount';
|
||||
this.orderDesc = false;
|
||||
this.order_by = function(field) {
|
||||
if (_this.orderBy == field) {
|
||||
_this.orderDesc = !_this.orderDesc;
|
||||
} else {
|
||||
_this.orderBy = field;
|
||||
}
|
||||
};
|
||||
let Bucket = function(categories, period) {
|
||||
let _this = this;
|
||||
this.categories = categories;
|
||||
this.period = period;
|
||||
this.score_threshold = 0;
|
||||
this.orderBy = 'amount';
|
||||
this.orderDesc = false;
|
||||
this.order_by = function(field) {
|
||||
if (_this.orderBy == field) {
|
||||
_this.orderDesc = !_this.orderDesc;
|
||||
} else {
|
||||
_this.orderBy = field;
|
||||
}
|
||||
};
|
||||
|
||||
this.pie_graph_options = {
|
||||
chart: {
|
||||
type: 'pieChart',
|
||||
donut: true,
|
||||
donutRatio: 0.25,
|
||||
height: 300,
|
||||
x: function(d) { return d.account; },
|
||||
y: function(d) { return d.amount; },
|
||||
showLabels: false,
|
||||
showLegend: true,
|
||||
legendPosition: 'right',
|
||||
showTooltipPercent: true,
|
||||
duration: 500,
|
||||
labelThreshold: 0.01,
|
||||
labelSunbeamLayout: true,
|
||||
labelsOutside: true
|
||||
}
|
||||
};
|
||||
};
|
||||
this.pie_graph_options = {
|
||||
chart: {
|
||||
type: 'pieChart',
|
||||
donut: true,
|
||||
donutRatio: 0.25,
|
||||
height: 300,
|
||||
x: function(d) { return d.account; },
|
||||
y: function(d) { return d.amount; },
|
||||
showLabels: false,
|
||||
showLegend: true,
|
||||
legendPosition: 'right',
|
||||
showTooltipPercent: true,
|
||||
duration: 500,
|
||||
labelThreshold: 0.01,
|
||||
labelSunbeamLayout: true,
|
||||
labelsOutside: true
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
ctrl.depth = 99;
|
||||
ctrl.depth = 99;
|
||||
|
||||
let retrieve_period_detailed_data = function() {
|
||||
ctrl.balance = {
|
||||
buckets: [new Bucket('Expenses Liabilities Equity Income', ctrl.period),
|
||||
new Bucket('Assets', null)],
|
||||
details: {}
|
||||
};
|
||||
let retrieve_period_detailed_data = function() {
|
||||
console.log(ctrl.period)
|
||||
ctrl.balance = {
|
||||
buckets: [new Bucket('Expenses Liabilities Equity Income', ctrl.period),
|
||||
new Bucket('Assets', null)],
|
||||
details: {}
|
||||
};
|
||||
|
||||
_(ctrl.balance.buckets).each(function(bucket) {
|
||||
API.balance({
|
||||
period: bucket.period,
|
||||
categories: bucket.categories,
|
||||
depth: ctrl.depth
|
||||
})
|
||||
.then(function(response) {
|
||||
bucket.raw_data = _.chain(response.data)
|
||||
.map(function(account) {
|
||||
account.amount = (account.amount < 0) ? account.amount * -1 : account.amount;
|
||||
account.score = score_account(account.account);
|
||||
return account;
|
||||
})
|
||||
.sortBy(function(account) {
|
||||
return 1 / account.amount;
|
||||
})
|
||||
.sortBy(function(account) {
|
||||
return account.account.split(":")[0];
|
||||
})
|
||||
.value()
|
||||
.reverse();
|
||||
bucket.raw_total = _(response.data).reduce(function(memo, account) {
|
||||
return memo + account.amount;
|
||||
}, 0);
|
||||
bucket.accounts_selected = bucket.raw_data;
|
||||
return $q.all(_(ctrl.balance.buckets).map(function(bucket) {
|
||||
return API.balance({
|
||||
period: bucket.period,
|
||||
categories: bucket.categories,
|
||||
depth: ctrl.depth
|
||||
})
|
||||
.then(function(response) {
|
||||
bucket.raw_data = _.chain(response.data)
|
||||
.map(function(account) {
|
||||
account.amount = (account.amount < 0) ? account.amount * -1 : account.amount;
|
||||
account.score = score_account(account.account);
|
||||
return account;
|
||||
})
|
||||
.sortBy(function(account) {
|
||||
return 1 / account.amount;
|
||||
})
|
||||
.sortBy(function(account) {
|
||||
return account.account.split(":")[0];
|
||||
})
|
||||
.value()
|
||||
.reverse();
|
||||
bucket.raw_total = _(response.data).reduce(function(memo, account) {
|
||||
return memo + account.amount;
|
||||
}, 0);
|
||||
bucket.accounts_selected = bucket.raw_data;
|
||||
|
||||
ctrl.filter_data();
|
||||
});
|
||||
});
|
||||
};
|
||||
ctrl.filter_data();
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
let retrieve_accounts = function() {
|
||||
API.accounts()
|
||||
.then(function(response) {
|
||||
ctrl.accounts = response.data.map(function(account_ary) {
|
||||
return account_ary.join(':');
|
||||
});
|
||||
});
|
||||
};
|
||||
let retrieve_accounts = function() {
|
||||
return $q.when(API.accounts()
|
||||
.then(function(response) {
|
||||
ctrl.accounts = response.data.map(function(account_ary) {
|
||||
return account_ary.join(':');
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
let retrieve_graph_values = function(params) {
|
||||
API.graph_values(params).then(function(response) {
|
||||
ctrl.periods = [];
|
||||
let retrieve_graph_values = function(params) {
|
||||
return $q.when(API.graph_values(params)
|
||||
.then(function(response) {
|
||||
ctrl.periods = [];
|
||||
|
||||
let largest_cat = _(response.data).reduce(function(memo, cat) {
|
||||
return cat.length > memo.length ? cat : memo;
|
||||
}, []);
|
||||
_.chain(largest_cat)
|
||||
.pluck('date')
|
||||
.each(function(date) {
|
||||
_(response.data).each(function(cat) {
|
||||
let value = _(cat).find({ date: date });
|
||||
if (_(value).isUndefined()) {
|
||||
cat.push({
|
||||
date: date,
|
||||
amount: 0,
|
||||
currency: _(cat).first().currency
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
_(response.data).each(function(cat) {
|
||||
cat = _(cat).sortBy(function(month) {
|
||||
return month.date;
|
||||
});
|
||||
});
|
||||
let largest_cat = _(response.data).reduce(function(memo, cat) {
|
||||
return cat.length > memo.length ? cat : memo;
|
||||
}, []);
|
||||
_.chain(largest_cat)
|
||||
.pluck('date')
|
||||
.each(function(date) {
|
||||
_(response.data).each(function(cat) {
|
||||
let value = _(cat).find({ date: date });
|
||||
if (_(value).isUndefined()) {
|
||||
cat.push({
|
||||
date: date,
|
||||
amount: 0,
|
||||
currency: _(cat).first().currency
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
_(response.data).each(function(cat) {
|
||||
cat = _(cat).sortBy(function(month) {
|
||||
return month.date;
|
||||
});
|
||||
});
|
||||
|
||||
ctrl.graphiques = {
|
||||
monthly_values: {
|
||||
options: {
|
||||
chart: {
|
||||
type: 'multiBarChart',
|
||||
height: 300,
|
||||
showControls: false,
|
||||
showLegend: true,
|
||||
showLabels: true,
|
||||
stacked: false,
|
||||
duration: 500,
|
||||
reduceXTicks: false,
|
||||
rotateLabels: 67,
|
||||
labelSunbeamLayout: true,
|
||||
useInteractiveGuideline: false,
|
||||
multibar: {
|
||||
dispatch: {
|
||||
elementClick: function(event) {
|
||||
ctrl.period = event.data.x;
|
||||
retrieve_period_detailed_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: _.chain(response.data)
|
||||
.keys()
|
||||
.reverse()
|
||||
.map(function(key) {
|
||||
let multiplicator = (key == "Income") ? -1 : 1;
|
||||
return {
|
||||
key: key,
|
||||
values: _.chain(response.data[key]).map(function(value) {
|
||||
let date = new Date(value.date);
|
||||
let period = date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1);
|
||||
ctrl.periods.push(period);
|
||||
ctrl.graphiques = {
|
||||
monthly_values: {
|
||||
options: {
|
||||
chart: {
|
||||
type: 'multiBarChart',
|
||||
height: 300,
|
||||
showControls: false,
|
||||
showLegend: true,
|
||||
showLabels: true,
|
||||
stacked: false,
|
||||
duration: 500,
|
||||
reduceXTicks: false,
|
||||
rotateLabels: 67,
|
||||
labelSunbeamLayout: true,
|
||||
useInteractiveGuideline: false,
|
||||
multibar: {
|
||||
dispatch: {
|
||||
elementClick: function(event) {
|
||||
ctrl.period = event.data.x;
|
||||
retrieve_period_detailed_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: _.chain(response.data)
|
||||
.keys()
|
||||
.reverse()
|
||||
.map(function(key) {
|
||||
let multiplicator = (key == "Income") ? -1 : 1;
|
||||
return {
|
||||
key: key,
|
||||
values: _.chain(response.data[key]).map(function(value) {
|
||||
let date = new Date(value.date);
|
||||
let period = date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1);
|
||||
ctrl.periods.push(period);
|
||||
|
||||
return {
|
||||
key: key,
|
||||
x: period,
|
||||
y: parseInt(value.amount) * multiplicator
|
||||
};
|
||||
})
|
||||
.sortBy(function(item) { return item.x; })
|
||||
.value()
|
||||
};
|
||||
})
|
||||
.value()
|
||||
}
|
||||
};
|
||||
return {
|
||||
key: key,
|
||||
x: period,
|
||||
y: parseInt(value.amount) * multiplicator
|
||||
};
|
||||
})
|
||||
.sortBy(function(item) { return item.x; })
|
||||
.value()
|
||||
};
|
||||
})
|
||||
.value()
|
||||
}
|
||||
};
|
||||
|
||||
ctrl.periods = _.chain(ctrl.periods).uniq().sort().reverse().value();
|
||||
ctrl.period = _(ctrl.periods).first();
|
||||
});
|
||||
};
|
||||
ctrl.periods = _.chain(ctrl.periods).uniq().sort().reverse().value();
|
||||
ctrl.period = _(ctrl.periods).first();
|
||||
}));
|
||||
};
|
||||
|
||||
ctrl.graphed_accounts = ['Expenses', 'Income'];
|
||||
ctrl.graphed_accounts = ['Expenses', 'Income'];
|
||||
|
||||
retrieve_accounts();
|
||||
retrieve_period_detailed_data();
|
||||
retrieve_graph_values({ period: '',
|
||||
categories: ctrl.graphed_accounts.join(' ') });
|
||||
}
|
||||
],
|
||||
template: `
|
||||
retrieve_accounts().then(function(response) {
|
||||
retrieve_graph_values({
|
||||
period: '',
|
||||
categories: ctrl.graphed_accounts.join(' ')
|
||||
}).then(function(response) {
|
||||
retrieve_period_detailed_data();
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
],
|
||||
template: `
|
||||
<md-content flex="100" layout="column">
|
||||
<md-card flex="100" layout="row">
|
||||
<md-card flex="20">
|
||||
|
@ -346,4 +353,4 @@ app.component('dashboard',
|
|||
</md-card>
|
||||
</md-content>
|
||||
`
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue