Print the calendar as a themed PDF of the view on screen (#342) #1173

Merged
tiagoagueda merged 1 commit from 342-print-calendar into main 2026-10-31 08:23:21 +00:00
Owner

The Calendar could not be printed properly: printing was the browser's
dialog over the page, with two entries a month cell, a New reminder button
in every cell, the legend and the navigation, and nothing turned a month on
its side. The templates plugin had no kind for a calendar template to set.

Print sits beside the views and opens /applications/calendar/print/ with
the page's question in the address: the view, the day, the kinds shown, an
agenda's last day and the search, read by agenda.asked_for, which the page
now reads them with too. It says which period and how many entries, and
offers a theme, a language and a paper. Download PDF posts to
/applications/calendar/print/file; a GET there draws the same PDF and
remembers nothing. It is a download and is never filed (#236).

Every entry of the period prints, without the month's two-per-cell limit,
and nothing that is a control does. A month is a grid; a week, a day and an
agenda are days one under another, the agenda without its empty days. What
is over is struck through and said in words. The entries are the plain
values of #330, agenda.Item, through agenda.printed_items, which shares its
reading with items_between but keeps whole days without a public address
and works in the document's language; Item gains said, the page's words
for its kind. agenda.span and agenda.period_title come out of _build, so
the page and the print name the same period.

ThemeKind.CALENDAR, with plain and classic templates extending
documents/themes/base_calendar.html, handed view, view_label, title,
person, produced_at, start, last, kinds, narrowed, search, weekdays, weeks,
days and count, plus the usual document names and the paper. The theme is
remembered in Profile.document_themes on a POST only. A month with no paper
chosen is the person's default turned landscape, where the theme prints on
that (#344).

No migration and no archive format change: document_themes already takes
any ThemeKind.

Closes #342

Notes for review

  • Print: the Calendar page has Print beside the views, carrying the page's address.
    • It opens /applications/calendar/print/, which says the view, the period, the kinds shown, the search and how many entries, and offers a theme, a language and a paper (as #341's export page).
    • Download PDF posts to /applications/calendar/print/file with the calendar's question in the address; a GET draws the same PDF and remembers nothing. Never filed.
  • The period: read from the address by agenda.asked_for, which page_for now uses too; agenda.span and agenda.period_title were pulled out of _build, so page and print share the period and its name.
  • The values (#330): entries are agenda.Items through the new agenda.printed_items, which shares _items with items_between. No second reading of the models.
    • Item.said added (the page's words for the kind, e.g. Done reminder:), with tests in test_calendar_print.py and test_plugin_surface.py.
  • The theme: ThemeKind.CALENDAR, plain and classic calendar.html extending documents/themes/base_calendar.html; remembered in Profile.document_themes on a POST only. Context names: view, view_label, title, person, produced_at, start, last, kinds, narrowed, search, weekdays, weeks, days, count; an entry is kind, said, title, detail, all_day, starts_at, ends_at, over, state.
  • Decisions the issue left open:
    • The options page (as #341), not a straight download.
    • The search (q) narrows the print as it narrows the page.
    • Whole days (deadlines, closings, answers) print even without POSTULO_PUBLIC_URL; items_between still withholds them for plugins.
    • The agenda's Overdue and Further ahead reminders are not printed: only the period's entries.
    • A month is a grid; week, day and agenda are days one under another. Week and day keep empty days, the agenda leaves them out, as on screen.
    • The period (and so a week's first weekday) is worked out in the reader's language, not the document's, so the print is the week on screen.
    • Paper: a month with none chosen is the person's default turned landscape where the theme allows; the other views take the default as it is.
    • Print is a button of its own, not an entry in the calendar's Export transfer registry (#862).
    • A month cell prints time, the kind in words and the title; the detail line only in the list views.
  • No migration and no format bump: the remembered theme lives in document_themes, whose import takes any ThemeKind.
  • WeasyPrint: the calendar case of the theme × kind × paper render test only runs in CI (no Pango here). Checked in Chromium by eye.
  • Wiki: scratchpad/batch/wiki-342.md, to apply after wiki-341.md. No new name on postulo.plugins.api.

🤖 Generated with Claude Code

The Calendar could not be printed properly: printing was the browser's dialog over the page, with two entries a month cell, a New reminder button in every cell, the legend and the navigation, and nothing turned a month on its side. The templates plugin had no kind for a calendar template to set. Print sits beside the views and opens /applications/calendar/print/ with the page's question in the address: the view, the day, the kinds shown, an agenda's last day and the search, read by agenda.asked_for, which the page now reads them with too. It says which period and how many entries, and offers a theme, a language and a paper. Download PDF posts to /applications/calendar/print/file; a GET there draws the same PDF and remembers nothing. It is a download and is never filed (#236). Every entry of the period prints, without the month's two-per-cell limit, and nothing that is a control does. A month is a grid; a week, a day and an agenda are days one under another, the agenda without its empty days. What is over is struck through and said in words. The entries are the plain values of #330, agenda.Item, through agenda.printed_items, which shares its reading with items_between but keeps whole days without a public address and works in the document's language; Item gains said, the page's words for its kind. agenda.span and agenda.period_title come out of _build, so the page and the print name the same period. ThemeKind.CALENDAR, with plain and classic templates extending documents/themes/base_calendar.html, handed view, view_label, title, person, produced_at, start, last, kinds, narrowed, search, weekdays, weeks, days and count, plus the usual document names and the paper. The theme is remembered in Profile.document_themes on a POST only. A month with no paper chosen is the person's default turned landscape, where the theme prints on that (#344). No migration and no archive format change: document_themes already takes any ThemeKind. Closes #342 ## Notes for review - **Print:** the Calendar page has *Print* beside the views, carrying the page's address. - It opens `/applications/calendar/print/`, which says the view, the period, the kinds shown, the search and how many entries, and offers a theme, a language and a paper (as #341's export page). - *Download PDF* posts to `/applications/calendar/print/file` with the calendar's question in the address; a GET draws the same PDF and remembers nothing. Never filed. - **The period:** read from the address by `agenda.asked_for`, which `page_for` now uses too; `agenda.span` and `agenda.period_title` were pulled out of `_build`, so page and print share the period and its name. - **The values (#330):** entries are `agenda.Item`s through the new `agenda.printed_items`, which shares `_items` with `items_between`. No second reading of the models. - `Item.said` added (the page's words for the kind, e.g. *Done reminder:*), with tests in `test_calendar_print.py` and `test_plugin_surface.py`. - **The theme:** `ThemeKind.CALENDAR`, plain and classic `calendar.html` extending `documents/themes/base_calendar.html`; remembered in `Profile.document_themes` on a POST only. Context names: `view`, `view_label`, `title`, `person`, `produced_at`, `start`, `last`, `kinds`, `narrowed`, `search`, `weekdays`, `weeks`, `days`, `count`; an entry is `kind`, `said`, `title`, `detail`, `all_day`, `starts_at`, `ends_at`, `over`, `state`. - **Decisions the issue left open:** - The options page (as #341), not a straight download. - The search (`q`) narrows the print as it narrows the page. - Whole days (deadlines, closings, answers) print even without `POSTULO_PUBLIC_URL`; `items_between` still withholds them for plugins. - The agenda's *Overdue* and *Further ahead* reminders are not printed: only the period's entries. - A month is a grid; week, day and agenda are days one under another. Week and day keep empty days, the agenda leaves them out, as on screen. - The period (and so a week's first weekday) is worked out in the reader's language, not the document's, so the print is the week on screen. - Paper: a month with none chosen is the person's default turned landscape where the theme allows; the other views take the default as it is. - *Print* is a button of its own, not an entry in the calendar's *Export* transfer registry (#862). - A month cell prints time, the kind in words and the title; the detail line only in the list views. - **No migration and no format bump:** the remembered theme lives in `document_themes`, whose import takes any `ThemeKind`. - **WeasyPrint:** the calendar case of the theme × kind × paper render test only runs in CI (no Pango here). Checked in Chromium by eye. - **Wiki:** `scratchpad/batch/wiki-342.md`, to apply after `wiki-341.md`. No new name on `postulo.plugins.api`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Print the calendar as a themed PDF of the view on screen (#342)
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 14m25s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m39s
CI / Security audit (pull_request) Has been cancelled
CI / Browser tests (Chromium) (pull_request) Has been cancelled
CI / Database tests on PostgreSQL (pull_request) Has been cancelled
467deeef3c
The Calendar could not be printed properly: printing was the browser's
dialog over the page, with two entries a month cell, a New reminder button
in every cell, the legend and the navigation, and nothing turned a month on
its side. The templates plugin had no kind for a calendar template to set.

Print sits beside the views and opens /applications/calendar/print/ with
the page's question in the address: the view, the day, the kinds shown, an
agenda's last day and the search, read by agenda.asked_for, which the page
now reads them with too. It says which period and how many entries, and
offers a theme, a language and a paper. Download PDF posts to
/applications/calendar/print/file; a GET there draws the same PDF and
remembers nothing. It is a download and is never filed (#236).

Every entry of the period prints, without the month's two-per-cell limit,
and nothing that is a control does. A month is a grid; a week, a day and an
agenda are days one under another, the agenda without its empty days. What
is over is struck through and said in words. The entries are the plain
values of #330, agenda.Item, through agenda.printed_items, which shares its
reading with items_between but keeps whole days without a public address
and works in the document's language; Item gains said, the page's words
for its kind. agenda.span and agenda.period_title come out of _build, so
the page and the print name the same period.

ThemeKind.CALENDAR, with plain and classic templates extending
documents/themes/base_calendar.html, handed view, view_label, title,
person, produced_at, start, last, kinds, narrowed, search, weekdays, weeks,
days and count, plus the usual document names and the paper. The theme is
remembered in Profile.document_themes on a POST only. A month with no paper
chosen is the person's default turned landscape, where the theme prints on
that (#344).

No migration and no archive format change: document_themes already takes
any ThemeKind.

Closes #342

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 342-print-calendar from 467deeef3c
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 14m25s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m39s
CI / Security audit (pull_request) Has been cancelled
CI / Browser tests (Chromium) (pull_request) Has been cancelled
CI / Database tests on PostgreSQL (pull_request) Has been cancelled
to 4f75f07b45
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 17m53s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m39s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m18s
CI / Security audit (pull_request) Successful in 1m25s
CI / Browser tests (Chromium) (pull_request) Successful in 35m46s
2026-10-31 06:30:11 +00:00
Compare
tiagoagueda deleted branch 342-print-calendar 2026-10-31 08:23:25 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo!1173
No description provided.