Skip to content

feat(ui): offer "that year to present" on /mypapers and /dois/mytags - #576

Merged
robsv merged 1 commit into
mainfrom
feat-year-to-present
Oct 22, 2026
Merged

robsv merged 1 commit into
mainfrom
feat-year-to-present

Conversation

@robsv

@robsv robsv commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

The publishing-year pulldown offered a single year or all years, with no way to ask for recent work. Each year now carries a second, narrower target linking to "-present" as well as the year alone, under a two-column heading so the second one is explained once rather than guessed at twenty times.

The year itself stays the wide, primary target, so a reader who ignores the right-hand column gets exactly the behaviour they had before. "All" keeps a single target, since "All to present" is nonsense.

OPT-IN per page, via year_pulldown(to_present=True). The value travels through 143 year == 'All' checks and 18 regex queries, and a page that has not been taught to read a range must never be offered one. Three call sites opt in; the other 62 pulldowns render byte-identical markup.

Spelled "-present", not "2024-". Both "^2024-" and "^2024+" are VALID regexes that quietly match a single year, so an unconverted page would have shown one year's results under a button claiming a range. "-present" matches nothing anywhere it is not understood, which is the failure worth having.

Four shared helpers - parse_year, year_clause, year_includes, year_label - because /dois/mytags filters in Mongo and /mypapers filters in Python. Two implementations of one rule is how a selection comes to mean different things on two pages; verified against 3,327 MouseLight records that both paths agree on every selection. A range is {"$gte": "2024"}: jrc_publishing_date is an ISO string, so that is a date comparison, and unlike a regex it cannot be coaxed into matching everything.

Fixes an injection on the way. The filter was {"$regex": "^" + year} with the path segment interpolated raw, so /dois/mytags/.* matched every DOI in the collection. parse_year refuses anything that is not "All", four digits, or "-present". NOTE: nine other sites still build that regex the same way - /tag//.* among them - and are untouched here.

A range has no upper bound, deliberately. One DOI is currently dated tomorrow (early-online papers carry future publishing dates), and capping at today would make "2026 to present" exclude a paper that "2026" - the target immediately to its left in the same menu row - includes.

Deploy: api/ -> OpenShift, ocbuild dis-utilities 120.132.0
Writes-to-production: none
Routes: no new routes; /dois/mytags/ and /mypapers?year= additionally accept "-present", and reject anything that is not a recognised selection rather than passing it to a regex
Sync-interaction: none

@stuarteberg

The publishing-year pulldown offered a single year or all years, with no way to
ask for recent work. Each year now carries a second, narrower target linking to
"<year>-present" as well as the year alone, under a two-column heading so the
second one is explained once rather than guessed at twenty times.

The year itself stays the wide, primary target, so a reader who ignores the
right-hand column gets exactly the behaviour they had before. "All" keeps a
single target, since "All to present" is nonsense.

OPT-IN per page, via year_pulldown(to_present=True). The value travels through
143 `year == 'All'` checks and 18 regex queries, and a page that has not been
taught to read a range must never be offered one. Three call sites opt in; the
other 62 pulldowns render byte-identical markup.

Spelled "-present", not "2024-". Both "^2024-" and "^2024+" are VALID regexes
that quietly match a single year, so an unconverted page would have shown one
year's results under a button claiming a range. "-present" matches nothing
anywhere it is not understood, which is the failure worth having.

Four shared helpers - parse_year, year_clause, year_includes, year_label -
because /dois/mytags filters in Mongo and /mypapers filters in Python. Two
implementations of one rule is how a selection comes to mean different things
on two pages; verified against 3,327 MouseLight records that both paths agree
on every selection. A range is {"$gte": "2024"}: jrc_publishing_date is an ISO
string, so that is a date comparison, and unlike a regex it cannot be coaxed
into matching everything.

Fixes an injection on the way. The filter was {"$regex": "^" + year} with the
path segment interpolated raw, so /dois/mytags/.* matched every DOI in the
collection. parse_year refuses anything that is not "All", four digits, or
"<year>-present". NOTE: nine other sites still build that regex the same way -
/tag/<name>/.* among them - and are untouched here.

A range has no upper bound, deliberately. One DOI is currently dated tomorrow
(early-online papers carry future publishing dates), and capping at today would
make "2026 to present" exclude a paper that "2026" - the target immediately to
its left in the same menu row - includes.

Two defects found in review after the pages worked:

- dis_responder.year_pulldown SHADOWS the dis_html one, adding the request
  coupling that keeps dis_html request-free. Callers reach the wrapper, so the
  new argument was a TypeError at render time on /mypapers/full. The wrapper
  now passes it through, and a test asserts it accepts every parameter the
  inner function has - the defect class, not the instance.
- The wrapper derives the year from the URL, where it arrives raw, so the
  button read "2024-present" instead of "2024 to present" on reload. Labelled
  in the derivation branch only; an explicit `selected` is passed through
  untouched.

And one in the prose: the empty state said "no publications in that year" after
a range was chosen, which reads as though the range had been ignored.

Deploy: api/ -> OpenShift, ocbuild dis-utilities 120.132.0
Writes-to-production: none
Routes: no new routes; /dois/mytags/<year> and /mypapers?year= additionally accept "<year>-present", and reject anything that is not a recognised selection rather than passing it to a regex
Sync-interaction: none
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@robsv robsv self-assigned this Oct 22, 2026
@robsv robsv added the enhancement New feature or request label Oct 22, 2026
@robsv
robsv merged commit 4aa1a78 into main Oct 22, 2026
2 checks passed
@robsv
robsv deleted the feat-year-to-present branch October 22, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant