Highlight active search constraints on results pages - #7159
Open
roed-math wants to merge 6 commits into
Open
Conversation
On search results pages, inputs that constrain the displayed query are now visually distinguished with a subtle yellow tint so users can see at a glance why results are filtered. What/why: constraint-eligible search boxes render a `search_constraint` class on results pages, plus `search_active` when their value in `info` is non-empty; CSS tints active text/select backgrounds and rings active checkboxes. Display controls (count, sort/column selectors, DynStats variable boxes, and diagram axis/color selectors) set `is_constraint = False` so they are never highlighted. Hidden inputs are untouched. A small JS hook keeps the highlight live as the user edits, pairing with the existing stale/fresh button signal. How verified: flask test client across elliptic curves, number fields, abstract groups, abvar/Fq (checkbox), modular-curve/groups diagram search, and DynStats; browse pages render unchanged; direct unit checks of every box subclass; all 19 color schemes resolve the new `search_active_background` key; /style.css renders; ECQ diagram-search and CMF dynamic-stats tests pass; pyflakes clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Emit exactly one class attribute per rendered input. Class names now go through a first-class `classes` argument on SearchBox, merged with `advanced` and the `search_*` classes and deduplicated; any class written into `extra` is merged too, so a tag can no longer end up with two class attributes (invalid HTML, and browsers discard one of them, which was making the feature silently fail on the hypergeometric and CMF forms). The existing `extra=['class=...']` uses migrate to `classes`, and `extra` is copied rather than shared. Stop marking presentation-only controls as constraints. The trace and Euler tables' `n`, `n_primality` and `view_modp` choose which columns are displayed, not which rows match, so they are no longer highlighted; this includes the `n_primality=primes` that set_Trn inserts on every trace search. `an_modulo` is contextual, since it only enters the query through the trace constraints, so `is_constraint` now also accepts a function of `info`. Keep `search_active` describing the results on screen. The JS that retagged inputs as the user typed is gone, so the highlight no longer claims a constraint that has not been submitted; the search button's existing fresh/stale signal still reports that the form was edited. Mark active checkboxes with a box-shadow ring rather than an outline, so the keyboard focus indicator survives, in a darker shade with usable contrast, and tint text inputs with background-color so the shorthand does not reset a background image. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A select beside a text box usually says how to read that box, and is handed to a @search_parser function as its mode. Those return immediately when their field is empty, so such a select cannot affect the query on its own; TextBoxWithSelect now treats its select as constraining only once the text box it qualifies has been filled in. Six selects are read directly while parsing instead, and so do restrict the results by themselves: the level type in classical modular forms and modular curves, the conductor type in elliptic curves and mod-l Galois representations, and the two CMF parities, which usually arrive with their text boxes empty because simult_change() submits both at once. Those pass is_constraint=True. Modular curves matters in particular because modcurve_browse.html links straight to ?level_type=... searches. The hypergeometric prime and the abelian variety geometric-decomposition checkbox are the same shape: both only pick which column a partner box is matched against, so they are gated on those boxes rather than highlighted whenever set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The level type offers "prime squared" and "powerful", but common_parse recognized neither, so both fell to the invalid-type branch. That branch flashes an error and returns a redirect, and both callers use the query common_parse builds while ignoring what it returns, so the redirect was dropped and the search ran with no condition on the level: picking either option showed an error and then every level anyway. mf_newforms and mf_newspaces already have level_is_prime_square and level_is_powerful, so the two values only needed adding to the list. The invalid branch now raises ValueError after the flash, the way the rest of this module reports bad input, so an unrecognized type stops the search rather than quietly running it unfiltered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CheckBox renders value="yes", but abvar's common_parse switched to the geometric columns only on "on", the value a browser supplies when a checkbox has no value attribute. Ticking "Use geometric decomposition" in the form and searching was therefore indistinguishable from leaving it alone: the dimension, number field and Galois group inputs went to dim*, number_fields and galois_groups rather than their geometric counterparts. Accept both values so hand written "on" links keep working. Test the query common_parse builds rather than the rows that come back, so the three retargeted field families are pinned without depending on what is currently in the database. Also tighten the prime square predicate in test_level_types, which as written also accepted fourth and sixth powers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
I like this addition! Just a note that on genus 2 curve searches, the two include/exclude boxes never get highlighted. That might be fine (as the box immediately above each of them does change colors) but wanted to point it out in case that was not intended. |
Member
|
I also like it. I looked at it with a blue color scheme. Have others looked with others? |
Member
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2770.
On search results pages, the inputs that are actually constraining the results being displayed are now tinted (text boxes and selects) or ringed (checkboxes), so it is visible at a glance why the results are filtered.
How it works
Marking happens server-side in the shared
search_boxes.pymachinery, so every section gets it.SearchBox._attrs(info)emits exactly oneclassattribute per input, merging the box's own classes withadvanced,search_constraint(this input constrains the results when filled in) andsearch_active(it is filled in right now). Class names are passed with a first-classclasses=argument rather than hand-written intoextra, since twoclassattributes on a tag is invalid HTML and browsers silently discard one of them.search_activedescribes the search that produced the rows on screen, and is deliberately server-owned: nothing rewrites it as the user edits the form, so the highlight never claims a constraint that has not been submitted. The existing fresh/stale "Search again" button remains the signal that the form has been edited.What counts as a constraint
is_constraintis a bool, or a function ofinfofor boxes whose role depends on the rest of the search.Not constraints: result count, sort and column controllers, dynamic-statistics variable boxes, diagram axis/colour/count boxes, hidden inputs, and the trace and Euler table display controls (
n,n_primality,view_modp) in classical modular forms and L-functions. That last group includes then_primality=primesthatset_Trninserts on every trace search, which would otherwise look filled in when the user never touched it.Contextual, via a callable:
an_modulocounts only when there are trace constraints for it to turn into congruences, not when it merely drivesview_modp=reductions.pcounts only when one of theAp,Bp,Apperp,Bpperpboxes is filled, since it only picks which columns those compare against.TextBoxWithSelect) counts only once that text box is filled. This is safe becauseSearchParser.__call__returns immediately on an empty field, so a select handed to a@search_parserasmode=cannot affect the query alone. Six selects are read directly during parsing and do constrain by themselves, so they opt out withis_constraint=True.Colours
Two colour-scheme keys, so both stay overridable per scheme:
search_active_background(#FFF9C4) for the tint andsearch_active_ring(#F9A825) for checkboxes, which are rendered natively and cannot be tinted. The ring usesbox-shadowrather thanoutlineso the browser's keyboard focus indicator survives. The tint usesbackground-colorrather than thebackgroundshorthand so it cannot reset a background image. The exact shades are a maintainer taste call and easy to tune.Two bugs found and fixed along the way
Both were pre-existing and unrelated to the highlighting, but each was directly in the path of deciding whether an input constrains the results.
common_parserecognised neither, so both fell to the invalid-type branch. That branch flashes an error and returns a redirect, and both callers use the querycommon_parsebuilds while discarding its return value, so the search then ran with no condition on the level at all.mf_newformsandmf_newspacesalready havelevel_is_prime_squareandlevel_is_powerful, so the two values only needed adding to the list. The invalid branch now raisesValueErrorafter the flash, the way the rest of that module reports bad input.CheckBoxrendersvalue="yes"but the parser tested== "on", so ticking the box in the form did nothing: the search used the ordinarydim*,number_fieldsandgalois_groupscolumns instead of the geometric ones. It now accepts both values, keeping hand-writtenonlinks working.Tests
New
SearchBoxTestinlmfdb/tests/test_utils.pycovers the rendering rules. Integration assertions intest_hgm.py,test_cmf.py,test_cmf2.py,test_lfunctions.py,test_modular_curves.pyandtest_av.pycheck the rendered pages, plus directcommon_parsequery-construction tests for the geometric decomposition checkbox. Tests compare class tokens as sets through a shared helper that asserts there is at most oneclassattribute, so nothing depends on ordering. No new test files, so the CI count is unchanged.Ported from roed-math#23, where the full write-up and comment history live.
🤖 Generated with Claude Code