Skip to content

Filter and search by series years, status and summary - #989

Merged
ajslater merged 1 commit into
developfrom
claude/unruffled-kepler-f89be7
Oct 20, 2026
Merged

ajslater merged 1 commit into
developfrom
claude/unruffled-kepler-f89be7

Conversation

@ajslater

Copy link
Copy Markdown
Owner

What

Users can now find comics by the series attributes added in #984–#987.

  • Browser filters: Series Start Year, Series End Year and Series Status. Status has a None row for series with a blank status.
  • Search:
    • start_year: / end_year: take the usual numeric operators, e.g. start_year:1990..1999 or end_year:<2000.
    • status: matches like a text field, e.g. status:ongoing or status:comp*.
    • series_desc: / series_description: / series_summary: search the series summary. A bare search word matches it too.
    • Years and status are ORM columns, like year:. The summary is a new FTS5 column, ComicFTS.series_summary.

Re-index behaviour

  • Migration 0059 drops and recreates codex_comicfts with the new column, as 0049 did, because FTS5 tables can't be ALTERed. The table comes back empty, so the first boot on an existing database re-indexes every comic through the startup SearchIndexSyncTask.
  • Import, inline path: linking a comic to its series writes series_summary along with the series name.
  • Import, summary changes: the importer prunes a series link that hasn't changed, so a re-import whose only change is the series summary would skip the inline path, even for comics in the batch. _bulk_update_models now records series whose summary really changed in FTS_UPDATED_M2MS["series_summary"]. The existing Universe re-sync then rewrites every comic of those series, filtered on comic__series__in with the value from F("comic__series__summary").
  • Full rebuild and incremental sync: SearchIndexerSync annotates series__summary.
  • Tag editor edits: AdminSeriesAttrsView already saves the summary straight to the database. It now also updates the series' ComicFTS.series_summary rows in place, so the new text is searchable at once without bumping Comic.updated_at or queueing a sync.

Changes from the plan

  • 0059's reverse recreates 0049's FTS table instead of a noop. A rollback is left with a working index, where 0049's reverse left no table.
  • Summary changes accumulate into FTS_UPDATED_M2MS with setdefault().update() rather than being assigned. The per-comic phases run once per chunk, so assignment would let a later chunk drop an earlier chunk's series. The existing universes entry still assigns, so it can lose earlier chunks the same way.
  • No comma-stripping: the FK-attribute re-sync skips the .strip(",") the m2m GROUP_CONCAT values get, so summaries keep their edge commas.
  • The choices view now looks up mapped rels (series__start_year, etc.) and stops assuming the field name is a Comic column. That assumption would have raised FieldDoesNotExist and failed the whole availability endpoint.
    • present()/absent() helpers treat a blank "" status as the None choice.
    • The Series Status sub-menu uses the m2m availability rule: two values, or a value and a blank.
  • Status filter values go through a new VuetifySeriesStatusChoiceField. It converts the null code before choice validation, so -1 is accepted and an unknown status still returns 400. Its pk serializer keeps the None row's pk as the int -1, which the frontend's NULL_PKS matches; BrowserChoicesCharPkSerializer would have sent "-1".
  • SettingsBrowserFilters fields moved from step 4 into the migration step, so the suite stays green between steps. Old user-data sidecars get the new schema.sql columns automatically through _reconcile_columns.

Tests

  • tests/test_browser_series_filters.py: availability, choices (including the None row), filtering on series and comic browses, and a settings round trip and validation.
  • tests/test_search_series_fields.py:
    • covers the inline index path, bare and alias summary search, and year/status tokens on publisher, series and comic browses;
    • covers SearchIndexerSync rebuild and incremental sync;
    • checks that a summary-only re-import re-indexes a sibling comic outside the batch. I confirmed this test fails with the hook disabled.
  • tests/test_admin_series_attrs.py: a summary edit updates only that series' index rows; a status-only edit leaves them alone.
  • tests/importer/test_basic.py: fixtures gain series_summary.

Verification

  • make build-choices, make fix, make lint, make ty all clean, and makemigrations --check reports no changes.
  • make test passes: 1734 Python passed with 1 xfailed, and 1033 frontend tests passed. make test-frontend also passes on its own.
  • Checked by hand in a fresh-DB dev stack with three seeded series:
    • The filter menu lists Series End Year, Series Start Year and Series Status, and Status offers None / Completed / Ongoing. Choosing None narrows the publisher to the blank-status series.
    • start_year:1990..1999, status:ongoing and a bare summary word each return only the matching series' comic.
    • A series summary edited in the tag editor (POST /admin/series-attrs) is found by a search for its new word straight away.

🤖 Generated with Claude Code

Browser filters for the series start year, end year and status (with a
None row for a blank status), and search-box support for all four:
start_year:/end_year:/status: are ORM columns like year:, and the series
summary becomes a ComicFTS column so bare terms match it.

Migration 0059 adds the filter-settings columns and rebuilds the FTS5
table with series_summary, so the first boot re-indexes every comic.
The importer prunes unchanged series links, so a series whose summary
changes now re-indexes all its comics through the FK re-sync path, and
the tag editor's database-only summary edit updates the index rows in
place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ajslater
ajslater merged commit c353b18 into develop Oct 20, 2026
9 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