Skip to content

web: balance report page (#2242) - #2739

Merged
simonmichael merged 15 commits into
hledgerorg:mainfrom
acinader:web-balance-report-csp
Sep 22, 2026
Merged

simonmichael merged 15 commits into
hledgerorg:mainfrom
acinader:web-balance-report-csp

Conversation

@acinader

@acinader acinader commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Builds on @thielema's web-balance-report branch.

Fourteen commits on top address the review comments on #2242 and what testing turned up.

/balance serves the balance report. Account names and
period headings link into the register (for now).

Two commits change the CLI's HTML output

  • borders as classes. hledger-web sends a Content-Security-Policy that
    forbids inline styles. Remove per-cell style attributes. Cells get class
    border-{top,bottom,left,right}-{single,double} and the builtin stylesheet
    gets eight new rules. Both writers changed together, so lucid and blaze do
    not drift apart here. Column headers get classes: account for accounts,
    amount over figures. (web: send a Content-Security-Policy - The Robots are Coming! #2703)
  • a negative class on cells whose amount is negative.

-O html output has two changes: the border color now follows
the text color instead of being hardcoded black, and a single-period report's
account column picks up the builtin th.account, td.account rule it was
missing, so that column sits flush left as it already does in a multi-period
report.

Other fixes

  • --depth at startup and depth: in the search box were ignored
  • Only the interval of the period expression was used, so
    ?period=monthly in 2024 gave monthly columns over the whole journal, and
    ?period=2024 gave a single column of all-time totals. The date span now
    restricts the report as a date: term would.
  • A date: term can set the interval too, as on the command line
    (date:monthly), and wins over the period parameter.
  • A period expression that does not parse is now presented in an error alert.
  • The table is styled by hledger.css rather than by an inline <style>
    block, whose unscoped rules would also have restyled the sidebar. It is a
    bootstrap table now, so it matches the journal and register pages.
  • The period parameter is kept by the search form on this page only (so far), and by
    its clear button, which used to drop you back to the single-period report.
  • Fix tooltips so they match the report for the link.
  • Remove the unused lucid dependency.
  • Apply the journal's commodity display styles.
  • -E matches account sidebar behavior, which is the opposite of the CLI.
  • The startup reporting interval (-M, -Q, -p 'monthly in 2025' …) produced a single column of row totals instead of the periods it asks for. It now opens the multi-period report, and a period parameter still overrides it.
  • --title was ignored — the heading was always "Balance Report". It is now the command line report's heading ("Balance changes in 2024-01-01..2026-12-31"), or --title's value verbatim when one is given.
  • A wide report used to drag the whole main pane sideways, heading and search
    box with it: bootstrap's .table-responsive only scrolls below 768px, so the
    wrapper carries a rule of our own, and the table scrolls inside the page.
  • Eighteen yesod-test specs for the page, and a manual section.

The page is standalone for now

One commit removes the /balance links from the journal page, so there are no links
to it in hledger-web. I think we should add all of the missing reports first and evaluate
them stand-alone before thinking about how to wire it all together.

Addresses @simonmichael's concern on #2242 about committing hledger-web to new
UI: nothing in the existing UI changes.

Open question: what should a column heading link to?

A period heading (2024) links to register?q=date:2024, from
Hledger.Cli.Anchor. It should instead go to /balance?q=date:2024.

The amount cells should probably become links too
(register?q=inacct:<account> date:<period>), since they are unlinked today
and the heading is currently the only route from this page to the transactions
behind a period. That would give: row → the account's transactions, column →
that period's balances, cell → that account's transactions in that period.

It belongs in Hledger.Cli.Anchor but is not included here.

How to test

Manual test plan: https://gist.github.com/acinader/e58e0445e6d517e153f93a5b685ae6e3.

It tests:

  • /balance?period=yearly — the table looks like the journal and register pages
  • /balance?q=depth:1 — as many rows as the sidebar
  • /balance?period=2024 — one column, holding 2024 only
  • /balance?period=monthly%20in%202024 — twelve columns
  • /balance?q=date:monthly — the interval from the search box
  • /balance?period=bogus — an alert, not a table
  • search, then clear: the period survives both
  • hledger bal -Y -O html | grep -c 'style="' — zero

Commits

  1. imp: html: mark table borders with CSS classes instead of inline styles
  2. dev: cli: export the balance report spreadsheet parts and title
  3. dev: web: style the table like the other pages
  4. dev: web: drop the unused lucid dependency, regenerate the cabal file
  5. dev: web: honor the depth limit
  6. dev: web: apply the period expression, report a bad one
  7. imp: lib: spreadsheet cells for negative amounts get a "negative" class
  8. dev: web: headings, report links, and the period parameter
  9. test: web: cover the balance page
  10. doc: web: describe the balance page and its period parameter
  11. dev: web: don't link to it from the journal page yet
  12. dev: web: take the interval from a date: search term
  13. fix: web: apply the journal's commodity display styles
  14. fix: web: read -E the way the rest of hledger-web does

AI usage: Claude Opus 5, ~140k output tokens across the branch (the
per-commit estimates in the commit messages sum to ~77k; the rest went to
review, testing, and drafting that produced no commit).

thielema and others added 15 commits September 20, 2026 18:20
…od balance reports as HTML pages

Journal page contains links to those reports.
Cell classes and builtin stylesheet rules replace attribute styles.

AI usage: Claude Opus 5, ~8k output tokens.
balanceReportAsSpreadsheetParts, allCommoditiesFromPeriodicReport, and
multiBalanceReportTitle, for hledger-web.

AI usage: Claude Opus 5, ~1k output tokens.
Render the report as the thead, tbody, and tfoot of a bootstrap table
in a .table-responsive wrapper, styled by hledger.css.

AI usage: Claude Opus 5, ~12k output tokens.
AI usage: Claude Opus 5, ~2k output tokens.
Only the interval was used, so "monthly in 2024" covered the whole
journal and "2024" was unrestricted. A bad expression now shows an
alert instead of running text.

AI usage: Claude Opus 5, ~10k output tokens.
The links row moves to a shared widget, marks the current report, and
gets per-interval titles. The heading is now the
command line report's. The search form and its clear button keep the
period parameter, on this page only (so far).

AI usage: Claude Opus 5, ~14k output tokens.
Seven cases: the report and its register links, no inline styles, the
multi-period report and the form keeping its period, the expression's
date span, a depth: term, and a bad period expression.

AI usage: Claude Opus 5, ~8k output tokens.
AI usage: Claude Opus 5, ~2k output tokens.
Keep it standalone until there are more such reports and a navigation
scheme for them (hledgerorg#2242). The links between the balance reports stay.

AI usage: Claude Opus 5, ~3k output tokens.
As on the command line, date:monthly sets the report interval and wins
over the period parameter. Exports intervalFromQueryOpts.

AI usage: Claude Opus 5, ~6k output tokens.
-E means the opposite here than on the command line: hide zero items,
which are shown by default. The report took the command line sense, so
a single -E made the sidebar hide zero accounts at the same moment the
table started showing them.

AI usage: Claude Opus 5, ~3k output tokens.
@simonmichael

Copy link
Copy Markdown
Member

Should this be marked draft ? This todo list seems still in progress

@acinader

acinader commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

Should this be marked draft ? This todo list seems still in progress

This is ready to go. This pr is the result of working through the to-do list.

I do have a question about column, row and cell linking behavior, but I think the current implementation is acceptable and good for an upcoming release.

@simonmichael

simonmichael commented Sep 22, 2026

Copy link
Copy Markdown
Member

It all sounds good to me, and looks good from my testing. And good enough to expose in the UI when you feel ready. I'll merge this soon if there are no objections.

My main feedback: I wonder how to clearly distinguish end balance reports and balance change reports for users, in line with the "easy obvious UX" goal, and hledger's bs/is reports. Do hledger-web users need to see changes in ALE accounts, or end balances in RX accounts ? Should we just provide bs and is reports, or include the more general/advanced behaviour of the balance command ?

@simonmichael simonmichael added the web The hledger-web tool. label Sep 22, 2026
@simonmichael

simonmichael commented Sep 22, 2026

Copy link
Copy Markdown
Member

As a quick aid, it would be nice to be able to toggle historical mode (-H) on this.

@acinader

Copy link
Copy Markdown
Contributor Author

today I learned that balance report + -H + type:AL = blance sheet.

I'd like to get this in and then close #2737.

Lots to digest.

I'd like @thielema's feedback too on next steps.

@simonmichael

Copy link
Copy Markdown
Member

I'm guessing @thielema won't object to this PR, which continues his earlier work. Merging, thank you both!

@simonmichael simonmichael reopened this Sep 22, 2026
@simonmichael
simonmichael merged commit 17c8cfe into hledgerorg:main Sep 22, 2026
3 checks passed
@simonmichael

Copy link
Copy Markdown
Member

today I learned that balance report + -H + type:AL = blance sheet.

That's right. And bal type:RX = is.

bs and is exist because balance is a complicated command with many modes. (And they're standard reports people, at least US people, have heard of.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

web The hledger-web tool.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants