Skip to content

Stats picks a window and opens a day - #67

Merged
klausbreyer merged 3 commits into
mainfrom
feature/stats-window
Aug 30, 2026
Merged

Stats picks a window and opens a day#67
klausbreyer merged 3 commits into
mainfrom
feature/stats-window

Conversation

@klausbreyer

@klausbreyer klausbreyer commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

The Stats screen showed the last thirty days and nothing else. No older numbers, no way to ask what happened on one day, and the top entries counted all time while every other table counted the window.

What it does now

  • A window to choose. 7, 30, 90 or 365 days, or all time, as a row of links over the figures. The choice stands in the address (?days=90), so the back button and a copied link keep it.
  • Bars that fit the window. Up to sixty days a bar is a day, up to a year a week (Monday first), above that a month. All time starts at the month of the first view. The heading says "by week" or "by month" when a bar is no day, and a series in months carries the year on its axis.
  • A bar opens. A click shows what was read in those days (entries and other addresses in one list, with views and people) and where the readers came from, under the chart. The address remembers the open bar (&day=2026-08-18). A second click, or "close", shuts it.
  • Top entries count the window, with a People column beside Views.
  • The figures say how the window moved against the one just before it: "views, last 30 days · +12 %". All time has nothing before it and says nothing.

Nothing new is counted. Every number comes from the rows that were already there.

How

Texttile.Stats reads a span (%{from, to}, from: nil for all time) instead of a count of days. window/2 builds one, series/2 draws it in bars, bar/2 finds the bar that holds a day, and a bar is itself a span, so the open bar is read with the same summary/1, pages_read/1 and referrers/2 as the whole window. StatsLive keeps its whole state in handle_params; a bar click is a push_patch. The editor's Stats tab draws its chart from the same series and is otherwise unchanged.

Checked

  • mix precommit: 1443 tests, 0 failures. Unit tests for the span, the three bar sizes, the window before, the bar lookup and pages_read; LiveView tests for the address, the click, the close, a day outside the window, the comparison and the People column; the browser flow clicks a bar and switches the window.
  • Visual QA in a headless browser at 1440x900 and 390x844: 30 days with a bar open, 90 days in weeks, all time in months. The chart counts exactly the window (the first week or month bar starts at its edge). The bar's tap area is the whole column height, so a low bar is as easy to hit on a phone as a tall one.
  • German translated, the template up to date.

Version

3.0.5 to 3.1.0.

Claude Fable 5 in Claude Code did the work.

A window is a span from a first day to a last one, or all time. Every
number the screens read takes that span, so a whole window and one bar
of its chart are read with the same functions. The series is drawn in
days, weeks or months by the length of the span, the summary carries
the span before it, top entries count the span and their people, and
pages_read lists entries and other addresses together.
7, 30, 90 or 365 days or all time, chosen in the address. A clicked bar
opens what was read in those days and where the readers came from under
the chart, and the address remembers the bar. Top entries count the
window with a people column, and the three figures say how the window
moved against the one before. The editor draws its chart from the same
series.
The first week or month bar of a long window reached back before the
window, so the chart counted days the figures did not. The bar now
starts where the window starts. Stats.step/1 says what a bar is from
the span itself, so a fresh blog's single month bar is a month, with
the year on its axis. Tests for both, for a fall against the window
before, and for a number that is no window.
@klausbreyer
klausbreyer merged commit 2c35ba1 into main Aug 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant