From 44770a36c7b71689bc8251cf752a8582f58a8868 Mon Sep 17 00:00:00 2001 From: Matiss Janis Aboltins Date: Mon, 13 May 2024 17:34:46 +0100 Subject: [PATCH] :bug: fix networth graph loading forever for empty budgets (#2725) --- packages/desktop-client/package.json | 2 + .../spreadsheets/net-worth-spreadsheet.ts | 67 +++++++++++++------ .../spreadsheets/spending-spreadsheet.ts | 5 +- .../src/components/reports/util.ts | 12 ---- upcoming-release-notes/2725.md | 6 ++ yarn.lock | 9 +++ 6 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 upcoming-release-notes/2725.md diff --git a/packages/desktop-client/package.json b/packages/desktop-client/package.json index c1617dcb01d..1c3f218cacf 100644 --- a/packages/desktop-client/package.json +++ b/packages/desktop-client/package.json @@ -21,6 +21,7 @@ "@swc/plugin-react-remove-properties": "^1.5.121", "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.2", + "@types/lodash": "^4", "@types/promise-retry": "^1.1.6", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.1", @@ -41,6 +42,7 @@ "inter-ui": "^3.19.3", "jest": "^27.5.1", "jest-watch-typeahead": "^2.2.2", + "lodash": "^4.17.21", "mdast-util-newline-to-break": "^2.0.0", "memoize-one": "^6.0.0", "pikaday": "1.8.2", diff --git a/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.ts index b5000d3e38a..2fc4c1ae272 100644 --- a/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.ts +++ b/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.ts @@ -1,7 +1,8 @@ -// @ts-strict-ignore import * as d from 'date-fns'; +import keyBy from 'lodash/keyBy'; import { runQuery } from 'loot-core/src/client/query-helpers'; +import { type useSpreadsheet } from 'loot-core/src/client/SpreadsheetProvider'; import { send } from 'loot-core/src/platform/client/fetch'; import * as monthUtils from 'loot-core/src/shared/months'; import { q } from 'loot-core/src/shared/query'; @@ -10,21 +11,27 @@ import { integerToAmount, amountToInteger, } from 'loot-core/src/shared/util'; +import { + type AccountEntity, + type RuleConditionEntity, +} from 'loot-core/types/models'; -import { index } from '../util'; +type Balance = { + date: string; + amount: number; +}; export function createSpreadsheet( - start, - end, - accounts, - conditions = [], - conditionsOp, + start: string, + end: string, + accounts: AccountEntity[], + conditions: RuleConditionEntity[] = [], + conditionsOp: 'and' | 'or', ) { - return async (spreadsheet, setData) => { - if (accounts.length === 0) { - return null; - } - + return async ( + spreadsheet: ReturnType, + setData: (data: ReturnType) => void, + ) => { const { filters } = await send('make-filters-from-conditions', { conditions: conditions.filter(cond => !cond.customName), }); @@ -32,7 +39,7 @@ export function createSpreadsheet( const data = await Promise.all( accounts.map(async acct => { - const [starting, balances] = await Promise.all([ + const [starting, balances]: [number, Balance[]] = await Promise.all([ runQuery( q('transactions') .filter({ @@ -65,7 +72,7 @@ export function createSpreadsheet( return { id: acct.id, - balances: index(balances, 'date'), + balances: keyBy(balances, 'date'), starting, }; }), @@ -75,7 +82,15 @@ export function createSpreadsheet( }; } -function recalculate(data, start, end) { +function recalculate( + data: Array<{ + id: string; + balances: Record; + starting: number; + }>, + start: string, + end: string, +) { const months = monthUtils.rangeInclusive(start, end); const accountBalances = data.map(account => { @@ -92,10 +107,20 @@ function recalculate(data, start, end) { let hasNegative = false; let startNetWorth = 0; let endNetWorth = 0; - let lowestNetWorth = null; - let highestNetWorth = null; - - const graphData = months.reduce((arr, month, idx) => { + let lowestNetWorth: number | null = null; + let highestNetWorth: number | null = null; + + const graphData = months.reduce< + Array<{ + x: string; + y: number; + assets: string; + debt: string; + change: string; + networth: string; + date: string; + }> + >((arr, month, idx) => { let debt = 0; let assets = 0; let total = 0; @@ -134,10 +159,10 @@ function recalculate(data, start, end) { }); arr.forEach(item => { - if (item.y < lowestNetWorth || lowestNetWorth === null) { + if (lowestNetWorth === null || item.y < lowestNetWorth) { lowestNetWorth = item.y; } - if (item.y > highestNetWorth || highestNetWorth === null) { + if (highestNetWorth === null || item.y > highestNetWorth) { highestNetWorth = item.y; } }); diff --git a/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts index 4203f18ccf8..e844aa63c7c 100644 --- a/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts +++ b/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts @@ -1,5 +1,7 @@ // @ts-strict-ignore +import keyBy from 'lodash/keyBy'; + import { runQuery } from 'loot-core/src/client/query-helpers'; import { type useSpreadsheet } from 'loot-core/src/client/SpreadsheetProvider'; import { send } from 'loot-core/src/platform/client/fetch'; @@ -16,7 +18,6 @@ import { } from 'loot-core/src/types/models/reports'; import { getSpecificRange } from '../reportRanges'; -import { index } from '../util'; import { makeQuery } from './makeQuery'; @@ -157,7 +158,7 @@ export function createSpendingSpreadsheet({ month: month.month, }; }); - const indexedData: SpendingMonthEntity = index(dayData, 'month'); + const indexedData: SpendingMonthEntity = keyBy(dayData, 'month'); return { months: indexedData, day, diff --git a/packages/desktop-client/src/components/reports/util.ts b/packages/desktop-client/src/components/reports/util.ts index d967a0bae55..ab45b9bb550 100644 --- a/packages/desktop-client/src/components/reports/util.ts +++ b/packages/desktop-client/src/components/reports/util.ts @@ -18,18 +18,6 @@ export async function runAll( cb(data); } -export function index< - T extends Record, - K extends keyof T, ->(data: T[], field: K) { - const result: Record = {}; - data.forEach(item => { - const key = item[field]; - result[key] = item; - }); - return result; -} - export function indexCashFlow< T extends { date: string; isTransfer: boolean; amount: number }, >(data: T[], date: string, isTransfer: string) { diff --git a/upcoming-release-notes/2725.md b/upcoming-release-notes/2725.md new file mode 100644 index 00000000000..376fa4cbfc7 --- /dev/null +++ b/upcoming-release-notes/2725.md @@ -0,0 +1,6 @@ +--- +category: Bugfix +authors: [MatissJanis] +--- + +Do not show loading indicator in networth report if the budget file is empty diff --git a/yarn.lock b/yarn.lock index 2ac07467e2d..556d626fea7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -73,6 +73,7 @@ __metadata: "@swc/plugin-react-remove-properties": "npm:^1.5.121" "@testing-library/react": "npm:14.1.2" "@testing-library/user-event": "npm:14.5.2" + "@types/lodash": "npm:^4" "@types/promise-retry": "npm:^1.1.6" "@types/react": "npm:^18.2.0" "@types/react-dom": "npm:^18.2.1" @@ -93,6 +94,7 @@ __metadata: inter-ui: "npm:^3.19.3" jest: "npm:^27.5.1" jest-watch-typeahead: "npm:^2.2.2" + lodash: "npm:^4.17.21" mdast-util-newline-to-break: "npm:^2.0.0" memoize-one: "npm:^6.0.0" pikaday: "npm:1.8.2" @@ -5493,6 +5495,13 @@ __metadata: languageName: node linkType: hard +"@types/lodash@npm:^4": + version: 4.17.1 + resolution: "@types/lodash@npm:4.17.1" + checksum: 384bdd29348a000f8e815f94839a1a8c7f5a4ca856b016ade7f2abdc1df0b4e3e009c113b69db320a8fde51d1f38e60c19462b9bf3e82e0e2e32d3ac3e7ba2c4 + languageName: node + linkType: hard + "@types/mdast@npm:^3.0.0": version: 3.0.12 resolution: "@types/mdast@npm:3.0.12"