diff --git a/public/app/js/app.js b/public/app/js/app.js index fa449638..7a1a5334 100644 --- a/public/app/js/app.js +++ b/public/app/js/app.js @@ -21,108 +21,46 @@ app.component('dashboard', { controller: ['$filter', '$q', 'API', function ($filter, $q, API) { var ctrl = this; - ctrl.xFunction = function () { - return function (d) { - return d.account; - }; - }; - ctrl.yFunction = function () { - return function (d) { - return d.amount; - }; - }; + 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) { var details = ctrl.balance.details[key]; - return '

' + key + '

' + '' + _(details).map(function (transaction) { - return ''; - }).join('') + '' + '
' + transaction.date + '' + transaction.payee + '' + $filter('number')(transaction.amount, 2) + ' ' + transaction.currency + '
Total :' + x + ' €
'; + console.log(details); + return "

" + key + "

" + _(details).map(function (transaction) { + return ""; + }).join('') + "
" + transaction.date + "" + transaction.payee + "" + $filter('number')(transaction.amount, 2) + " " + transaction.currency + "
Total :" + x + " \u20AC
'"; }; }; - var 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; + ctrl.filter_data = function (bucket) { + bucket.data = [{ key: bucket.categories, values: [] }]; + if (_(bucket.accounts_selected).isEmpty() && bucket.score_threshold === 0) { + bucket.data[0].values = bucket.raw_data; } else { - return 0; + _(bucket.accounts_selected).each(function (account_selected) { + bucket.data[0].values = bucket.data[0].values.concat($filter('filter')(bucket.raw_data, account_selected, true)); + }); } - }; - ctrl.coloring_score = function (score) { - var adjusted_score = score; - var color_scale = ['#99f', '#0f0', '#3f0', '#6f0', '#9f0', '#cf0', '#fc0', '#f90', '#f60', '#f30', '#f00']; - if (score <= -100) { - adjusted_score = (score * -1) - 100; - color_scale = ['#f0f']; - } - else if (score <= -10) { - adjusted_score = (score * -1) - 10; - color_scale = ['#360']; - } - return color_scale[adjusted_score]; - }; - 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 = [{ key: 'accounts', values: [] }]; - if (_(bucket.accounts_selected).isEmpty() && bucket.score_threshold === 0) { - bucket.data[0].values = bucket.raw_data; - } - else { - _(bucket.accounts_selected).each(function (account_selected) { - bucket.data[0].values = bucket.data[0].values.concat($filter('filter')(bucket.raw_data, account_selected, true)); - }); - } - bucket.total_detailed = _.chain(bucket.data[0].values) - .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[0].values) + .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(); }; var Bucket = function (categories, period) { var _this = this; @@ -164,9 +102,24 @@ app.component('dashboard', { }; }; ctrl.depth = 99; + var merge_buckets = function (buckets) { + var first_bucket = ctrl.balance.buckets.shift(); + ctrl.balance.buckets = [_(ctrl.balance.buckets).reduce(function (memo, bucket) { + memo.categories += " " + bucket.categories; + memo.graph_options.chart.height += bucket.graph_options.chart.height; + memo.raw_data = memo.raw_data.concat(bucket.raw_data); + memo.data.push(bucket.data[0]); + memo.total_detailed = memo.total_detailed.concat(bucket.total_detailed); + return memo; + }, first_bucket)]; + console.log(ctrl.balance.buckets); + }; var retrieve_period_detailed_data = function () { ctrl.balance = { - buckets: [new Bucket('Expenses Liabilities Equity Income', ctrl.period)], + buckets: [new Bucket('Expenses', ctrl.period), + new Bucket('Liabilities', ctrl.period), + new Bucket('Equity', ctrl.period), + new Bucket('Income', ctrl.period)], details: {} }; return $q.all(_(ctrl.balance.buckets).map(function (bucket) { @@ -177,10 +130,6 @@ app.component('dashboard', { }) .then(function (response) { bucket.raw_data = _.chain(response.data) - .map(function (account) { - account.score = score_account(account.account); - return account; - }) .sortBy(function (account) { return 1 / account.amount; }) @@ -193,9 +142,13 @@ app.component('dashboard', { return memo + account.amount; }, 0); bucket.accounts_selected = bucket.raw_data; - ctrl.filter_data(); + ctrl.filter_data(bucket); + bucket.graph_options.chart.height = 60 + (15 * bucket.data[0].values.length); }); - })); + })) + .then(function () { + ctrl.buckets = merge_buckets(ctrl.buckets); + }); }; var retrieve_accounts = function () { return $q.when(API.accounts() diff --git a/public/app/js/app.min.js b/public/app/js/app.min.js index 6fc852e5..fc560333 100644 --- a/public/app/js/app.min.js +++ b/public/app/js/app.min.js @@ -3,16 +3,16 @@ $jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Sym $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?(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=[{key:"accounts",values:[]}];_(b.accounts_selected).isEmpty()&&0===b.score_threshold?b.data[0].values=b.raw_data:_(b.accounts_selected).each(function(c){b.data[0].values= -b.data[0].values.concat(a("filter")(b.raw_data,c,!0))});b.total_detailed=_.chain(b.data[0].values).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.graph_options={chart:{type:"multiBarHorizontalChart",height:600,margin:{top:20,right:20,bottom:20,left:200},x:function(a){return a.account},y:function(a){return a.amount},valueFormat:function(a){return a+" \u20ac"},showYAxis:!1,showValues:!0,showLegend:!1,showTooltipPercent:!0,duration:500,labelThreshold:.01,labelSunbeamLayout:!0,labelsOutside:!0}}};b.depth=99;var h=function(){b.balance={buckets:[new g("Expenses Liabilities Equity Income", -b.period)],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.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 \x3c!--\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 --\x3e\n \x3cmd-card flex\x3d"78"\x3e\n \x3cnvd3 data\x3d"bucket.data"\n options\x3d"bucket.graph_options" \x3e\n \x3c/nvd3\x3e\n \x3c/md-card\x3e\n \x3c!--\n \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\n --\x3e\n \x3c/md-content\x3e\n \x3c/md-card\x3e\n \x3c/md-content\x3e\n'}); +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(g,k,c,m,d){c=b.balance.details[g];console.log(c);return"\x3cmd-content\x3e\x3ch3\x3e"+g+"\x3c/h3\x3e\x3ctable\x3e"+_(c).map(function(b){return"\x3ctr\x3e\x3ctd\x3e"+b.date+"\x3c/td\x3e\x3ctd\x3e"+b.payee+'\x3c/td\x3e\x3ctd style\x3d"text-align: right"\x3e'+ +a("number")(b.amount,2)+" "+b.currency+"\x3c/td\x3e\x3c/tr\x3e"}).join("")+"\x3ctr\x3e\x3cth\x3e\x3c/th\x3e\x3cth\x3eTotal :\x3c/th\x3e\x3cth\x3e"+k+" \u20ac\x3c/th\x3e\x3c/tr\x3e\x3c/table\x3e\x3c/md-content\x3e'"}};b.filter_data=function(b){b.data=[{key:b.categories,values:[]}];_(b.accounts_selected).isEmpty()&&0===b.score_threshold?b.data[0].values=b.raw_data:_(b.accounts_selected).each(function(c){b.data[0].values=b.data[0].values.concat(a("filter")(b.raw_data,c,!0))});b.total_detailed=_.chain(b.data[0].values).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 e=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.graph_options={chart:{type:"multiBarHorizontalChart",height:600,margin:{top:20,right:20,bottom:20,left:200}, +x:function(a){return a.account},y:function(a){return a.amount},valueFormat:function(a){return a+" \u20ac"},showYAxis:!1,showValues:!0,showLegend:!1,showTooltipPercent:!0,duration:500,labelThreshold:.01,labelSunbeamLayout:!0,labelsOutside:!0}}};b.depth=99;var f=function(a){a=b.balance.buckets.shift();b.balance.buckets=[_(b.balance.buckets).reduce(function(a,b){a.categories+=" "+b.categories;a.graph_options.chart.height+=b.graph_options.chart.height;a.raw_data=a.raw_data.concat(b.raw_data);a.data.push(b.data[0]); +a.total_detailed=a.total_detailed.concat(b.total_detailed);return a},a)];console.log(b.balance.buckets)},h=function(){b.balance={buckets:[new e("Expenses",b.period),new e("Liabilities",b.period),new e("Equity",b.period),new e("Income",b.period)],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).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(a);a.graph_options.chart.height=60+15*a.data[0].values.length})})).then(function(){b.buckets=f(b.buckets)})},l=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){l({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 \x3c!--\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 --\x3e\n \x3cmd-card flex\x3d"78"\x3e\n \x3cnvd3 data\x3d"bucket.data"\n options\x3d"bucket.graph_options" \x3e\n \x3c/nvd3\x3e\n \x3c/md-card\x3e\n \x3c!--\n \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\n --\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")}}]); diff --git a/public/app/ts/components/dashboard.ts b/public/app/ts/components/dashboard.ts index 5e0afb98..5c252178 100644 --- a/public/app/ts/components/dashboard.ts +++ b/public/app/ts/components/dashboard.ts @@ -4,108 +4,36 @@ app.component('dashboard', 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 '

' + key + '

' + '' + _(details).map(function(transaction) { - return ''; - }).join('') + '' + '
' + transaction.date + '' + transaction.payee + '' + $filter('number')(transaction.amount, 2) + ' ' + transaction.currency + '
Total :' + x + ' €
'; - }; - }; + ctrl.filter_data = function(bucket) { + bucket.data = [{ key: bucket.categories, values: [] }]; - // 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; + if (_(bucket.accounts_selected).isEmpty() && bucket.score_threshold === 0) { + bucket.data[0].values = bucket.raw_data; } 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']; - - 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']; + _(bucket.accounts_selected).each(function(account_selected) { + bucket.data[0].values = bucket.data[0].values.concat($filter('filter')(bucket.raw_data, account_selected, true)); + }); } - return color_scale[adjusted_score]; - }; - - 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 = [{ key: 'accounts', values: [] }]; - - if (_(bucket.accounts_selected).isEmpty() && bucket.score_threshold === 0) { - bucket.data[0].values = bucket.raw_data; - } else { - _(bucket.accounts_selected).each(function(account_selected) { - bucket.data[0].values = bucket.data[0].values.concat($filter('filter')(bucket.raw_data, account_selected, true)); - }); - } - - bucket.total_detailed = _.chain(bucket.data[0].values) - .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[0].values) + .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) { @@ -125,7 +53,6 @@ app.component('dashboard', this.graph_options = { chart: { - //type: 'discreteBarChart', type: 'multiBarHorizontalChart', height: 600, margin: { @@ -151,10 +78,26 @@ app.component('dashboard', ctrl.depth = 99; + let merge_buckets = function(buckets) { + let first_bucket = ctrl.balance.buckets.shift(); + ctrl.balance.buckets = [_(ctrl.balance.buckets).reduce(function(memo, bucket) { + memo.categories += ` ${bucket.categories}`; + memo.graph_options.chart.height += bucket.graph_options.chart.height; + memo.raw_data = memo.raw_data.concat(bucket.raw_data); + memo.data.push(bucket.data[0]); + memo.total_detailed = memo.total_detailed.concat(bucket.total_detailed); + + return memo; + }, first_bucket)]; + console.log(ctrl.balance.buckets) + }; + let retrieve_period_detailed_data = function() { ctrl.balance = { - buckets: [new Bucket('Expenses Liabilities Equity Income', ctrl.period)],// , - // new Bucket('Assets', null)], + buckets: [new Bucket('Expenses', ctrl.period), + new Bucket('Liabilities', ctrl.period), + new Bucket('Equity', ctrl.period), + new Bucket('Income', ctrl.period)], details: {} }; @@ -166,10 +109,6 @@ app.component('dashboard', }) .then(function(response) { bucket.raw_data = _.chain(response.data) - .map(function(account) { - account.score = score_account(account.account); - return account; - }) .sortBy(function(account) { return 1 / account.amount; }) @@ -183,9 +122,14 @@ app.component('dashboard', }, 0); bucket.accounts_selected = bucket.raw_data; - ctrl.filter_data(); + ctrl.filter_data(bucket); + + bucket.graph_options.chart.height = 60 + (15 * bucket.data[0].values.length); }); - })); + })) + .then(function() { + ctrl.buckets = merge_buckets(ctrl.buckets); + }); }; let retrieve_accounts = function() { @@ -294,16 +238,17 @@ app.component('dashboard', }); } ], - template: ` - - - - - - - + + + + + +