Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* This list will be dynamically filled with all the transactions between
* the start and and date you select on the "Show Chart" page
* and filtered according to your specified filter.
* An example entry for this list and tutorial about how to create custom charts ca be found in the BudgetMaster wiki:
* https://github.com/deadlocker8/BudgetMaster/wiki/How-to-create-custom-charts
*/
var transactionData = [];
// Note: All variables starting with "localized" are only available inside default charts.
// objects for easier handling of categories with corresponding sums
class CategorySum
{
constructor(categoryName, color)
{
this.categoryName = categoryName;
this.color = color;
this.amount = 0;
}
add(amount)
{
this.amount += amount;
}
}
CategorySum.prototype.toString = function(){return this.categoryName + " , " + this.amount;};
class CategorySumHandler
{
constructor()
{
this.sums = [];
}
getByCategoryName(categoryName)
{
return this.sums.find(obj => {
return obj.categoryName === categoryName
});
}
add(categorySum)
{
this.sums.push(categorySum);
}
getTotalSum()
{
var total = 0;
this.sums.forEach(function(sum)
{
total += sum.amount;
});
return total;
}
static sortNumber(a, b)
{
return a.amount - b.amount;
}
getSumsSorted()
{
var sumsSorted = this.sums.filter(function(item){
return item.amount !== 0;
});
return sumsSorted.sort(CategorySumHandler.sortNumber);
}
}
var incomeHandler = new CategorySumHandler();
var expenditureHandler = new CategorySumHandler();
for(var i = 0; i < transactionData.length; i++)
{
var transaction = transactionData[i];
var categoryName = transaction.category.name;
// create new category if not already in dict
if(incomeHandler.getByCategoryName(categoryName) === undefined)
{
incomeHandler.add(new CategorySum(categoryName, transaction.category.color));
}
if(expenditureHandler.getByCategoryName(categoryName) === undefined)
{
expenditureHandler.add(new CategorySum(categoryName, transaction.category.color));
}
var amount = transaction.amount;
if(amount > 0)
{
incomeHandler.getByCategoryName(categoryName).add(amount);
}
else
{
expenditureHandler.getByCategoryName(categoryName).add(Math.abs(amount));
}
}
// Prepare your chart settings here (mandatory)
var plotlyData = addSeries(incomeHandler, 0);
plotlyData = plotlyData.concat(addSeries(expenditureHandler, 1));
// Add your Plotly layout settings here (optional)
var plotlyLayout = {
title: {
text: localizedTitle
},
hovermode: 'closest', // show hover popup only for hovered item
grid: {rows: 1, columns: 2},
annotations: [
{
font: {
size: 20
},
xref: "paper",
yref: "paper",
xanchor: "center",
yanchor: "top",
showarrow: false,
text: localizedData['label2'],
x: 0.25,
y: 0
},
{
font: {
size: 20
},
xref: "paper",
yref: "paper",
xanchor: "center",
yanchor: "top",
showarrow: false,
text: localizedData['label1'],
x: 0.75,
y: 0
}
],
};
// Add your Plotly configuration settings here (optional)
var plotlyConfig = {
showSendToCloud: false,
displaylogo: false,
showLink: false,
responsive: true,
displayModeBar: true,
toImageButtonOptions: {
format: 'png',
filename: 'BudgetMaster_chart_export',
height: 1080,
width: 1920,
}
};
// Don't touch this line
Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig);
function addSeries(sumHandler, column)
{
var plotlyData = [];
var total = sumHandler.getTotalSum();
var sums = sumHandler.getSumsSorted();
var values = sums.map(item => item.amount);
var colors = sums.map(item => item.color);
var labels = sums.map(item => item.categoryName);
var hoverTexts = sums.map((item, index) => `
${labels[index]}<br>
${(values[index]/100).toFixed(1) + ' ' + localizedCurrency}<br>
${(values[index] / total * 100).toFixed(1)}%
`);
var borders = sums.map(item => {
if(item.color.toUpperCase().startsWith('#FFFFFF'))
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
{
return 1;
}
return 0;
});
plotlyData.push({
values: values,
labels: labels,
type: 'pie',
text: hoverTexts,
hoverinfo: 'text',
textinfo: 'none',
marker: {
colors: colors,
line: {
color: '#212121',
width: borders
}
},
domain: {
row: 0,
column: column,
},
});
return plotlyData;
}