diff --git a/package-lock.json b/package-lock.json index e22c6afd9f..cb9e3a60b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,10 @@ "alpinejs": "^3.12.3", "bootstrap": "^5.3.0", "chart.js": "^4.3.3", + "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.12.0", "date-fns": "^2.30.0", + "i18n-js": "^4.3.0", "store": "^2.0.12" }, "devDependencies": { @@ -458,6 +460,14 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -508,6 +518,15 @@ "pnpm": ">=7" } }, + "node_modules/chartjs-adapter-date-fns": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz", + "integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==", + "peerDependencies": { + "chart.js": ">=2.8.0", + "date-fns": ">=2.0.0" + } + }, "node_modules/chartjs-chart-sankey": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/chartjs-chart-sankey/-/chartjs-chart-sankey-0.12.0.tgz", @@ -688,6 +707,15 @@ "node": ">= 6" } }, + "node_modules/i18n-js": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-4.3.0.tgz", + "integrity": "sha512-PX93eT6WPV6Ym6mHtFKGDRZB0zwDX7HUPkgprjsZ28J6/Ohw1nvRYuM93or3pWv2VLxs6XfBf7X9Fc/YAZNEtQ==", + "dependencies": { + "bignumber.js": "*", + "make-plural": "*" + } + }, "node_modules/immutable": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz", @@ -752,6 +780,11 @@ "vite": "^3.0.0 || ^4.0.0" } }, + "node_modules/make-plural": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", + "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", diff --git a/package.json b/package.json index a6bae62222..f8060cfc2a 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,10 @@ "alpinejs": "^3.12.3", "bootstrap": "^5.3.0", "chart.js": "^4.3.3", + "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.12.0", "date-fns": "^2.30.0", + "i18n-js": "^4.3.0", "store": "^2.0.12" } } diff --git a/public/build/manifest.json b/public/build/manifest.json index 75bdd0bae7..8524716241 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -24,7 +24,7 @@ "src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2" }, "resources/assets/v2/dashboard.js": { - "file": "assets/dashboard-9172f6d4.js", + "file": "assets/dashboard-9c513338.js", "isEntry": true, "src": "resources/assets/v2/dashboard.js" }, diff --git a/resources/assets/v2/bootstrap.js b/resources/assets/v2/bootstrap.js index 1746b1dca5..32ec909c4f 100644 --- a/resources/assets/v2/bootstrap.js +++ b/resources/assets/v2/bootstrap.js @@ -35,7 +35,9 @@ Promise.all([ } // save local in window.__ something - window.__localeId__ = values[3]; + window.__localeId__ = values[2]; + store.set('language', values[3]); + store.set('locale', values[3]); const event = new Event('firefly-iii-bootstrapped'); document.dispatchEvent(event); diff --git a/resources/assets/v2/dashboard.js b/resources/assets/v2/dashboard.js index e972b8decb..a5e81b681c 100644 --- a/resources/assets/v2/dashboard.js +++ b/resources/assets/v2/dashboard.js @@ -28,7 +28,54 @@ import sankey from './pages/dashboard/sankey.js'; import subscriptions from './pages/dashboard/subscriptions.js'; import piggies from './pages/dashboard/piggies.js'; -const comps = {dates, boxes, accounts, budgets, categories, sankey, subscriptions, piggies}; + +import { + Chart, + LineController, + LineElement, + PieController, + BarController, + BarElement, + TimeScale, + ArcElement, + LinearScale, + Legend, + Filler, + Colors, + CategoryScale, + PointElement, + Tooltip +} from "chart.js"; +import 'chartjs-adapter-date-fns'; + +// register things +Chart.register({ + LineController, + LineElement, + ArcElement, + BarController, + TimeScale, + PieController, + BarElement, + Filler, + Colors, + LinearScale, + CategoryScale, + PointElement, + Tooltip, + Legend +}); + +const comps = { + dates, + boxes, + accounts, + budgets, + categories, + sankey, + subscriptions, + piggies +}; function loadPage(comps) { Object.keys(comps).forEach(comp => { diff --git a/resources/assets/v2/pages/dashboard/accounts.js b/resources/assets/v2/pages/dashboard/accounts.js index 5dac6e45ef..03b876cf67 100644 --- a/resources/assets/v2/pages/dashboard/accounts.js +++ b/resources/assets/v2/pages/dashboard/accounts.js @@ -18,20 +18,20 @@ * along with this program. If not, see . */ -//import ApexCharts from "apexcharts"; import {getVariable} from "../../store/get-variable.js"; import {setVariable} from "../../store/set-variable.js"; import Dashboard from "../../api/v2/chart/account/dashboard.js"; import formatMoney from "../../util/format-money.js"; import Get from "../../api/v2/model/account/get.js"; -//import Chart from "chart.js/auto"; -import {Chart} from "chart.js"; +import {Chart} from 'chart.js'; +import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; // this is very ugly, but I have no better ideas at the moment to save the currency info // for each series. let currencies = []; -let chart = null; -let chartData = null; +let chart = null; +let chartData = null; +let afterPromises = false; export default () => ({ loading: false, loadingAccounts: false, @@ -47,22 +47,18 @@ export default () => ({ dashboard.dashboard(new Date(window.store.get('start')), new Date(window.store.get('end')), null).then((response) => { this.chartData = response.data; this.drawChart(this.generateOptions(this.chartData)); + this.loading = false; }); }, generateOptions(data) { - currencies = []; - let options = { - type: 'line', - data: { - labels: [], - datasets: [] - }, - }; + currencies = []; + let options = getDefaultChartSettings('line'); for (let i = 0; i < data.length; i++) { if (data.hasOwnProperty(i)) { - let current = data[i]; - let dataset = {}; + let yAxis = 'y'; + let current = data[i]; + let dataset = {}; let collection = []; // if index = 0, push all keys as labels: @@ -74,22 +70,43 @@ export default () => ({ // use the "native" currency code and use the "native_entries" as array if (this.autoConversion) { currencies.push(current.native_code); + dataset.currency_code = current.native_code; collection = Object.values(current.native_entries); + yAxis = 'y' + current.native_code; } if (!this.autoConversion) { + yAxis = 'y' + current.currency_code; + dataset.currency_code = current.currency_code; currencies.push(current.currency_code); collection = Object.values(current.entries); } + dataset.yAxisID = yAxis; dataset.data = collection; - for (const [ii, value] of Object.entries(collection)) { - //entry.push({x: format(new Date(ii), 'yyyy-MM-dd'), y: parseFloat(value)}); - } + // add data set to the correct Y Axis: + options.data.datasets.push(dataset); - //options.series.push({name: current.label, data: entry}); } } + // for each entry in currencies, add a new y-axis: + for (let currency in currencies) { + if (currencies.hasOwnProperty(currency)) { + let code = 'y' + currencies[currency]; + if (!options.options.scales.hasOwnProperty(code)) { + options.options.scales[code] = { + id: currency, + type: 'linear', + position: 1 === parseInt(currency) ? 'right' : 'left', + ticks: { + callback: function (value, index, values) { + return formatMoney(value, currencies[currency]); + } + } + }; + } + } + } return options; }, loadChart() { @@ -108,31 +125,33 @@ export default () => ({ drawChart(options) { if (null !== chart) { // chart already in place, refresh: - chart.data.datasets = options.data.datasets; + chart.options = options.options; + chart.data = options.data; chart.update(); return; } chart = new Chart(document.querySelector("#account-chart"), options); }, loadAccounts() { - console.log('loadAccounts'); + // console.log('loadAccounts'); if (true === this.loadingAccounts) { - console.log('loadAccounts CANCELLED'); + // console.log('loadAccounts CANCELLED'); return; } this.loadingAccounts = true; if (this.accountList.length > 0) { - console.log('NO need to load account data'); + // console.log('NO need to load account data'); this.loadingAccounts = false; return; } - console.log('loadAccounts continue!'); - const max = 10; + // console.log('loadAccounts continue!'); + const max = 10; let totalAccounts = 0; - let count = 0; - let accounts = []; + let count = 0; + let accounts = []; Promise.all([getVariable('frontpageAccounts'),]).then((values) => { totalAccounts = values[0].length; + //console.log(values[0]); for (let i in values[0]) { let account = values[0]; if (account.hasOwnProperty(i)) { @@ -149,7 +168,7 @@ export default () => ({ break; } let current = response.data.data[ii]; - let group = { + let group = { title: null === current.attributes.group_title ? '' : current.attributes.group_title, id: current.id, transactions: [], @@ -158,25 +177,26 @@ export default () => ({ let currentTransaction = current.attributes.transactions[iii]; //console.log(currentTransaction); group.transactions.push({ - description: currentTransaction.description, - id: current.id, - amount: formatMoney(currentTransaction.amount, currentTransaction.currency_code), - native_amount: formatMoney(currentTransaction.native_amount, currentTransaction.native_code), - }); + description: currentTransaction.description, + id: current.id, + amount: formatMoney(currentTransaction.amount, currentTransaction.currency_code), + native_amount: formatMoney(currentTransaction.native_amount, currentTransaction.native_code), + }); } groups.push(group); } - console.log(parent); + // console.log(parent); accounts.push({ - name: parent.attributes.name, - id: parent.id, - balance: formatMoney(parent.attributes.current_balance, parent.attributes.currency_code), - native_balance: formatMoney(parent.attributes.native_current_balance, parent.attributes.native_code), - groups: groups, - }); + name: parent.attributes.name, + id: parent.id, + balance: formatMoney(parent.attributes.current_balance, parent.attributes.currency_code), + native_balance: formatMoney(parent.attributes.native_current_balance, parent.attributes.native_code), + groups: groups, + }); count++; if (count === totalAccounts) { this.accountList = accounts; + this.loadingAccounts = false; } }); }); @@ -187,20 +207,31 @@ export default () => ({ }, init() { + // console.log('accounts init'); Promise.all([getVariable('viewRange', '1M'), getVariable('autoConversion', false),]).then((values) => { + //console.log('accounts after promises'); this.autoConversion = values[1]; + afterPromises = true; // main dashboard chart: this.loadChart(); this.loadAccounts(); }); window.store.observe('end', () => { - chartData = null; + if (!afterPromises) { + return; + } + // console.log('accounts observe end'); + chartData = null; this.accountList = []; // main dashboard chart: this.loadChart(); this.loadAccounts(); }); window.store.observe('autoConversion', () => { + if (!afterPromises) { + return; + } + // console.log('accounts observe autoconversion'); this.loadChart(); this.loadAccounts(); }); diff --git a/resources/assets/v2/pages/dashboard/boxes.js b/resources/assets/v2/pages/dashboard/boxes.js index f9eb90155d..037f8a1136 100644 --- a/resources/assets/v2/pages/dashboard/boxes.js +++ b/resources/assets/v2/pages/dashboard/boxes.js @@ -23,6 +23,7 @@ import {format} from "date-fns"; import {getVariable} from "../../store/get-variable.js"; import formatMoney from "../../util/format-money.js"; +let afterPromises = false; export default () => ({ balanceBox: {amounts: [], subtitles: []}, @@ -173,35 +174,43 @@ export default () => ({ this.balanceBox.subtitles.push(subtitles[i]); } } + this.loading = false; }, loadBoxes() { - if (true === this.loading) { return; } this.loading = true; if (null === this.boxData) { this.getFreshData(); + return; } - if (null !== this.boxData) { - this.generateOptions(this.boxData); - //this.drawChart(); - } - + this.generateOptions(this.boxData); this.loading = false; }, // Getter init() { + // console.log('boxes init'); Promise.all([getVariable('viewRange'), getVariable('autoConversion', false)]).then((values) => { + // console.log('boxes after promises'); + afterPromises = true; this.autoConversion = values[1]; this.loadBoxes(); }); window.store.observe('end', () => { + if (!afterPromises) { + return; + } + // console.log('boxes observe end'); this.boxData = null; this.loadBoxes(); }); window.store.observe('autoConversion', (newValue) => { + if (!afterPromises) { + return; + } + // console.log('boxes observe autoConversion'); this.autoConversion = newValue; this.loadBoxes(); }); diff --git a/resources/assets/v2/pages/dashboard/budgets.js b/resources/assets/v2/pages/dashboard/budgets.js index 5c3d82e3b9..bfb274ad44 100644 --- a/resources/assets/v2/pages/dashboard/budgets.js +++ b/resources/assets/v2/pages/dashboard/budgets.js @@ -19,14 +19,26 @@ */ import {getVariable} from "../../store/get-variable.js"; 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"; +import {Chart} from 'chart.js'; +import {I18n} from "i18n-js"; let currencies = []; let chart = null; let chartData = null; +let afterPromises = false; + +let language; +let i18n; // for translating items in the chart. + +async function loadTranslations(i18n, locale) { + const response = await fetch(`./v2/i18n/${locale}.json`); + const translations = await response.json(); + + i18n.store(translations); +} + export default () => ({ loading: false, @@ -136,19 +148,37 @@ export default () => ({ init() { - Promise.all([getVariable('autoConversion', false),]).then((values) => { + // console.log('budgets init'); + Promise.all([getVariable('autoConversion', false), getVariable('language', 'en-US')]).then((values) => { + + i18n = new I18n(); + loadTranslations(i18n, values[1]); + // load translations. + //i18n = require('../../lang/' + values[1] + '.js').default; + //import lang from '../../lang/' + values[1] + '.js'; + //language = values[1]; + this.autoConversion = values[0]; + afterPromises = true; if (false === this.loading) { this.loadChart(); } }); window.store.observe('end', () => { + if (!afterPromises) { + return; + } + // console.log('boxes observe end'); if (false === this.loading) { this.chartData = null; this.loadChart(); } }); window.store.observe('autoConversion', (newValue) => { + if (!afterPromises) { + return; + } + // console.log('boxes observe autoConversion'); this.autoConversion = newValue; 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 4e1e9fb049..f1165ef0f1 100644 --- a/resources/assets/v2/pages/dashboard/categories.js +++ b/resources/assets/v2/pages/dashboard/categories.js @@ -19,15 +19,13 @@ */ 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"; +import {Chart} from "chart.js"; let currencies = []; - let chart = null; let chartData = null; +let afterPromises = false; export default () => ({ loading: false, @@ -142,15 +140,23 @@ export default () => ({ this.getFreshData(); }, init() { + // console.log('categories init'); Promise.all([getVariable('autoConversion', false),]).then((values) => { this.autoConversion = values[0]; + afterPromises = true; this.loadChart(); }); window.store.observe('end', () => { + if (!afterPromises) { + return; + } this.chartData = null; this.loadChart(); }); window.store.observe('autoConversion', (newValue) => { + if (!afterPromises) { + return; + } this.autoConversion = newValue; this.loadChart(); }); diff --git a/resources/assets/v2/pages/dashboard/piggies.js b/resources/assets/v2/pages/dashboard/piggies.js index 9248e21f7e..7d88d8b03a 100644 --- a/resources/assets/v2/pages/dashboard/piggies.js +++ b/resources/assets/v2/pages/dashboard/piggies.js @@ -19,10 +19,10 @@ */ import {getVariable} from "../../store/get-variable.js"; import Get from "../../api/v2/model/piggy-bank/get.js"; - -let currencies = []; +import {Chart} from 'chart.js'; let apiData = {}; +let afterPromises = false; export default () => ({ loading: false, @@ -106,16 +106,27 @@ export default () => ({ this.getFreshData(); }, init() { + // console.log('piggies init'); apiData = []; Promise.all([getVariable('autoConversion', false)]).then((values) => { + // console.log('piggies after promises'); + afterPromises = true; this.autoConversion = values[0]; this.loadPiggyBanks(); }); window.store.observe('end', () => { + if (!afterPromises) { + return; + } + // console.log('piggies observe end'); apiData = []; this.loadPiggyBanks(); }); window.store.observe('autoConversion', (newValue) => { + if (!afterPromises) { + return; + } + // console.log('piggies observe autoConversion'); this.autoConversion = newValue; this.loadPiggyBanks(); }); diff --git a/resources/assets/v2/pages/dashboard/sankey.js b/resources/assets/v2/pages/dashboard/sankey.js index 974d1857a6..a5116c4cf3 100644 --- a/resources/assets/v2/pages/dashboard/sankey.js +++ b/resources/assets/v2/pages/dashboard/sankey.js @@ -20,14 +20,15 @@ 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 {Chart} from 'chart.js'; import {Flow, SankeyController} from 'chartjs-chart-sankey'; -Chart.register(SankeyController, Flow); +Chart.register({SankeyController, Flow}); + let currencies = []; - -let chart = null; +let afterPromises = false; +let chart = null; let transactions = []; // little helper @@ -107,17 +108,17 @@ export default () => ({ // variables collected for the sankey chart: let amounts = {}; - let bigBox = 'TODO All money'; - let labels = {}; + let bigBox = 'TODO All money'; + let labels = {}; for (let i in transactions) { if (transactions.hasOwnProperty(i)) { let group = transactions[i]; for (let ii in group.attributes.transactions) { if (group.attributes.transactions.hasOwnProperty(ii)) { // properties of the transaction, used in the generation of the chart: - let transaction = group.attributes.transactions[ii]; + let transaction = group.attributes.transactions[ii]; let currencyCode = this.autoConversion ? transaction.native_code : transaction.currency_code; - let amount = this.autoConversion ? parseFloat(transaction.native_amount) : parseFloat(transaction.amount); + let amount = this.autoConversion ? parseFloat(transaction.native_amount) : parseFloat(transaction.amount); let flowKey; /* @@ -127,11 +128,11 @@ export default () => ({ */ if ('deposit' === transaction.type) { // nr 1 - let category = getObjectName('category', transaction.category_name, 'in', currencyCode); - let revenueAccount = getObjectName('account', transaction.source_name, 'in', currencyCode); - labels[category] = getLabelName('category', transaction.category_name, currencyCode); + let category = getObjectName('category', transaction.category_name, 'in', currencyCode); + let revenueAccount = getObjectName('account', transaction.source_name, 'in', currencyCode); + labels[category] = getLabelName('category', transaction.category_name, currencyCode); labels[revenueAccount] = getLabelName('account', transaction.source_name, currencyCode); - flowKey = revenueAccount + '-' + category + '-' + currencyCode; + flowKey = revenueAccount + '-' + category + '-' + currencyCode; if (!amounts.hasOwnProperty(flowKey)) { amounts[flowKey] = { from: revenueAccount, @@ -160,9 +161,9 @@ export default () => ({ */ if ('withdrawal' === transaction.type) { // 1. - let budget = getObjectName('budget', transaction.budget_name, 'out', currencyCode); + let budget = getObjectName('budget', transaction.budget_name, 'out', currencyCode); labels[budget] = getLabelName('budget', transaction.budget_name, currencyCode); - flowKey = bigBox + '-' + budget + '-' + currencyCode; + flowKey = bigBox + '-' + budget + '-' + currencyCode; if (!amounts.hasOwnProperty(flowKey)) { amounts[flowKey] = { @@ -175,9 +176,9 @@ export default () => ({ // 2. - let category = getObjectName('category', transaction.category_name, 'out', currencyCode); + let category = getObjectName('category', transaction.category_name, 'out', currencyCode); labels[category] = getLabelName('category', transaction.category_name, currencyCode); - flowKey = budget + '-' + category + '-' + currencyCode; + flowKey = budget + '-' + category + '-' + currencyCode; if (!amounts.hasOwnProperty(flowKey)) { amounts[flowKey] = { @@ -189,9 +190,9 @@ export default () => ({ amounts[flowKey].amount += amount; // 3. - let expenseAccount = getObjectName('account', transaction.destination_name, 'out', currencyCode); + let expenseAccount = getObjectName('account', transaction.destination_name, 'out', currencyCode); labels[expenseAccount] = getLabelName('account', transaction.destination_name, currencyCode); - flowKey = category + '-' + expenseAccount + '-' + currencyCode; + flowKey = category + '-' + expenseAccount + '-' + currencyCode; if (!amounts.hasOwnProperty(flowKey)) { amounts[flowKey] = { @@ -208,32 +209,32 @@ export default () => ({ } let dataSet = - // sankey chart has one data set. - { - label: 'My sankey', - data: [], - //colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from), - //colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to), - colorMode: 'gradient', // or 'from' or 'to' - labels: labels, - /* 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 - }; + // sankey chart has one data set. + { + label: 'My sankey', + data: [], + //colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from), + //colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to), + colorMode: 'gradient', // or 'from' or 'to' + labels: labels, + /* 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 + }; for (let i in amounts) { if (amounts.hasOwnProperty(i)) { let amount = amounts[i]; @@ -297,24 +298,31 @@ export default () => ({ this.getFreshData(); }, init() { + // console.log('sankey init'); transactions = []; Promise.all([getVariable('autoConversion', false), getVariable('sankeyGrouping', 'account')]).then((values) => { + // console.log('sankey after promises'); + afterPromises = true; this.autoConversion = values[0]; this.sankeyGrouping = values[1]; this.loadChart(); }); window.store.observe('end', () => { + if (!afterPromises) { + return; + } + // console.log('sankey observe end'); this.transactions = []; this.loadChart(); }); window.store.observe('autoConversion', (newValue) => { + if (!afterPromises) { + return; + } + // console.log('sankey observe autoConversion'); this.autoConversion = newValue; this.loadChart(); }); - window.store.observe('sankeyGrouping', (newValue) => { - this.sankeyGrouping = newValue; - this.loadChart(); - }); }, }); diff --git a/resources/assets/v2/pages/dashboard/subscriptions.js b/resources/assets/v2/pages/dashboard/subscriptions.js index a6972e5cf8..482c029f2b 100644 --- a/resources/assets/v2/pages/dashboard/subscriptions.js +++ b/resources/assets/v2/pages/dashboard/subscriptions.js @@ -19,14 +19,13 @@ */ import {getVariable} from "../../store/get-variable.js"; import Get from "../../api/v2/model/subscription/get.js"; -import Chart from 'chart.js/auto'; import {getDefaultChartSettings} from "../../support/default-chart-settings.js"; -import formatMoney from "../../util/format-money.js"; import {format} from "date-fns"; +import {Chart} from 'chart.js'; -let currencies = []; -let chart = null; -let chartData = null; +let chart = null; +let chartData = null; +let afterPromises = false; export default () => ({ loading: false, @@ -54,7 +53,7 @@ export default () => ({ }, getFreshData() { const getter = new Get(); - let params = { + let params = { start: format(new Date(window.store.get('start')), 'y-MM-dd'), end: format(new Date(window.store.get('end')), 'y-MM-dd') }; @@ -63,23 +62,23 @@ export default () => ({ let paidData = response.data; getter.unpaid(params).then((response) => { let unpaidData = response.data; - let chartData = {paid: paidData, unpaid: unpaidData}; + let chartData = {paid: paidData, unpaid: unpaidData}; this.drawChart(this.generateOptions(chartData)); this.loading = false; }); }); }, generateOptions(data) { - let options = getDefaultChartSettings('pie'); + let options = getDefaultChartSettings('pie'); // console.log(data); - options.data.labels = ['TODO paid', 'TODO unpaid']; + options.data.labels = ['TODO paid', 'TODO unpaid']; options.data.datasets = []; - let collection = {}; + let collection = {}; for (let i in data.paid) { if (data.paid.hasOwnProperty(i)) { - let current = data.paid[i]; + let current = data.paid[i]; let currencyCode = this.autoConversion ? current.native_code : current.currency_code; - let amount = this.autoConversion ? current.native_sum : current.sum; + let amount = this.autoConversion ? current.native_sum : current.sum; if (!collection.hasOwnProperty(currencyCode)) { collection[currencyCode] = { paid: 0, @@ -93,9 +92,9 @@ export default () => ({ // unpaid for (let i in data.unpaid) { if (data.unpaid.hasOwnProperty(i)) { - let current = data.unpaid[i]; + let current = data.unpaid[i]; let currencyCode = this.autoConversion ? current.native_code : current.currency_code; - let amount = this.autoConversion ? current.native_sum : current.sum; + let amount = this.autoConversion ? current.native_sum : current.sum; if (!collection.hasOwnProperty(currencyCode)) { collection[currencyCode] = { paid: 0, @@ -129,19 +128,30 @@ export default () => ({ init() { + // console.log('subscriptions init'); Promise.all([getVariable('autoConversion', false),]).then((values) => { + // console.log('subscriptions after promises'); this.autoConversion = values[0]; + afterPromises = true; if (false === this.loading) { this.loadChart(); } }); window.store.observe('end', () => { + if (!afterPromises) { + return; + } + // console.log('subscriptions observe end'); if (false === this.loading) { this.chartData = null; this.loadChart(); } }); window.store.observe('autoConversion', (newValue) => { + if (!afterPromises) { + return; + } + // console.log('subscriptions observe autoConversion'); this.autoConversion = newValue; if (false === this.loading) { this.loadChart(); diff --git a/resources/assets/v2/support/default-chart-settings.js b/resources/assets/v2/support/default-chart-settings.js index a1c5e06044..54fd0918f9 100644 --- a/resources/assets/v2/support/default-chart-settings.js +++ b/resources/assets/v2/support/default-chart-settings.js @@ -18,6 +18,8 @@ * along with this program. If not, see . */ +import formatMoney from "../util/format-money.js"; + function getDefaultChartSettings(type) { if ('sankey' === type) { return { @@ -43,6 +45,7 @@ function getDefaultChartSettings(type) { datasets: [], }, options: { + maintainAspectRatio: false, scales: { y: { beginAtZero: true @@ -51,7 +54,40 @@ function getDefaultChartSettings(type) { }, }; } - return []; + if ('line' === type) { + return { + options: { + plugins: { + tooltip: { + callbacks: { + label: function (tooltipItem) { + console.log(tooltipItem); + let currency = tooltipItem.dataset.currency_code; + return formatMoney(tooltipItem.raw, currency); + }, + }, + }, + }, + maintainAspectRatio: false, + scales: { + x: { + // The axis for this scale is determined from the first letter of the id as `'x'` + // It is recommended to specify `position` and / or `axis` explicitly. + type: 'time', + time: { + tooltipFormat: 'PP', + } + }, + }, + }, + type: 'line', + data: { + labels: [], + datasets: [] + }, + }; + } + return {}; } export {getDefaultChartSettings}; diff --git a/resources/views/v2/index.blade.php b/resources/views/v2/index.blade.php index e5c063d611..951eb51804 100644 --- a/resources/views/v2/index.blade.php +++ b/resources/views/v2/index.blade.php @@ -20,7 +20,7 @@ title="{{ __('firefly.yourAccounts') }}">{{ __('firefly.yourAccounts') }} -
+
-
-
- -
+
+
@@ -68,7 +66,7 @@ title="{{ __('firefly.yourAccounts') }}">{{ __('firefly.categories') }}
-
+
@@ -77,6 +75,11 @@ @@ -77,7 +90,14 @@ -

{{ __('firefly.left_to_spend') }}

+ + @@ -108,9 +128,16 @@ -

- {{ __('firefly.net_worth') }} -

+ +