From dffddfda189a5f24a7ed6c99d530ba597da03134 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 8 Aug 2023 14:11:04 +0200 Subject: [PATCH] Expand layout --- package-lock.json | 9 + package.json | 1 + resources/assets/v2/api/v1/accounts/get.js | 3 +- .../assets/v2/api/v2/model/transaction/get.js | 34 +++ resources/assets/v2/dashboard.js | 5 +- .../assets/v2/pages/dashboard/accounts.js | 117 ++++------- .../assets/v2/pages/dashboard/budgets.js | 197 +++--------------- .../assets/v2/pages/dashboard/categories.js | 148 ++++--------- resources/assets/v2/pages/dashboard/sankey.js | 155 ++++++++++++++ resources/assets/v2/store/Basic.js | 2 - resources/assets/v2/store/set-variable.js | 2 - .../v2/support/default-chart-settings.js | 13 +- resources/views/v2/index.blade.php | 9 +- 13 files changed, 340 insertions(+), 355 deletions(-) create mode 100644 resources/assets/v2/api/v2/model/transaction/get.js create mode 100644 resources/assets/v2/pages/dashboard/sankey.js diff --git a/package-lock.json b/package-lock.json index 0069c717a6..e22c6afd9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "alpinejs": "^3.12.3", "bootstrap": "^5.3.0", "chart.js": "^4.3.3", + "chartjs-chart-sankey": "^0.12.0", "date-fns": "^2.30.0", "store": "^2.0.12" }, @@ -507,6 +508,14 @@ "pnpm": ">=7" } }, + "node_modules/chartjs-chart-sankey": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/chartjs-chart-sankey/-/chartjs-chart-sankey-0.12.0.tgz", + "integrity": "sha512-2f0YfDWNTTDqztVALlD2YMdSbpmjxdxHpcpKgBi9cUq3IPWBvHb58h4gIa7GjsYVjMLwX6gusDXgxlh9PMKkkA==", + "peerDependencies": { + "chart.js": ">=3.3.0" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", diff --git a/package.json b/package.json index 075a651fc8..a6bae62222 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "alpinejs": "^3.12.3", "bootstrap": "^5.3.0", "chart.js": "^4.3.3", + "chartjs-chart-sankey": "^0.12.0", "date-fns": "^2.30.0", "store": "^2.0.12" } diff --git a/resources/assets/v2/api/v1/accounts/get.js b/resources/assets/v2/api/v1/accounts/get.js index 11efebc6f8..719dcd0195 100644 --- a/resources/assets/v2/api/v1/accounts/get.js +++ b/resources/assets/v2/api/v1/accounts/get.js @@ -19,6 +19,7 @@ */ import {api} from "../../../boot/axios"; +import format from "date-fns/format"; export default class Get { @@ -29,7 +30,7 @@ export default class Get { * @returns {Promise>} */ get(identifier, date) { - let params = {date: date}; + let params = {date: format(date, 'y-MM-d').slice(0, 10)}; if (!date) { return api.get('/api/v1/accounts/' + identifier); } diff --git a/resources/assets/v2/api/v2/model/transaction/get.js b/resources/assets/v2/api/v2/model/transaction/get.js new file mode 100644 index 0000000000..ce8af4e7bd --- /dev/null +++ b/resources/assets/v2/api/v2/model/transaction/get.js @@ -0,0 +1,34 @@ +/* + * get.js + * Copyright (c) 2023 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 . + */ + + +import {api} from "../../../../boot/axios"; + +export default class Get { + + /** + * + * @param params + * @returns {Promise>} + */ + get(params) { + return api.get('/api/v1/transactions', {params: params}); + } +} diff --git a/resources/assets/v2/dashboard.js b/resources/assets/v2/dashboard.js index 16f46ad5c0..15d26e592e 100644 --- a/resources/assets/v2/dashboard.js +++ b/resources/assets/v2/dashboard.js @@ -24,12 +24,13 @@ import boxes from './pages/dashboard/boxes.js'; import accounts from './pages/dashboard/accounts.js'; import budgets from './pages/dashboard/budgets.js'; import categories from './pages/dashboard/categories.js'; +import sankey from './pages/dashboard/sankey.js'; -const comps = {dates, boxes, accounts, budgets, categories}; +const comps = {dates, boxes, accounts, budgets, categories, sankey}; function loadPage(comps) { Object.keys(comps).forEach(comp => { - console.log(`Loading ${comp}`); + console.log(`Loading page component "${comp}"`); let data = comps[comp](); Alpine.data(comp, () => data); }); diff --git a/resources/assets/v2/pages/dashboard/accounts.js b/resources/assets/v2/pages/dashboard/accounts.js index 0f47135f01..d64d9f81a4 100644 --- a/resources/assets/v2/pages/dashboard/accounts.js +++ b/resources/assets/v2/pages/dashboard/accounts.js @@ -22,129 +22,97 @@ import {getVariable} from "../../store/get-variable.js"; import {setVariable} from "../../store/set-variable.js"; import Dashboard from "../../api/v2/chart/account/dashboard.js"; -import formatLocal from "../../util/format.js"; -import {format} from "date-fns"; import formatMoney from "../../util/format-money.js"; import Get from "../../api/v1/accounts/get.js"; +import Chart from "chart.js/auto"; // this is very ugly, but I have no better ideas at the moment to save the currency info // for each series. -window.currencies = []; +let currencies = []; +let chart = null; +let chartData = null; export default () => ({ loading: false, loadingAccounts: false, accountList: [], autoConversion: false, - chart: null, - chartData: null, chartOptions: null, switchAutoConversion() { this.autoConversion = !this.autoConversion; setVariable('autoConversion', this.autoConversion); - this.loadChart(); }, getFreshData() { const dashboard = new Dashboard(); dashboard.dashboard(new Date(window.store.get('start')), new Date(window.store.get('end')), null).then((response) => { this.chartData = response.data; - this.generateOptions(this.chartData); - this.drawChart(); + this.drawChart(this.generateOptions(this.chartData)); }); }, generateOptions(data) { - window.currencies = []; + currencies = []; let options = { - legend: {show: false}, - chart: { - height: 400, - type: 'line' - }, - series: [], - settings: [], - xaxis: { - categories: [], - labels: { - formatter: function (value) { - if (undefined === value) { - return ''; - } - const date = new Date(value); - if (date instanceof Date && !isNaN(date)) { - return formatLocal(date, 'PP'); - } - console.error('Could not parse "' + value + '", return "".'); - return ':('; - } - } - }, - yaxis: { - labels: { - formatter: function (value, index) { - if (undefined === value) { - return value; - } - if (undefined === index) { - return value; - } - if (typeof index === 'object') { - index = index.seriesIndex; - } - //console.log(index); - let currencyCode = window.currencies[index] ?? 'EUR'; - return formatMoney(value, currencyCode); - } - } + type: 'line', + data: { + labels: [], + datasets: [] }, }; - // render data: + for (let i = 0; i < data.length; i++) { if (data.hasOwnProperty(i)) { let current = data[i]; - let entry = []; + let dataset = {}; let collection = []; + + // if index = 0, push all keys as labels: + if (0 === i) { + options.data.labels = Object.keys(current.entries); + } + dataset.label = current.label; + // use the "native" currency code and use the "native_entries" as array if (this.autoConversion) { - window.currencies.push(current.native_code); - collection = current.native_entries; + currencies.push(current.native_code); + collection = Object.values(current.native_entries); } if (!this.autoConversion) { - window.currencies.push(current.currency_code); - collection = current.entries; + currencies.push(current.currency_code); + collection = Object.values(current.entries); } + dataset.data = collection; for (const [ii, value] of Object.entries(collection)) { - entry.push({x: format(new Date(ii), 'yyyy-MM-dd'), y: parseFloat(value)}); + //entry.push({x: format(new Date(ii), 'yyyy-MM-dd'), y: parseFloat(value)}); } - options.series.push({name: current.label, data: entry}); + options.data.datasets.push(dataset); + //options.series.push({name: current.label, data: entry}); } } - this.chartOptions = options; + + return options; }, loadChart() { if (true === this.loading) { return; } this.loading = true; - if (null === this.chartData) { + if (null === chartData) { this.getFreshData(); + return; } - if (null !== this.chartData) { - this.generateOptions(this.chartData); - this.drawChart(); - } - + this.drawChart(this.generateOptions(chartData)); this.loading = false; + }, - drawChart() { - if (null !== this.chart) { + drawChart(options) { + if (null !== chart) { // chart already in place, refresh: - this.chart.updateOptions(this.chartOptions); - } - if (null === this.chart) { - //this.chart = new ApexCharts(document.querySelector("#account-chart"), this.chartOptions); - //this.chart.render(); + chart.data.datasets = options.data.datasets; + chart.update(); + return; } + chart = new Chart(document.querySelector("#account-chart"), options); }, loadAccounts() { if (true === this.loadingAccounts) { @@ -211,13 +179,12 @@ export default () => ({ this.autoConversion = values[1]; // main dashboard chart: this.loadChart(); - // this.loadAccounts(); + this.loadAccounts(); }); window.store.observe('end', () => { - this.chartData = null; - this.expenseAccountChart = null; + chartData = null; // main dashboard chart: - // this.loadChart(); + this.loadChart(); this.loadAccounts(); }); }, diff --git a/resources/assets/v2/pages/dashboard/budgets.js b/resources/assets/v2/pages/dashboard/budgets.js index 3001d2d757..5c3d82e3b9 100644 --- a/resources/assets/v2/pages/dashboard/budgets.js +++ b/resources/assets/v2/pages/dashboard/budgets.js @@ -22,60 +22,51 @@ import Dashboard from "../../api/v2/chart/budget/dashboard.js"; // todo optimize import Chart from 'chart.js/auto'; import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; +import formatMoney from "../../util/format-money.js"; + +let currencies = []; +let chart = null; +let chartData = null; -window.budgetCurrencies = []; export default () => ({ loading: false, - chart: null, autoConversion: false, - chartData: null, - chartOptions: null, loadChart() { if (true === this.loading) { return; } this.loading = true; - if (null === this.chartData) { - this.getFreshData(); - } - if (null !== this.chartData) { - this.generateOptions(this.chartData); - this.drawChart(); + + if (null !== chartData) { + this.drawChart(this.generateOptions(chartData)); this.loading = false; + return; } + this.getFreshData(); }, - drawChart() { - if (null !== this.chart) { - // chart already in place, refresh: - console.log('refresh'); - this.chart.data = this.chartOptions.data; - //this.chart.updateOptions(this.chartOptions); - } - if (null === this.chart) { - //this.chart = new ApexCharts(document.querySelector("#budget-chart"), this.chartOptions); - this.chart = new Chart(document.querySelector("#budget-chart"), this.chartOptions); - //this.chart.render(); + drawChart(options) { + if (null !== chart) { + chart.data.datasets = options.data.datasets; + chart.update(); + return; } + chart = new Chart(document.querySelector("#budget-chart"), options); }, getFreshData() { const dashboard = new Dashboard(); dashboard.dashboard(new Date(window.store.get('start')), new Date(window.store.get('end')), null).then((response) => { - this.chartData = response.data; - this.generateOptions(this.chartData); - this.drawChart(); + chartData = response.data; // save chart data for later. + this.drawChart(this.generateOptions(response.data)); this.loading = false; }); }, generateOptions(data) { - window.budgetCurrencies = []; + currencies = []; let options = getDefaultChartSettings('column'); options.options.locale = window.store.get('locale').replace('_', '-'); options.options.plugins = { tooltip: { callbacks: { - // tooltip: function (context) { - // //console.log(context); - // }, title: function (context) { return context.label; }, @@ -85,12 +76,7 @@ export default () => ({ if (label) { label += ': '; } - //console.log('label'); - //console.log(context.label + ' X'); - //return context.label + ' X'; - // console.log(context); - return label + ' ' + context.parsed.x; - // return label + ' ' + formatMoney(context.parsed.y, window.budgetCurrencies[context.parsed.x] ?? 'EUR'); + return label + ' ' + formatMoney(context.parsed.y, currencies[context.parsed.x] ?? 'EUR'); } } } @@ -126,7 +112,7 @@ export default () => ({ let label = current.label + ' (' + current.currency_code + ')'; options.data.labels.push(label); if (this.autoConversion) { - window.budgetCurrencies.push(current.native_code); + currencies.push(current.native_code); // series 0: spent options.data.datasets[0].data.push(parseFloat(current.native_entries.spent) * -1); // series 1: left @@ -135,7 +121,7 @@ export default () => ({ options.data.datasets[2].data.push(parseFloat(current.native_entries.overspent)); } if (!this.autoConversion) { - window.budgetCurrencies.push(current.currency_code); + currencies.push(current.currency_code); // series 0: spent options.data.datasets[0].data.push(parseFloat(current.entries.spent) * -1); // series 1: left @@ -143,147 +129,30 @@ export default () => ({ // series 2: overspent options.data.datasets[2].data.push(parseFloat(current.entries.overspent)); } - // console.log('Currencies'); - // console.log(window.budgetCurrencies); - // } } - - // options = { - // legend: {show: false}, - // series: [{ - // name: 'Spent', - // data: [] - // }, { - // name: 'Left', - // data: [] - // }, { - // name: 'Overspent', - // data: [] - // }], - // chart: { - // type: 'bar', - // height: 400, - // stacked: true, - // toolbar: {tools: {zoom: false, download: false, pan: false}}, - // zoom: { - // enabled: true - // } - // }, - // responsive: [{ - // breakpoint: 480, - // options: { - // legend: { - // position: 'bottom', - // offsetX: -10, - // offsetY: 0 - // } - // } - // }], - // plotOptions: { - // bar: { - // horizontal: false, - // borderRadius: 10, - // dataLabels: { - // total: { - // enabled: true, - // // style: { - // // fontSize: '13px', - // // fontWeight: 900 - // // }, - // formatter: function (val, opt) { - // let index = 0; - // if (typeof opt === 'object') { - // index = opt.dataPointIndex; // this is the "category name + currency" index - // } - // let currencyCode = window.budgetCurrencies[index] ?? 'EUR'; - // return formatMoney(val, currencyCode); - // } - // } - // } - // }, - // }, - // yaxis: { - // labels: { - // formatter: function (value, index) { - // if (undefined === value) { - // return value; - // } - // if (undefined === index) { - // return value; - // } - // if (typeof index === 'object') { - // index = index.dataPointIndex; // this is the "category name + currency" index - // } - // let currencyCode = window.budgetCurrencies[index] ?? 'EUR'; - // return formatMoney(value, currencyCode); - // } - // } - // }, - // xaxis: { - // categories: [] - // }, - // fill: { - // opacity: 0.8 - // }, - // dataLabels: { - // formatter: function (val, opt) { - // let index = 0; - // if (typeof opt === 'object') { - // index = opt.dataPointIndex; // this is the "category name + currency" index - // } - // let currencyCode = window.budgetCurrencies[index] ?? 'EUR'; - // return formatMoney(val, currencyCode); - // }, - // } - // }; - - - // for (const i in data) { - // if (data.hasOwnProperty(i)) { - // let current = data[i]; - // // convert to EUR yes no? - // let label = current.label + ' (' + current.currency_code + ')'; - // options.xaxis.categories.push(label); - // if (this.autoConversion) { - // window.budgetCurrencies.push(current.native_code); - // - // // series 0: spent - // options.series[0].data.push(parseFloat(current.native_entries.spent) * -1); - // // series 1: left - // options.series[1].data.push(parseFloat(current.native_entries.left)); - // // series 2: overspent - // options.series[2].data.push(parseFloat(current.native_entries.overspent)); - // } - // if (!this.autoConversion) { - // window.budgetCurrencies.push(current.currency_code); - // // series 0: spent - // options.series[0].data.push(parseFloat(current.entries.spent) * -1); - // // series 1: left - // options.series[1].data.push(parseFloat(current.entries.left)); - // // series 2: overspent - // options.series[2].data.push(parseFloat(current.entries.overspent)); - // } - // - // } - // } - this.chartOptions = options; + return options; }, init() { Promise.all([getVariable('autoConversion', false),]).then((values) => { this.autoConversion = values[0]; - this.loadChart(); + if (false === this.loading) { + this.loadChart(); + } }); - // todo the charts don't need to reload from server if the autoConversion value changes. window.store.observe('end', () => { - this.chartData = null; - this.loadChart(); + if (false === this.loading) { + this.chartData = null; + this.loadChart(); + } }); window.store.observe('autoConversion', (newValue) => { this.autoConversion = newValue; - this.loadChart(); + if (false === this.loading) { + this.loadChart(); + } }); }, diff --git a/resources/assets/v2/pages/dashboard/categories.js b/resources/assets/v2/pages/dashboard/categories.js index 7cd71fb14e..4e1e9fb049 100644 --- a/resources/assets/v2/pages/dashboard/categories.js +++ b/resources/assets/v2/pages/dashboard/categories.js @@ -21,79 +21,22 @@ import {getVariable} from "../../store/get-variable.js"; import Dashboard from "../../api/v2/chart/category/dashboard.js"; //import ApexCharts from "apexcharts"; import formatMoney from "../../util/format-money.js"; +import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; +import Chart from "chart.js/auto"; + +let currencies = []; + +let chart = null; +let chartData = null; -window.categoryCurrencies = []; export default () => ({ loading: false, - chart: null, autoConversion: false, - chartData: null, - chartOptions: null, generateOptions(data) { - window.categoryCurrencies = []; - let options = { - series: [], - chart: { - type: 'bar', - height: 350 - }, - plotOptions: { - bar: { - horizontal: false, - columnWidth: '55%', - endingShape: 'rounded' - }, - }, - dataLabels: { - enabled: false - }, - stroke: { - show: true, - width: 2, - colors: ['transparent'] - }, - xaxis: { - categories: [], - }, - yaxis: { - labels: { - formatter: function (value, index) { - if (undefined === value) { - return value; - } - if (undefined === index) { - return value; - } - if (typeof index === 'object') { - index = index.dataPointIndex; // this is the "category name + currency" index - } - let currencyCode = window.budgetCurrencies[index] ?? 'EUR'; - return formatMoney(value, currencyCode); - } - } - }, - fill: { - opacity: 1 - }, - tooltip: { - y: { - formatter: function (value, index) { - if (undefined === value) { - return value; - } - if (undefined === index) { - return value; - } - if (typeof index === 'object') { - index = index.seriesIndex; // this is the currency index. - } - let currencyCode = window.categoryCurrencies[index] ?? 'EUR'; - return formatMoney(value, currencyCode); - } - } - } - }; - // first, collect all currencies and use them as series. + currencies = []; + let options = getDefaultChartSettings('column'); + + // first, create "series" per currency. let series = {}; for (const i in data) { if (data.hasOwnProperty(i)) { @@ -109,11 +52,12 @@ export default () => ({ name: code, data: {}, }; - window.categoryCurrencies.push(code); + currencies.push(code); } } } - // loop data again to add amounts. + + // loop data again to add amounts to each series. for (const i in data) { if (data.hasOwnProperty(i)) { let current = data[i]; @@ -147,42 +91,40 @@ export default () => ({ } } // add label to x-axis, not unimportant. - if (!options.xaxis.categories.includes(current.label)) { - options.xaxis.categories.push(current.label); + if (!options.data.labels.includes(current.label)) { + options.data.labels.push(current.label); } } } - // loop the series and create Apex-compatible data sets. + // loop the series and create ChartJS-compatible data sets. for (const i in series) { - let current = { - name: i, + let dataset = { + label: i, data: [], } for (const ii in series[i].data) { - current.data.push(series[i].data[ii]); + dataset.data.push(series[i].data[ii]); } - options.series.push(current); + options.data.datasets.push(dataset); } - this.chartOptions = options; + + return options; }, - drawChart() { - if (null !== this.chart) { - // chart already in place, refresh: - this.chart.updateOptions(this.chartOptions); + drawChart(options) { + if (null !== chart) { + chart.data.datasets = options.data.datasets; + chart.update(); + return; } - if (null === this.chart) { - this.chart = new ApexCharts(document.querySelector("#category-chart"), this.chartOptions); - this.chart.render(); - } - this.loading = false; + chart = new Chart(document.querySelector("#category-chart"), options); }, getFreshData() { const dashboard = new Dashboard(); dashboard.dashboard(new Date(window.store.get('start')), new Date(window.store.get('end')), null).then((response) => { - this.chartData = response.data; - this.generateOptions(this.chartData); - this.drawChart(); + chartData = response.data; // save chart data for later. + this.drawChart(this.generateOptions(response.data)); + this.loading = false; }); }, @@ -191,28 +133,26 @@ export default () => ({ return; } this.loading = true; - if (null === this.chartData) { - this.getFreshData(); - } - if (null !== this.chartData) { - this.generateOptions(this.chartData); - this.drawChart(); - } - this.loading = false; + if (null !== chartData) { + this.drawChart(this.generateOptions(chartData)); + this.loading = false; + return; + } + this.getFreshData(); }, init() { Promise.all([getVariable('autoConversion', false),]).then((values) => { - // this.autoConversion = values[0]; - // this.loadChart(); + this.autoConversion = values[0]; + this.loadChart(); }); window.store.observe('end', () => { - // this.chartData = null; - // this.loadChart(); + this.chartData = null; + this.loadChart(); }); window.store.observe('autoConversion', (newValue) => { - // this.autoConversion = newValue; - // this.loadChart(); + this.autoConversion = newValue; + this.loadChart(); }); }, diff --git a/resources/assets/v2/pages/dashboard/sankey.js b/resources/assets/v2/pages/dashboard/sankey.js new file mode 100644 index 0000000000..2e0861faab --- /dev/null +++ b/resources/assets/v2/pages/dashboard/sankey.js @@ -0,0 +1,155 @@ +/* + * budgets.js + * Copyright (c) 2023 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 . + */ +import {getVariable} from "../../store/get-variable.js"; +import Get from "../../api/v2/model/transaction/get.js"; +import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; +import Chart from "chart.js/auto"; +import {Flow, SankeyController} from 'chartjs-chart-sankey'; + +Chart.register(SankeyController, Flow); + +let currencies = []; + +let chart = null; +let transactions = []; + +export default () => ({ + loading: false, + autoConversion: false, + generateOptions(data) { + currencies = []; + console.log('generate options'); + let options = getDefaultChartSettings('sankey'); + + // temp code for first sankey + const colors = { + a: 'red', + b: 'green', + c: 'blue', + d: 'gray' + }; + + const getColor = (key) => colors[key]; + // end of temp code for first sankey + let dataSet = + // sankey chart has one data set. + { + label: 'My sankey', + data: [ + {from: 'a', to: 'b', flow: 10}, + {from: 'a', to: 'c', flow: 5}, + {from: 'b', to: 'c', flow: 10}, + {from: 'd', to: 'c', flow: 7} + ], + colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from), + colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to), + colorMode: 'gradient', // or 'from' or 'to' + /* optional labels */ + labels: { + a: 'Label A', + b: 'Label B', + c: 'Label C', + d: 'Label D' + }, + /* optional priority */ + priority: { + b: 1, + d: 0 + }, + /* optional column overrides */ + column: { + d: 1 + }, + size: 'max', // or 'min' if flow overlap is preferred + }; + options.data.datasets.push(dataSet); + + + return options; + }, + drawChart(options) { + if (null !== chart) { + chart.data.datasets = options.data.datasets; + chart.update(); + return; + } + chart = new Chart(document.querySelector("#sankey-chart"), options); + + }, + getFreshData() { + let params = { + start: window.store.get('start').slice(0, 10), + end: window.store.get('end').slice(0, 10), + type: 'withdrawal,deposit', + page: 1 + }; + this.downloadTransactions(params); + }, + downloadTransactions(params) { + console.log('Downloading page ' + params.page + '...'); + const getter = new Get(); + getter.get(params).then((response) => { + transactions = [...transactions, ...response.data.data]; + //this.drawChart(this.generateOptions(response.data)); + //this.loading = false; + if (parseInt(response.data.meta.pagination.total_pages) > params.page) { + // continue to next page. + params.page++; + this.downloadTransactions(params); + return; + } + // continue to next step. + console.log('Final page!'); + console.log(transactions); + }); + }, + + loadChart() { + if (true === this.loading) { + return; + } + this.loading = true; + + if (0 !== transactions.length) { + this.drawChart(this.generateOptions()); + this.loading = false; + return; + } + this.getFreshData(); + }, + init() { + transactions = []; + Promise.all([getVariable('autoConversion', false),]).then((values) => { + this.autoConversion = values[0]; + this.loadChart(); + }); + window.store.observe('end', () => { + this.transactions = []; + this.loadChart(); + }); + window.store.observe('autoConversion', (newValue) => { + this.autoConversion = newValue; + this.loadChart(); + }); + }, + +}); + + diff --git a/resources/assets/v2/store/Basic.js b/resources/assets/v2/store/Basic.js index 00fdf6416e..51f985a64f 100644 --- a/resources/assets/v2/store/Basic.js +++ b/resources/assets/v2/store/Basic.js @@ -33,7 +33,6 @@ const Basic = () => { * */ const init = () => { - console.log('Basic store init') this.loadVariable('viewRange') this.loadVariable('darkMode') this.loadVariable('language') @@ -89,7 +88,6 @@ const Basic = () => { const triggerReady = () => { this.count++; if (this.count === this.readyCount) { - console.log('Basic store is ready!') // trigger event: const event = new Event("BasicStoreReady"); document.dispatchEvent(event); diff --git a/resources/assets/v2/store/set-variable.js b/resources/assets/v2/store/set-variable.js index 0617c28db7..6b4a79f94f 100644 --- a/resources/assets/v2/store/set-variable.js +++ b/resources/assets/v2/store/set-variable.js @@ -36,13 +36,11 @@ export function setVariable(name, value = null) { // post to user preferences (because why not): let putter = new Put(); putter.put(name, value).then((response) => { - // console.log('Put in API'); }).catch(() => { // preference does not exist (yet). // POST it let poster = (new Post); poster.post(name, value).then((response) => { - // console.log('Post in API'); }); }); } diff --git a/resources/assets/v2/support/default-chart-settings.js b/resources/assets/v2/support/default-chart-settings.js index c42ca77328..9524905a80 100644 --- a/resources/assets/v2/support/default-chart-settings.js +++ b/resources/assets/v2/support/default-chart-settings.js @@ -19,10 +19,21 @@ */ function getDefaultChartSettings(type) { + if ('sankey' === type) { + return { + type: 'sankey', + data: { + datasets: [], + } + } + } if ('column' === type) { return { type: 'bar', - data: {}, + data: { + labels: [], + datasets: [], + }, options: { scales: { y: { diff --git a/resources/views/v2/index.blade.php b/resources/views/v2/index.blade.php index fc40ae2f11..8dc3020ba6 100644 --- a/resources/views/v2/index.blade.php +++ b/resources/views/v2/index.blade.php @@ -8,6 +8,7 @@
@include('partials.dashboard.boxes') +
@@ -20,7 +21,7 @@
-
+