Better frontend code and charts.

This commit is contained in:
James Cole
2020-07-05 21:03:35 +02:00
parent a56cefda7d
commit 4271dc1638
22 changed files with 202 additions and 299 deletions

View File

@@ -41,7 +41,56 @@
return this.newDataSet;
},
colorizeData(dataSet) {
colorizeBarData(dataSet) {
this.dataSet = dataSet;
this.newDataSet = {
count: 0,
labels: [],
datasets: []
};
// colors
let colourSet = [
[53, 124, 165],
[0, 141, 76], // green
[219, 139, 11],
[202, 25, 90], // paars rood-ish #CA195A
[85, 82, 153],
[66, 133, 244],
[219, 68, 55], // red #DB4437
[244, 180, 0],
[15, 157, 88],
[171, 71, 188],
[0, 172, 193],
[255, 112, 67],
[158, 157, 36],
[92, 107, 192],
[240, 98, 146],
[0, 121, 107],
[194, 24, 91]
];
let fillColors = [];
//let strokePointHighColors = [];
for (let i = 0; i < colourSet.length; i++) {
fillColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.5)");
//strokePointHighColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.9)");
}
this.newDataSet.labels = this.dataSet.labels;
this.newDataSet.count = this.dataSet.count;
for (let setKey in this.dataSet.datasets) {
if (this.dataSet.datasets.hasOwnProperty(setKey)) {
var dataset = this.dataSet.datasets[setKey];
dataset.fill = false;
dataset.backgroundColor = dataset.borderColor = fillColors[setKey];
this.newDataSet.datasets.push(dataset);
}
}
return this.newDataSet;
},
colorizeLineData(dataSet) {
this.dataSet = dataSet;
this.newDataSet = {
count: 0,

View File

@@ -24,6 +24,7 @@
<script>
import FormatLabel from "../charts/FormatLabel";
export default {
name: "DefaultBarOptions",
@@ -31,55 +32,23 @@
return {}
},
methods: {
/**
* Takes a string phrase and breaks it into separate phrases no bigger than 'maxwidth', breaks are made at complete words.
* https://stackoverflow.com/questions/21409717/chart-js-and-long-labels
*
* @param str
* @param maxwidth
* @returns {Array}
*/
formatLabel(str, maxwidth) {
var sections = [];
str = String(str);
var words = str.split(" ");
var temp = "";
words.forEach(function (item, index) {
if (temp.length > 0) {
var concat = temp + ' ' + item;
if (concat.length > maxwidth) {
sections.push(temp);
temp = "";
} else {
if (index === (words.length - 1)) {
sections.push(concat);
return;
} else {
temp = concat;
return;
}
}
}
if (index === (words.length - 1)) {
sections.push(item);
return;
}
if (item.length < maxwidth) {
temp = item;
} else {
sections.push(item);
}
});
return sections;
},
getDefaultOptions() {
return {
type: 'bar',
layout: {
padding: {
left: 50,
right: 50,
top: 0,
bottom: 0
},
},
stacked: true,
elements: {
line: {
cubicInterpolationMode: 'monotone'
}
},
legend: {
display: false,
},
@@ -88,11 +57,6 @@
},
responsive: true,
maintainAspectRatio: false,
elements: {
line: {
cubicInterpolationMode: 'monotone'
}
},
scales: {
xAxes: [
{
@@ -103,23 +67,26 @@
ticks: {
// break ticks when too long.
callback: function (value, index, values) {
//return this.formatLabel(value, 20);
return value;
return FormatLabel.methods.formatLabel(value, 20);
//return value;
}
}
}
],
yAxes: [{
stacked: false,
display: true,
drawOnChartArea: false,
offset: true,
beginAtZero: true,
ticks: {
callback: function (tickValue) {
"use strict";
let currencyCode = this.chart.data.datasets[0].currency_code ? this.chart.data.datasets[0].currency_code : 'EUR';
return new Intl.NumberFormat(window.localeValue, {style: 'currency', currency: currencyCode}).format(tickValue);
},
beginAtZero: true
}
}
}]
},
tooltips: {
@@ -128,8 +95,10 @@
label: function (tooltipItem, data) {
"use strict";
let currencyCode = data.datasets[tooltipItem.datasetIndex].currency_code ? data.datasets[tooltipItem.datasetIndex].currency_code : 'EUR';
let nrString =
new Intl.NumberFormat(window.localeValue, {style: 'currency', currency: currencyCode}).format(tooltipItem.yLabel)
let nrString = new Intl.NumberFormat(window.localeValue, {
style: 'currency',
currency: currencyCode
}).format(tooltipItem.yLabel);
return data.datasets[tooltipItem.datasetIndex].label + ': ' + nrString;
}

View File

@@ -0,0 +1,73 @@
<!--
- FormatLabel.vue
- Copyright (c) 2020 james@firefly-iii.org
-
- This file is part of Firefly III (https://github.com/firefly-iii).
-
- This program 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.
-
- This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script>
export default {
name: "FormatLabel",
methods: {
/**
* Takes a string phrase and breaks it into separate phrases no bigger than 'maxwidth', breaks are made at complete words.
* https://stackoverflow.com/questions/21409717/chart-js-and-long-labels
*
* @param str
* @param maxwidth
* @returns {Array}
*/
formatLabel(str, maxwidth) {
var sections = [];
str = String(str);
var words = str.split(" ");
var temp = "";
words.forEach(function (item, index) {
if (temp.length > 0) {
var concat = temp + ' ' + item;
if (concat.length > maxwidth) {
sections.push(temp);
temp = "";
} else {
if (index === (words.length - 1)) {
sections.push(concat);
return;
} else {
temp = concat;
return;
}
}
}
if (index === (words.length - 1)) {
sections.push(item);
return;
}
if (item.length < maxwidth) {
temp = item;
} else {
sections.push(item);
}
});
return sections;
},
}
}
</script>

View File

@@ -25,7 +25,7 @@
</div>
<div class="card-body">
<div>
<main-account-chart v-if="loaded" :styles="chartStyles" :options="chartOptions" :chart-data="chartData"></main-account-chart>
<canvas id="mainAccountsChart" style="min-height: 400px; height: 400px; max-height: 400px; max-width: 100%;"></canvas>
</div>
</div>
<div class="card-footer">
@@ -35,45 +35,24 @@
</template>
<script>
import MainAccountChart from "./MainAccountChart";
import DataConverter from "../charts/DataConverter";
import DefaultLineOptions from "../charts/DefaultLineOptions";
export default {
components: {
MainAccountChart
},
data() {
return {
chartData: null,
loaded: false,
chartOptions: null,
}
},
name: "MainAccount",
mounted() {
this.chartOptions = DefaultLineOptions.methods.getDefaultOptions();
this.loaded = false;
axios.get('./api/v1/chart/account/overview?start=' + window.sessionStart + '&end=' + window.sessionEnd)
.then(response => {
this.chartData = DataConverter.methods.convertChart(response.data);
this.chartData = DataConverter.methods.colorizeData(this.chartData);
this.chartData = DataConverter.methods.convertLabelsToDate(this.chartData);
this.loaded = true
let chartData = DataConverter.methods.convertChart(response.data);
chartData = DataConverter.methods.colorizeLineData(chartData);
let lineChartCanvas = $('#mainAccountsChart').get(0).getContext('2d');
new Chart(lineChartCanvas, {
type: 'line',
data: chartData,
options: DefaultLineOptions.methods.getDefaultOptions()
});
});
},
methods: {
},
computed: {
chartStyles() {
return {
height: '400px',
'max-height': '400px',
position: 'relative',
display: 'block',
}
}
},
name: "MainAccount"
}
</script>

View File

@@ -24,8 +24,8 @@
<h3 class="card-title">{{ $t('firefly.budgets') }}</h3>
</div>
<div class="card-body">
<div>
<main-budget-chart v-if="loaded" :styles="chartStyles" :options="chartOptions" :chart-data="chartData"></main-budget-chart>
<div style="position: relative;">
<canvas id="mainBudgetChart" style="min-height: 400px; height: 400px; max-height: 400px; max-width: 100%;"></canvas>
</div>
</div>
<div class="card-footer">
@@ -35,45 +35,22 @@
</template>
<script>
import MainBudgetChart from "./MainBudgetChart";
import DefaultBarOptions from "../charts/DefaultBarOptions";
import DataConverter from "../charts/DataConverter";
export default {
name: "MainBudget",
components: {
MainBudgetChart
},
data() {
return {
chartData: null,
loaded: false,
chartOptions: null,
}
},
mounted() {
this.chartOptions = DefaultBarOptions.methods.getDefaultOptions();
this.loaded = false;
axios.get('./api/v1/chart/budget/overview?start=' + window.sessionStart + '&end=' + window.sessionEnd)
.then(response => {
this.chartData = response.data;
//this.chartData = DataConverter.methods.colorizeData(this.chartData);
this.chartData = DataConverter.methods.convertChart(this.chartData);
this.loaded = true
let chartData = DataConverter.methods.convertChart(response.data);
let stackedBarChartCanvas = $('#mainBudgetChart').get(0).getContext('2d')
new Chart(stackedBarChartCanvas, {
type: 'bar',
data: chartData,
options: DefaultBarOptions.methods.getDefaultOptions()
});
});
},
methods: {
},
computed: {
chartStyles() {
return {
height: '400px',
'max-height': '400px',
position: 'relative',
display: 'block',
}
}
},
}
</script>

View File

@@ -1,34 +0,0 @@
<!--
- MainBudgetChart.vue
- Copyright (c) 2020 james@firefly-iii.org
-
- This file is part of Firefly III (https://github.com/firefly-iii).
-
- This program 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.
-
- This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script>
import {Line} from 'vue-chartjs'
export default {
name: "MainBudgetChart",
extends: Line,
props: ['options', 'chartData'],
mounted() {
this.renderChart(this.chartData, this.options)
}
}
</script>

View File

@@ -25,7 +25,7 @@
</div>
<div class="card-body">
<div>
<main-category-chart v-if="loaded" :styles="chartStyles" :options="chartOptions" :chart-data="chartData"></main-category-chart>
<canvas id="mainCategoryChart" style="min-height: 400px; height: 400px; max-height: 400px; max-width: 100%;"></canvas>
</div>
</div>
<div class="card-footer">
@@ -35,44 +35,23 @@
</template>
<script>
import MainCategoryChart from "./MainCategoryChart";
import DefaultBarOptions from "../charts/DefaultBarOptions";
import DataConverter from "../charts/DataConverter";
export default {
name: "MainCategory",
components: {
MainCategoryChart
},
data() {
return {
chartData: null,
loaded: false,
chartOptions: null,
}
},
mounted() {
this.chartOptions = DefaultBarOptions.methods.getDefaultOptions();
this.loaded = false;
axios.get('./api/v1/chart/category/overview?start=' + window.sessionStart + '&end=' + window.sessionEnd)
.then(response => {
this.chartData = response.data;
this.chartData = DataConverter.methods.convertChart(this.chartData);
this.loaded = true
let chartData = DataConverter.methods.convertChart(response.data);
chartData = DataConverter.methods.colorizeLineData(chartData);
let stackedBarChartCanvas = $('#mainCategoryChart').get(0).getContext('2d')
new Chart(stackedBarChartCanvas, {
type: 'bar',
data: chartData,
options: DefaultBarOptions.methods.getDefaultOptions()
});
});
},
methods: {
},
computed: {
chartStyles() {
return {
height: '400px',
'max-height': '400px',
position: 'relative',
display: 'block',
}
}
},
}
</script>

View File

@@ -1,36 +0,0 @@
<!--
- MainCategoryChart.vue
- Copyright (c) 2020 james@firefly-iii.org
-
- This file is part of Firefly III (https://github.com/firefly-iii).
-
- This program 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.
-
- This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script>
import {Line} from "vue-chartjs";
export default {
name: "MainCategoryChart",
extends: Line,
props: ['options', 'chartData'],
mounted() {
this.renderChart(this.chartData, this.options)
}
}
</script>
<style scoped>
</style>

View File

@@ -26,54 +26,34 @@
</div>
<div class="card-body">
<div>
<main-debit-chart v-if="loaded" :styles="chartStyles" :options="chartOptions" :chart-data="chartData"></main-debit-chart>
<canvas id="mainDebitChart" style="min-height: 400px; height: 400px; max-height: 400px; max-width: 100%;"></canvas>
</div>
</div>
<div class="card-footer">
<a href="./accounts/expense" class="btn btn-default button-sm"><i class="far fa-money-bill-alt"></i> {{ $t('firefly.go_to_expenses') }}</a>
<a href="./transactions/withdrawals" class="btn btn-default button-sm"><i class="far fa-money-bill-alt"></i> {{ $t('firefly.go_to_expenses') }}</a>
</div>
</div>
</template>
<script>
import MainDebitChart from "./MainDebitChart";
import DefaultBarOptions from "../charts/DefaultBarOptions";
import DataConverter from "../charts/DataConverter";
export default {
name: "MainDebit",
components: {
MainDebitChart
},
data() {
return {
chartData: null,
loaded: false,
chartOptions: null,
}
},
mounted() {
this.chartOptions = DefaultBarOptions.methods.getDefaultOptions();
this.loaded = false;
axios.get('./api/v1/chart/account/expense?start=' + window.sessionStart + '&end=' + window.sessionEnd)
.then(response => {
this.chartData = response.data;
this.chartData = DataConverter.methods.convertChart(this.chartData);
this.loaded = true
let chartData = DataConverter.methods.convertChart(response.data);
chartData = DataConverter.methods.colorizeLineData(chartData);
let stackedBarChartCanvas = $('#mainDebitChart').get(0).getContext('2d')
new Chart(stackedBarChartCanvas, {
type: 'bar',
data: chartData,
options: DefaultBarOptions.methods.getDefaultOptions()
});
});
},
methods: {
},
computed: {
chartStyles() {
return {
height: '400px',
'max-height': '400px',
position: 'relative',
display: 'block',
}
}
},
}
</script>

View File

@@ -1,35 +0,0 @@
<!--
- MainDebitChart.vue
- Copyright (c) 2020 james@firefly-iii.org
-
- This file is part of Firefly III (https://github.com/firefly-iii).
-
- This program 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.
-
- This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script>
import {Line} from 'vue-chartjs'
export default {
name: "MainDebitChart",
extends: Line,
props: ['options', 'chartData'],
mounted() {
// this.chartData is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.chartData, this.options)
}
}
</script>