Date pickers: a picker per calendar view, the agenda's end day, and the calendar beside every date (#933) #1017

Merged
tiagoagueda merged 10 commits from 933-date-pickers into main 2026-10-22 00:58:35 +00:00
Owner

Closes #933

One set of date pickers for the calendar and every date in the app, built on the <c-date-picker> of #928 rather than beside it, as the approved plan says. Six commits, one per part.

What changed

1. The component grows three modes (cotton/date_picker.html, readyDatePickers() in app.js, assets/css/basecoat.css)

  • mode="week": the row under the pointer or the focus is lit, the days either side of the month are drawn so a week is whole, and any day pressed gives the week's first day.
  • mode="month": a 3x4 grid of months, the arrows beside the year stepping a year; arrows move by a month and a row, Page Up/Down by a year; the choice is YYYY-MM.
  • mode="range": a first press and a last (swapped if earlier), the days between lit as the pointer moves, a status line saying both; the event carries until.
  • min/max are the caller's (the birth picker's "not after today" is now its page's max); empty is no limit.
  • With input/until_input the panel fills those boxes itself and fires change (readyDateFields()); with submit it sends their form.
  • Under 40rem the panel is a sheet along the foot of the window with 44 px days; the hand placement leaves it to the stylesheet there. The placement is dropped as a panel closes, because htmx's settle copies an id'd element's style and the CSP refuses that (#709's trap).

2. The server's first weekday on <html>: data-first-weekday (Django's numbering, which is Date.getDay()'s) from the ui context processor, read by every picker; data-week-numbers where the language numbers weeks (German, the Nordic languages), which adds an ISO 8601 week column.

3. Every date in the forms: <c-date-field> (the button and the picker, after the box it fills) and core/date_widgets.py: DateInput, and DateTimeInput, a date box with its calendar plus a native type="time" box, read back as the YYYY-MM-DDTHH:MM the datetime-local box posted. Fields, input formats and the "cannot end before it starts" checks are unchanged, a request posting the value whole still works, ?on= prefills still work. The 28 date and 7 date-and-time fields of the applications, listings, capture, documents and CV forms use them. The interview's "was the time changed" check (#545) now reads the posted value through the widget.

4. The calendar: the period's name opens a picker per view (month: months; week: week-selecting grid; day: day grid; agenda: range). It writes into the existing GET form and sends it, so the form stays the no-script path and both reach the same address. The agenda takes ?until= (its last day): absent means the thirty days as before (old links unchanged), reversed is swapped, capped at 366 days (AGENDA_MAX_DAYS); Previous/Next/Today step by and keep the length ("Next 7 days"); the title becomes "start to end"; the legend, the agenda's view link, the masthead search (SearchScope keep) and the file download carry it.

5. The report and the table filters: the report's month box gets the month picker, its From/To boxes one range picker; each table date filter (header and narrow copies, ids kept) one range picker, which fires change once on the second box, so htmx narrows the table once with both.

A bug found on the way

Django's DateInput writes its value in the language's first input format, %d/%m/%Y in British English, and a type="date" box throws 19/10/2026 away: a stored date (closing date, CV dates, ...) was drawn as an empty box on every edit page in en-GB and other day-first languages. The new widget always writes ISO 8601. Regression test included (fails on the old widget).

Deviations from the plan

  • The widget module is core/date_widgets.py, not core/widgets.py: that name is already the dashboard's widget registry.
  • Week numbering is a set in core/weeks.py (NUMBERED_WEEKS, numbers_weeks()), not WEEK_NUMBERS = True in config/formats/<lang>/formats.py: Django's get_format reads only format names it knows, and that package's docstring rules an invented one out.
  • <c-date-field> draws the button and the picker, not the input: the box stays drawn by Django (or the page), and the component goes after it. This lets one component serve a form field, the report's pair and a filter's pair without wrapping their different markup.
  • Ranges inside forms are two day pickers, not one range picker (the plan left this open: "can use"): a CV entry's or an interview's start and end are separate boxes the server already validates as a pair, often not side by side.
  • The month view's picker goes to ?on=YYYY-MM-01 (the form's own on box), not ?month=YYYY-MM; both draw the same month.
  • The agenda's no-script form gains a "To" box labelled with the existing "From"/"To" strings.

Library check

bootstrap-datepicker was the issue's model for behaviour (minViewMode, week selection, range), not a dependency: it needs jQuery and Bootstrap's CSS. Other candidates (flatpickr, vanilla-calendar-pro, Pikaday) bring their own styling and markup and would replace, not extend, the ARIA grid #928 already built and tested; extending it kept one component and no new vendored script.

New strings for Weblate (msgids only, no msgstr)

Choose a month, Previous year, Next year, From %(start)s to %(end)s, From %(start)s: now choose the last day, Choose dates from a calendar, Time, %(start)s to %(end)s, Previous %(days)s day / Previous %(days)s days, Next %(days)s day / Next %(days)s days. Week of %(day)s, Week, Calendar, From, To, Dates you choose are reused. The status sentences go through blocktranslate so the catalogue holds %(day)s as Python's do, not an escaped %%(day)s.

Tests

  • Unit: new tests/test_date_pickers_933.py (component modes, first weekday on <html>, week numbering, both widgets including split/whole posts and the #545 check, the per-view pickers, agenda until default/cap/swap/round trip/steps, the report and the filters, the empty-box regression). Updated where behaviour changed: test_appointments.py, test_reminders_on_the_calendar.py (two boxes instead of one), test_theme.py (the <html> tag grew attributes), test_tables.py (unnamed controls post nothing), test_width.py (a picker's <table role="grid"> is not a page table). Whole unit suite -n 2, without GeoNames data as in CI: 19,493 passed, 120 skipped, 1 xfailed, and one failure, test_width.py, fixed in the last commit and rerun alone (72 passed).
  • Browser, run one file at a time with -m e2e --browser chromium: new tests/e2e/test_date_pickers.py (17), test_calendar_views.py (21, with five new per-view tests), test_birth_picker.py (11), test_appointments.py (4), test_dated_things.py (13), test_application_filters.py (40), test_column_filters.py (26), test_accessibility.py (23), test_rendering_modes.py (4): all pass. test_application_filters.py's 320 px reflow check now skips controls inside a closed popover.
  • JS and templates the browser suite covers changed (the picker, placement, the calendar, every date field, the filters): please read the CI browser job carefully.

A model (Claude) wrote this change under the contributor's direction; it was reviewed as a stranger's patch would be.

Wiki: a commit in postulo.wiki (not pushed) describes the pickers under Tracking applications → Calendar.

🤖 Generated with Claude Code

Closes #933 One set of date pickers for the calendar and every date in the app, built on the `<c-date-picker>` of #928 rather than beside it, as the approved plan says. Six commits, one per part. ## What changed **1. The component grows three modes** (`cotton/date_picker.html`, `readyDatePickers()` in `app.js`, `assets/css/basecoat.css`) - `mode="week"`: the row under the pointer or the focus is lit, the days either side of the month are drawn so a week is whole, and any day pressed gives the week's first day. - `mode="month"`: a 3x4 grid of months, the arrows beside the year stepping a year; arrows move by a month and a row, Page Up/Down by a year; the choice is `YYYY-MM`. - `mode="range"`: a first press and a last (swapped if earlier), the days between lit as the pointer moves, a status line saying both; the event carries `until`. - `min`/`max` are the caller's (the birth picker's "not after today" is now its page's `max`); empty is no limit. - With `input`/`until_input` the panel fills those boxes itself and fires `change` (`readyDateFields()`); with `submit` it sends their form. - Under 40rem the panel is a sheet along the foot of the window with 44 px days; the hand placement leaves it to the stylesheet there. The placement is dropped as a panel closes, because htmx's settle copies an id'd element's `style` and the CSP refuses that (#709's trap). **2. The server's first weekday on `<html>`**: `data-first-weekday` (Django's numbering, which is `Date.getDay()`'s) from the `ui` context processor, read by every picker; `data-week-numbers` where the language numbers weeks (German, the Nordic languages), which adds an ISO 8601 week column. **3. Every date in the forms**: `<c-date-field>` (the button and the picker, after the box it fills) and `core/date_widgets.py`: `DateInput`, and `DateTimeInput`, a date box with its calendar plus a native `type="time"` box, read back as the `YYYY-MM-DDTHH:MM` the `datetime-local` box posted. Fields, input formats and the "cannot end before it starts" checks are unchanged, a request posting the value whole still works, `?on=` prefills still work. The 28 date and 7 date-and-time fields of the applications, listings, capture, documents and CV forms use them. The interview's "was the time changed" check (#545) now reads the posted value through the widget. **4. The calendar**: the period's name opens a picker per view (month: months; week: week-selecting grid; day: day grid; agenda: range). It writes into the existing GET form and sends it, so the form stays the no-script path and both reach the same address. The agenda takes `?until=` (its last day): absent means the thirty days as before (old links unchanged), reversed is swapped, capped at 366 days (`AGENDA_MAX_DAYS`); Previous/Next/Today step by and keep the length ("Next 7 days"); the title becomes "start to end"; the legend, the agenda's view link, the masthead search (`SearchScope keep`) and the file download carry it. **5. The report and the table filters**: the report's month box gets the month picker, its From/To boxes one range picker; each table date filter (header and narrow copies, ids kept) one range picker, which fires `change` once on the second box, so htmx narrows the table once with both. ## A bug found on the way Django's `DateInput` writes its value in the language's first input format, `%d/%m/%Y` in British English, and a `type="date"` box throws `19/10/2026` away: a stored date (closing date, CV dates, ...) was drawn as an **empty box** on every edit page in en-GB and other day-first languages. The new widget always writes ISO 8601. Regression test included (fails on the old widget). ## Deviations from the plan - **The widget module is `core/date_widgets.py`**, not `core/widgets.py`: that name is already the dashboard's widget registry. - **Week numbering is a set in `core/weeks.py`** (`NUMBERED_WEEKS`, `numbers_weeks()`), not `WEEK_NUMBERS = True` in `config/formats/<lang>/formats.py`: Django's `get_format` reads only format names it knows, and that package's docstring rules an invented one out. - **`<c-date-field>` draws the button and the picker, not the input**: the box stays drawn by Django (or the page), and the component goes after it. This lets one component serve a form field, the report's pair and a filter's pair without wrapping their different markup. - **Ranges inside forms are two day pickers**, not one range picker (the plan left this open: "can use"): a CV entry's or an interview's start and end are separate boxes the server already validates as a pair, often not side by side. - **The month view's picker goes to `?on=YYYY-MM-01`** (the form's own `on` box), not `?month=YYYY-MM`; both draw the same month. - The agenda's no-script form gains a "To" box labelled with the existing "From"/"To" strings. ## Library check bootstrap-datepicker was the issue's model for behaviour (`minViewMode`, week selection, range), not a dependency: it needs jQuery and Bootstrap's CSS. Other candidates (flatpickr, vanilla-calendar-pro, Pikaday) bring their own styling and markup and would replace, not extend, the ARIA grid #928 already built and tested; extending it kept one component and no new vendored script. ## New strings for Weblate (msgids only, no msgstr) `Choose a month`, `Previous year`, `Next year`, `From %(start)s to %(end)s`, `From %(start)s: now choose the last day`, `Choose dates from a calendar`, `Time`, `%(start)s to %(end)s`, `Previous %(days)s day` / `Previous %(days)s days`, `Next %(days)s day` / `Next %(days)s days`. `Week of %(day)s`, `Week`, `Calendar`, `From`, `To`, `Dates you choose` are reused. The status sentences go through `blocktranslate` so the catalogue holds `%(day)s` as Python's do, not an escaped `%%(day)s`. ## Tests - Unit: new `tests/test_date_pickers_933.py` (component modes, first weekday on `<html>`, week numbering, both widgets including split/whole posts and the #545 check, the per-view pickers, agenda `until` default/cap/swap/round trip/steps, the report and the filters, the empty-box regression). Updated where behaviour changed: `test_appointments.py`, `test_reminders_on_the_calendar.py` (two boxes instead of one), `test_theme.py` (the `<html>` tag grew attributes), `test_tables.py` (unnamed controls post nothing), `test_width.py` (a picker's `<table role="grid">` is not a page table). Whole unit suite `-n 2`, without GeoNames data as in CI: 19,493 passed, 120 skipped, 1 xfailed, and one failure, `test_width.py`, fixed in the last commit and rerun alone (72 passed). - Browser, run one file at a time with `-m e2e --browser chromium`: new `tests/e2e/test_date_pickers.py` (17), `test_calendar_views.py` (21, with five new per-view tests), `test_birth_picker.py` (11), `test_appointments.py` (4), `test_dated_things.py` (13), `test_application_filters.py` (40), `test_column_filters.py` (26), `test_accessibility.py` (23), `test_rendering_modes.py` (4): all pass. `test_application_filters.py`'s 320 px reflow check now skips controls inside a closed popover. - JS and templates the browser suite covers changed (the picker, placement, the calendar, every date field, the filters): please read the CI browser job carefully. A model (Claude) wrote this change under the contributor's direction; it was reviewed as a stranger's patch would be. Wiki: a commit in `postulo.wiki` (not pushed) describes the pickers under *Tracking applications → Calendar*. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The calendar's views and the rest of the app need four pickers, and #928
already built one: `<c-date-picker>` and `readyDatePickers()`. This grows
that one component rather than writing a second.

- `mode="week"` lights the row under the pointer or the focus, draws the
  days either side of the month so a week is whole, and chooses the
  week's first day, whichever day of it is pressed.
- `mode="month"` is a grid of three by four months, the arrows beside the
  year stepping a year; the keys move by a month and a row, Page Up and
  Page Down by a year. The choice is `YYYY-MM`.
- `mode="range"` takes a first day and a last, swaps them if the last is
  earlier, lights the days between as the pointer moves, and says both in
  the status line; the event carries `until` beside `value`.
- `min` and `max` are the caller's: the birth picker's "nothing after
  today" was hard-coded and is now the profile page's `max`; empty means
  no limit, and the year list then runs a century back and a decade on.
- With `input`/`until_input` the panel fills those boxes itself and fires
  their `change` (`readyDateFields`), with `submit` it sends their form,
  and a `data-picker` on an opener retargets it once the script runs.
- Under 40rem the panel is a sheet along the foot of the window with
  44-pixel days; the hand placement leaves it to the stylesheet there.

The status sentences go through `blocktranslate` so the catalogue holds
`%(day)s` as Python does, and "Week of %(day)s" is the calendar's own.

Refs #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The calendar's weeks start where `core.weeks.first_day()` says: the
person's choice, else the locale's (#859). The date picker worked its
weeks out from the browser's `Intl` week info instead, which knows nothing
of that choice, so a person who starts their weeks on a Sunday saw a
Sunday-first month grid beside a Monday-first picker.

`<html>` now carries `data-first-weekday` (Django's numbering, which is
`Date.getDay()`'s) from the `ui` context processor, and the picker reads
it, keeping `Intl` only for a page drawn without it. Sunday is 0, so the
template writes the number as it is rather than through `default`.

`data-week-numbers` is set where the language numbers its weeks (the
Nordic languages and German), and the pickers then lead each row with its
ISO 8601 week number. The list lives in `core/weeks.py`, not in
`config/formats` as the plan had it: Django's `get_format` reads only the
names it knows, and that package's docstring rules an invented one out.

Refs #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The forms asked for dates with the browser's own boxes, which look and
behave differently in every browser. Each now keeps that box, which stays
the form, and gets Postulo's calendar beside it.

- `<c-date-field>` is the button and the `<c-date-picker>` it opens,
  written after the box (or the pair of boxes) it fills. The button is
  hidden until the script runs; without it the box posts what it always
  did. The calendar takes the name of the box's label.
- `core/date_widgets.py` (not `core/widgets.py`, which is the
  dashboard's) has `DateInput`, drawn through `partials/date_widget.html`,
  and `DateTimeInput`, a date box with its calendar and a native
  `type="time"` box. The two are read back as the `YYYY-MM-DDTHH:MM` the
  `datetime-local` box posted, so the fields, their input formats and the
  "cannot end before it starts" checks are untouched, and a request that
  posts the value whole is read as before. The date box keeps the field's
  name and id, so the label still names it; the time box is `<name>_time`.
- The 28 date fields and the seven date-and-time ones in the
  applications, listings, capture, documents and CV forms use them.
- The interview's "was the time changed?" check (#545) compared the raw
  posted field with the time drawn; it now reads the value through the
  widget, which puts the two boxes back together.

Found on the way: Django's `DateInput` writes its value in the language's
first input format, `%d/%m/%Y` in British English, and a date box throws
`19/10/2026` away, so a stored date was drawn as an empty box. The new
widget always writes ISO 8601, which is the box's wire format.

Ranges in a form (a CV entry's start and end, an interview's start and
end) are two day pickers, not one range picker: the fields are two boxes
the server validates as a pair already, often not side by side.

Refs #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The period's name opened the same "Go to the day" box in all four views.
With a script it now opens the picker that fits the view: the months of a
year for the month, a day grid that chooses a whole week for the week, a
day for the day, and a first and a last day for the agenda. The picker
writes its choice into the GET form that was already there and sends it,
so the form stays the way in with no script and both arrive at the same
address. The button keeps `popovertarget` on that form; `data-picker`
retargets it once the script runs.

The agenda had no end day to choose, so a range picker had nothing to
write. `?until=` is its last day now:

- absent, the agenda runs the thirty days it always did, and every old
  address says what it said; thirty days named are the same as none;
- an end before the start is swapped, and an end more than a year off
  (`AGENDA_MAX_DAYS`, 366) is brought back;
- Previous, Next and Today step by the chosen length and keep it, and
  their names say it ("Next 7 days"); the title is "start to end";
- the legend, the agenda's view button, the search (SearchScope keeps
  `until`) and the file download carry it; the other views ignore it;
- the no-script form gains a "To" box beside "From" in the agenda.

Refs #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The last two places that wrote their date boxes by hand:

- The report's month box gets the months of a year beside it, and its
  "From" and "To" boxes one range picker, beside the second, which fills
  both. The boxes are the form as before, with or without a script.
- A table's date filter, in its header and in the block a phone reaches,
  gets one range picker beside its "to" box. A choice fills both boxes
  and fires the second's `change`, which is what the header's htmx
  listens for, so the table narrows once, with both. The boxes keep their
  ids and names.

A swap of the header brought the panel back through htmx's settle, which
copies an element's `style` across with `setAttribute`, and the CSP
refused the placement `app.js` had set on it. The panel now drops that
placement as it closes (#709's trap, on a popover this time).

Two tests learnt that a closed popover is not on the screen: the narrow
block's reflow check skips controls inside one, and the "each name is
posted once" check skips controls with no name, such as the calendar's
month and year lists, which post nothing.

`tests/e2e/test_date_pickers.py` drives each mode by keyboard and
pointer, the date-and-time pair, the range in either order and Escape
after one press, a filter narrowing the table, the server's first
weekday and week numbers, right to left, the phone's sheet with 44-pixel
days, axe in both themes, and the boxes as the form with scripts off.

Refs #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two lines: what was added, and the bug the new widget fixed on the way
(a stored date drawn as an empty box in British English and every other
language whose first input format is not ISO 8601), with a test that
fails on the old widget and passes on the new one.

Closes #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tell the width check that a picker's month is not a table on the page (#933)
Some checks failed
Every Python / Unit tests (Python 3.12) (push) Has been cancelled
Every Python / Unit tests (Python 3.13) (push) Has been cancelled
CI / Browser tests (Chromium) (pull_request) Has been cancelled
CI / Unit tests and coverage (Python 3.14) (pull_request) Has been cancelled
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Has been cancelled
CI / Database tests on PostgreSQL (pull_request) Has been cancelled
CI / Security audit (pull_request) Has been cancelled
CI / Browser tests (Chromium) (push) Has been cancelled
CI / Unit tests and coverage (Python 3.14) (push) Has been cancelled
CI / Checks: lint, migrations, catalogues, settings, built files (push) Has been cancelled
CI / Database tests on PostgreSQL (push) Has been cancelled
CI / Security audit (push) Has been cancelled
ad783cec4a
Every form with a date now carries a date picker, whose month is a
`<table role="grid">` in a closed popover. The #273 check counts any
<table> inside <main> as a table that should have taken the screen, and
flagged twenty-four form pages. The picker's grid is not content laid
out in the column, so the check passes over it.

Refs #933

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 933-date-pickers from ad783cec4a
Some checks failed
Every Python / Unit tests (Python 3.12) (push) Has been cancelled
Every Python / Unit tests (Python 3.13) (push) Has been cancelled
CI / Browser tests (Chromium) (pull_request) Has been cancelled
CI / Unit tests and coverage (Python 3.14) (pull_request) Has been cancelled
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Has been cancelled
CI / Database tests on PostgreSQL (pull_request) Has been cancelled
CI / Security audit (pull_request) Has been cancelled
CI / Browser tests (Chromium) (push) Has been cancelled
CI / Unit tests and coverage (Python 3.14) (push) Has been cancelled
CI / Checks: lint, migrations, catalogues, settings, built files (push) Has been cancelled
CI / Database tests on PostgreSQL (push) Has been cancelled
CI / Security audit (push) Has been cancelled
to fdc243067b
All checks were successful
CI / Unit tests and coverage (Python 3.14) (push) Successful in 11m52s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 2m51s
CI / Database tests on PostgreSQL (push) Successful in 3m19s
CI / Browser tests (Chromium) (push) Successful in 28m58s
CI / Security audit (push) Successful in 40s
Every Python / Unit tests (Python 3.12) (push) Successful in 11m56s
Every Python / Unit tests (Python 3.13) (push) Successful in 11m55s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 13m29s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m17s
CI / Database tests on PostgreSQL (pull_request) Successful in 5m15s
CI / Security audit (pull_request) Successful in 1m10s
CI / Browser tests (Chromium) (pull_request) Successful in 31m13s
2026-10-19 19:25:49 +00:00
Compare
tiagoagueda force-pushed 933-date-pickers from fdc243067b
All checks were successful
CI / Unit tests and coverage (Python 3.14) (push) Successful in 11m52s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 2m51s
CI / Database tests on PostgreSQL (push) Successful in 3m19s
CI / Browser tests (Chromium) (push) Successful in 28m58s
CI / Security audit (push) Successful in 40s
Every Python / Unit tests (Python 3.12) (push) Successful in 11m56s
Every Python / Unit tests (Python 3.13) (push) Successful in 11m55s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 13m29s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m17s
CI / Database tests on PostgreSQL (pull_request) Successful in 5m15s
CI / Security audit (pull_request) Successful in 1m10s
CI / Browser tests (Chromium) (pull_request) Successful in 31m13s
to b99131a08c
Some checks failed
CI / Unit tests and coverage (Python 3.14) (push) Successful in 12m11s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 3m13s
CI / Database tests on PostgreSQL (push) Successful in 3m45s
CI / Security audit (push) Successful in 51s
CI / Browser tests (Chromium) (push) Failing after 30m32s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 12m12s
CI / Security audit (pull_request) Successful in 52s
Every Python / Unit tests (Python 3.12) (push) Successful in 13m6s
Every Python / Unit tests (Python 3.13) (push) Successful in 13m0s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 2m54s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m49s
CI / Browser tests (Chromium) (pull_request) Successful in 29m17s
2026-10-20 06:20:51 +00:00
Compare
Merge main into 933-date-pickers
Some checks failed
CI / Unit tests and coverage (Python 3.14) (push) Successful in 12m34s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 2m48s
CI / Database tests on PostgreSQL (push) Successful in 3m51s
CI / Security audit (push) Failing after 59s
Every Python / Unit tests (Python 3.13) (push) Successful in 12m54s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m53s
CI / Security audit (pull_request) Failing after 48s
CI / Browser tests (Chromium) (pull_request) Successful in 30m25s
CI / Browser tests (Chromium) (push) Successful in 30m19s
Every Python / Unit tests (Python 3.12) (push) Successful in 13m39s
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 13m17s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m10s
fd980dad99
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Merge remote-tracking branch 'origin/main' into HEAD
Some checks failed
CI / Unit tests and coverage (Python 3.14) (push) Successful in 13m46s
CI / Security audit (push) Successful in 1m14s
CI / Browser tests (Chromium) (push) Successful in 31m22s
Every Python / Unit tests (Python 3.12) (push) Successful in 14m26s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 2m56s
CI / Database tests on PostgreSQL (push) Successful in 4m23s
Every Python / Unit tests (Python 3.13) (push) Successful in 13m23s
CI / Browser tests (Chromium) (pull_request) Failing after 42m59s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 15m22s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m10s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 11m50s
CI / Security audit (pull_request) Successful in 1m5s
b4694daca1
Merge remote-tracking branch 'origin/main' into HEAD
Some checks failed
CI / Database tests on PostgreSQL (push) Successful in 4m3s
CI / Security audit (push) Successful in 1m9s
CI / Browser tests (Chromium) (push) Failing after 36m14s
CI / Unit tests and coverage (Python 3.14) (push) Successful in 18m18s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 3m17s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m44s
Every Python / Unit tests (Python 3.12) (push) Successful in 14m34s
Every Python / Unit tests (Python 3.13) (push) Successful in 14m8s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 13m25s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 2m58s
CI / Security audit (pull_request) Successful in 48s
CI / Browser tests (Chromium) (pull_request) Successful in 29m59s
9d0b81ad94
tiagoagueda deleted branch 933-date-pickers 2026-10-22 00:58:38 +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!1017
No description provided.