[PR #7582] [MERGED] Enhance Sankey chart datamodel, show income and allow layer filtering #56573

Closed
opened 2026-05-01 04:31:13 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/actualbudget/actual/pull/7582
Author: @emiltb
Created: 4/21/2026
Status: Merged
Merged: 4/24/2026
Merged by: @matt-fidd

Base: masterHead: better-sankey-datamodel


📝 Commits (10+)

  • eca4d8e Refactor to use directed, weighted graph as datamodel
  • 8b62389 Fix percentage labels
  • 302095f Reimplement sorting and topN handling
  • fc1cf8c Fix typing. Show toBudget on graph.
  • 2b73b01 Implement better DAG model
  • c33c47f Fix Other-grouping with new datamodel
  • f52ecc1 Add global sorting
  • 56d19f1 Reorder spreadsheet code for clarity
  • bddeb0d Add percentageLabels back
  • 8f8b5cd Fix all sorting modes

📊 Changes

8 files changed (+1302 additions, -636 deletions)

View changed files

📝 packages/desktop-client/e2e/reports.test.ts-snapshots/Reports-custom-reports-Switches-to-Line-Graph-and-checks-the-visuals-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/reports.test.ts-snapshots/Reports-custom-reports-Validates-that-show-summary-button-shows-the-summary-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/src/components/reports/graphs/SankeyGraph.tsx (+21 -85)
📝 packages/desktop-client/src/components/reports/reports/Sankey.tsx (+197 -7)
📝 packages/desktop-client/src/components/reports/reports/SankeyCard.tsx (+25 -19)
📝 packages/desktop-client/src/components/reports/spreadsheets/sankey-spreadsheet.ts (+1051 -525)
📝 packages/loot-core/src/types/models/dashboard.ts (+2 -0)
upcoming-release-notes/7582.md (+6 -0)

📄 Description

Description

This is a rather large update to the Sankey chart, that was merged earlier this month. There was a very reasonable request to show income and make it possible to filter which layers to show in the graph, as well as other smaller improvements I wanted to make. The underlying datamodel of the chart was not very clear in the first run, so I have rewritten the entire spreadsheet code to use a single weighted, directed acyclic graph (DAG). This makes it much simpler to reason about the relationship between nodes in the chart and work with it accordingly, and it is then parsed into the format that Recharts Sankey plot needs in one pass at the end, after all other processing is done. The code should also be much more readable as this point.

This PR keeps all functionality from the already merged implementation (grouping small nodes in 'Other' categories, sorting modes, viewing as percentage, filtering), even though the entire codebase is rewritten.

The majority of the code is written by myself, with smaller contributions and help with fixing typechecking issues using opencode.

Note

Since this is basically a full rewrite of the report, it would be very nice to have it merged for 2026.5.0, since it will be much more relevant to have broad testing of this rather than the version currently on master. I know that it is a big ask with a rather short notice, but fingers crossed :-)

New features

  • Now includes income payees and income categories
  • Allows the user to select a range of layers to show
  • Better handling of budget-variations (i.e. overspent, overbudgeted, left to budget amounts) as well as money kept from or held for next month.

Spent view
2026-04-21T23:46:28,124335510+02:00

Budgeted view
2026-04-21T23:47:04,682667545+02:00

Relates to #1919. Builds on previous work in #7220, #7442, #7476.

Testing

I have tested manually tested that the the different filtering options, date selection and layer selection provides satisfactory views with both a test budgt and my own budget.

Checklist

  • Release notes added (see link above)
  • No obvious regressions in affected areas
  • Self-review has been performed - I understand what each change in the code does and why it is needed

Bundle Stats

Bundle Files count Total bundle size % Changed
desktop-client 34 13.87 MB → 13.88 MB (+17.53 kB) +0.12%
loot-core 1 5.27 MB 0%
api 2 3.89 MB 0%
cli 1 7.91 MB 0%
crdt 1 41.83 kB 0%
View detailed bundle stats

desktop-client

Total

Files count Total bundle size % Changed
34 13.87 MB → 13.88 MB (+17.53 kB) +0.12%
Changeset
File Δ Size
home/runner/work/actual/actual/packages/component-library/src/icons/v1/Layers.tsx 🆕 +435 B 0 B → 435 B
src/components/reports/spreadsheets/sankey-spreadsheet.ts 📈 +10.49 kB (+75.95%) 13.81 kB → 24.29 kB
src/components/reports/reports/Sankey.tsx 📈 +8.37 kB (+29.28%) 28.58 kB → 36.95 kB
locale/zh-Hans.json 📈 +394 B (+0.32%) 119.35 kB → 119.73 kB
locale/es.json 📈 +585 B (+0.32%) 181.29 kB → 181.86 kB
src/components/reports/graphs/NetWorthGraph.tsx 📈 +8 B (+0.04%) 21.24 kB → 21.25 kB
src/components/reports/graphs/DonutGraph.tsx 📈 +4 B (+0.02%) 22.7 kB → 22.7 kB
src/components/reports/reports/CustomReport.tsx 📈 +4 B (+0.01%) 41.84 kB → 41.84 kB
src/components/reports/SaveReport.tsx 📉 -2 B (-0.02%) 12.91 kB → 12.91 kB
src/components/reports/reports/SankeyCard.tsx 📉 -68 B (-0.89%) 7.43 kB → 7.37 kB
src/components/reports/graphs/SankeyGraph.tsx 📉 -2.65 kB (-27.21%) 9.74 kB → 7.09 kB
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger

Asset File Size % Changed
static/js/ReportRouter.js 1.2 MB → 1.22 MB (+16.15 kB) +1.31%
static/js/es.js 181.29 kB → 181.86 kB (+585 B) +0.32%
static/js/Value.js 4.94 MB → 4.94 MB (+435 B) +0.01%
static/js/zh-Hans.js 119.35 kB → 119.73 kB (+394 B) +0.32%

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
static/js/index.js 1.86 MB 0%
static/js/BackgroundImage.js 121.09 kB 0%
static/js/FormulaEditor.js 962.55 kB 0%
static/js/PayeeRuleCountLabel.js 52.52 kB 0%
static/js/ScheduleEditForm.js 145.68 kB 0%
static/js/TransactionEdit.js 186.56 kB 0%
static/js/TransactionList.js 85.81 kB 0%
static/js/ca.js 191.49 kB 0%
static/js/chart-theme.js 796.5 kB 0%
static/js/client.js 451.37 kB 0%
static/js/da.js 104.22 kB 0%
static/js/de.js 173.88 kB 0%
static/js/en-GB.js 8.2 kB 0%
static/js/en.js 176.76 kB 0%
static/js/extends.js 518.66 kB 0%
static/js/fr.js 182.5 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.46 kB 0%
static/js/it.js 168.33 kB 0%
static/js/narrow.js 364.31 kB 0%
static/js/nb-NO.js 151.39 kB 0%
static/js/nl.js 108.46 kB 0%
static/js/pl.js 88.14 kB 0%
static/js/pt-BR.js 193.27 kB 0%
static/js/resize-observer.js 18.06 kB 0%
static/js/th.js 178.63 kB 0%
static/js/theme.js 31.67 kB 0%
static/js/uk.js 212.03 kB 0%
static/js/useFormatList.js 8.63 kB 0%
static/js/wide.js 453 B 0%
static/js/workbox-window.prod.es5.js 7.33 kB 0%

loot-core

Total

Files count Total bundle size % Changed
1 5.27 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.JKo6NKKa.js 5.27 MB 0%

api

Total

Files count Total bundle size % Changed
2 3.89 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
index.js 3.89 MB 0%
models.js 0 B 0%

cli

Total

Files count Total bundle size % Changed
1 7.91 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
cli.js 7.91 MB 0%

crdt

Total

Files count Total bundle size % Changed
1 41.83 kB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
index.js 41.83 kB 0%

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/actualbudget/actual/pull/7582 **Author:** [@emiltb](https://github.com/emiltb) **Created:** 4/21/2026 **Status:** ✅ Merged **Merged:** 4/24/2026 **Merged by:** [@matt-fidd](https://github.com/matt-fidd) **Base:** `master` ← **Head:** `better-sankey-datamodel` --- ### 📝 Commits (10+) - [`eca4d8e`](https://github.com/actualbudget/actual/commit/eca4d8eb630d1396f25548016db825032149f8d1) Refactor to use directed, weighted graph as datamodel - [`8b62389`](https://github.com/actualbudget/actual/commit/8b62389f6e7714c1febb82bdeefba6dfc9b6560e) Fix percentage labels - [`302095f`](https://github.com/actualbudget/actual/commit/302095f3d181eeb8a07f426c3ef563d2f34440e3) Reimplement sorting and topN handling - [`fc1cf8c`](https://github.com/actualbudget/actual/commit/fc1cf8ca5b28e12efd59a8f572edb57cef29447d) Fix typing. Show toBudget on graph. - [`2b73b01`](https://github.com/actualbudget/actual/commit/2b73b01e9d7964116628ed0a646cfa48c987e2ab) Implement better DAG model - [`c33c47f`](https://github.com/actualbudget/actual/commit/c33c47f0ff9dffa4809fa3e797f6e9a5d1443c69) Fix Other-grouping with new datamodel - [`f52ecc1`](https://github.com/actualbudget/actual/commit/f52ecc124ee4582357c424e641c0a37830449148) Add global sorting - [`56d19f1`](https://github.com/actualbudget/actual/commit/56d19f110f16a7e0ae24c6ec6a7a7fe39163e729) Reorder spreadsheet code for clarity - [`bddeb0d`](https://github.com/actualbudget/actual/commit/bddeb0d9466a4ac03a6645f38dddae5cbf237aeb) Add percentageLabels back - [`8f8b5cd`](https://github.com/actualbudget/actual/commit/8f8b5cd18712a40a5f4487087bd974d11f749af3) Fix all sorting modes ### 📊 Changes **8 files changed** (+1302 additions, -636 deletions) <details> <summary>View changed files</summary> 📝 `packages/desktop-client/e2e/reports.test.ts-snapshots/Reports-custom-reports-Switches-to-Line-Graph-and-checks-the-visuals-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/reports.test.ts-snapshots/Reports-custom-reports-Validates-that-show-summary-button-shows-the-summary-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/src/components/reports/graphs/SankeyGraph.tsx` (+21 -85) 📝 `packages/desktop-client/src/components/reports/reports/Sankey.tsx` (+197 -7) 📝 `packages/desktop-client/src/components/reports/reports/SankeyCard.tsx` (+25 -19) 📝 `packages/desktop-client/src/components/reports/spreadsheets/sankey-spreadsheet.ts` (+1051 -525) 📝 `packages/loot-core/src/types/models/dashboard.ts` (+2 -0) ➕ `upcoming-release-notes/7582.md` (+6 -0) </details> ### 📄 Description ## Description This is a rather large update to the Sankey chart, that was merged earlier this month. There was a very reasonable request to show income and make it possible to filter which layers to show in the graph, as well as other smaller improvements I wanted to make. The underlying datamodel of the chart was not very clear in the first run, so I have rewritten the entire spreadsheet code to use a single weighted, directed acyclic graph (DAG). This makes it much simpler to reason about the relationship between nodes in the chart and work with it accordingly, and it is then parsed into the format that Recharts Sankey plot needs in one pass at the end, after all other processing is done. The code should also be much more readable as this point. This PR keeps all functionality from the already merged implementation (grouping small nodes in 'Other' categories, sorting modes, viewing as percentage, filtering), even though the entire codebase is rewritten. The majority of the code is written by myself, with smaller contributions and help with fixing typechecking issues using opencode. ### Note Since this is basically a full rewrite of the report, it would be very nice to have it merged for 2026.5.0, since it will be much more relevant to have broad testing of this rather than the version currently on `master`. I know that it is a big ask with a rather short notice, but fingers crossed :-) ### New features - Now includes income payees and income categories - Allows the user to select a range of layers to show - Better handling of budget-variations (i.e. overspent, overbudgeted, left to budget amounts) as well as money kept from or held for next month. **Spent view** <img width="1572" height="601" alt="2026-04-21T23:46:28,124335510+02:00" src="https://github.com/user-attachments/assets/ae709e41-a5f7-44e0-860e-3988dd59d707" /> **Budgeted view** <img width="1570" height="594" alt="2026-04-21T23:47:04,682667545+02:00" src="https://github.com/user-attachments/assets/3f70a2fa-7159-4caa-bb00-fc9601b33f5d" /> ## Related issue(s) Relates to #1919. Builds on previous work in #7220, #7442, #7476. ## Testing I have tested manually tested that the the different filtering options, date selection and layer selection provides satisfactory views with both a test budgt and my own budget. ## Checklist - [X] Release notes added (see link above) - [X] No obvious regressions in affected areas - [X] Self-review has been performed - I understand what each change in the code does and why it is needed <!--- actual-bot-sections ---> <!--- bundlestats-action-comment key:combined start ---> ### Bundle Stats Bundle | Files count | Total bundle size | % Changed ------ | ----------- | ----------------- | --------- desktop-client | 34 | 13.87 MB → 13.88 MB (+17.53 kB) | +0.12% loot-core | 1 | 5.27 MB | 0% api | 2 | 3.89 MB | 0% cli | 1 | 7.91 MB | 0% crdt | 1 | 41.83 kB | 0% <details> <summary>View detailed bundle stats</summary> #### desktop-client **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 34 | 13.87 MB → 13.88 MB (+17.53 kB) | +0.12% <details> <summary>Changeset</summary> File | Δ | Size ---- | - | ---- `home/runner/work/actual/actual/packages/component-library/src/icons/v1/Layers.tsx` | 🆕 +435 B | 0 B → 435 B `src/components/reports/spreadsheets/sankey-spreadsheet.ts` | 📈 +10.49 kB (+75.95%) | 13.81 kB → 24.29 kB `src/components/reports/reports/Sankey.tsx` | 📈 +8.37 kB (+29.28%) | 28.58 kB → 36.95 kB `locale/zh-Hans.json` | 📈 +394 B (+0.32%) | 119.35 kB → 119.73 kB `locale/es.json` | 📈 +585 B (+0.32%) | 181.29 kB → 181.86 kB `src/components/reports/graphs/NetWorthGraph.tsx` | 📈 +8 B (+0.04%) | 21.24 kB → 21.25 kB `src/components/reports/graphs/DonutGraph.tsx` | 📈 +4 B (+0.02%) | 22.7 kB → 22.7 kB `src/components/reports/reports/CustomReport.tsx` | 📈 +4 B (+0.01%) | 41.84 kB → 41.84 kB `src/components/reports/SaveReport.tsx` | 📉 -2 B (-0.02%) | 12.91 kB → 12.91 kB `src/components/reports/reports/SankeyCard.tsx` | 📉 -68 B (-0.89%) | 7.43 kB → 7.37 kB `src/components/reports/graphs/SankeyGraph.tsx` | 📉 -2.65 kB (-27.21%) | 9.74 kB → 7.09 kB </details> <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** Asset | File Size | % Changed ----- | --------- | --------- static/js/ReportRouter.js | 1.2 MB → 1.22 MB (+16.15 kB) | +1.31% static/js/es.js | 181.29 kB → 181.86 kB (+585 B) | +0.32% static/js/Value.js | 4.94 MB → 4.94 MB (+435 B) | +0.01% static/js/zh-Hans.js | 119.35 kB → 119.73 kB (+394 B) | +0.32% **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- static/js/index.js | 1.86 MB | 0% static/js/BackgroundImage.js | 121.09 kB | 0% static/js/FormulaEditor.js | 962.55 kB | 0% static/js/PayeeRuleCountLabel.js | 52.52 kB | 0% static/js/ScheduleEditForm.js | 145.68 kB | 0% static/js/TransactionEdit.js | 186.56 kB | 0% static/js/TransactionList.js | 85.81 kB | 0% static/js/ca.js | 191.49 kB | 0% static/js/chart-theme.js | 796.5 kB | 0% static/js/client.js | 451.37 kB | 0% static/js/da.js | 104.22 kB | 0% static/js/de.js | 173.88 kB | 0% static/js/en-GB.js | 8.2 kB | 0% static/js/en.js | 176.76 kB | 0% static/js/extends.js | 518.66 kB | 0% static/js/fr.js | 182.5 kB | 0% static/js/indexeddb-main-thread-worker-e59fee74.js | 13.46 kB | 0% static/js/it.js | 168.33 kB | 0% static/js/narrow.js | 364.31 kB | 0% static/js/nb-NO.js | 151.39 kB | 0% static/js/nl.js | 108.46 kB | 0% static/js/pl.js | 88.14 kB | 0% static/js/pt-BR.js | 193.27 kB | 0% static/js/resize-observer.js | 18.06 kB | 0% static/js/th.js | 178.63 kB | 0% static/js/theme.js | 31.67 kB | 0% static/js/uk.js | 212.03 kB | 0% static/js/useFormatList.js | 8.63 kB | 0% static/js/wide.js | 453 B | 0% static/js/workbox-window.prod.es5.js | 7.33 kB | 0% </div> </details> --- #### loot-core **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 5.27 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- kcab.worker.JKo6NKKa.js | 5.27 MB | 0% </div> </details> --- #### api **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 2 | 3.89 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- index.js | 3.89 MB | 0% models.js | 0 B | 0% </div> </details> --- #### cli **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 7.91 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- cli.js | 7.91 MB | 0% </div> </details> --- #### crdt **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 41.83 kB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- index.js | 41.83 kB | 0% </div> </details> </details> <!--- bundlestats-action-comment key:combined end ---> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-01 04:31:13 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#56573