Skip to content

Store callout block state in localStorage - #20462

Open
aviseth wants to merge 1 commit into
pypi:mainfrom
aviseth:callout-blocks-local-storage
Open

aviseth wants to merge 1 commit into
pypi:mainfrom
aviseth:callout-blocks-local-storage

Conversation

@aviseth

@aviseth aviseth commented Aug 28, 2026

Copy link
Copy Markdown

Fixes #14950

Moves the collapsible and dismissable controllers from callout_block_* cookies
to localStorage, following notification_controller.js. This state is only ever
read by the browser, so sending it up in the headers on every request bought
nothing.

One behaviour change, and it is the interesting part

data-*-setting="global" existed to choose between a path=/ cookie and a
path-scoped one. localStorage is origin-wide, so it no longer means anything and
is removed along with the two template attributes.

What it was doing turns out to matter, though. Every collapsible already set it,
so those are unaffected. No dismissable did — so a dismissed callout was scoped
to the URL directory, which means the same explanatory callout had to be
dismissed again on every project you own. That reads like an accident rather
than a decision, and it now sticks the first time. Happy to preserve the old
scoping if it was deliberate.

Existing cookies are not migrated. The state is "has read this help text", so a
callout reappearing once costs a click, which seemed cheaper than a migration
shim someone has to remember to delete.

Not done

The issue floats converting all three controllers into one. That touches
notification_controller and its key naming too, so I left it — happy to follow
up if you want it.

Testing

npm test: 111 pass under TZ=UTC, both controllers at 100%. npm run lint
and djlint clean.

Both test files are rewritten. The old collapsible test seeded a
callout_block_settings_collapsed cookie against a fixture whose identifier was
project_roles, so the controller never saw it and the assertion passed for the
wrong reason. The new tests fail against the cookie implementation (5 failures)
and pass against this one.

The collapsible and dismissable controllers persisted their state in
`callout_block_*` cookies, so every page load shipped it back to PyPI in the
request headers for state only the browser ever reads. Move both to
localStorage, following the notification controller.

This removes the `setting="global"` attribute along with the cookies. It
existed to choose between a `path=/` cookie and a path-scoped one, and
localStorage is origin-wide, so it no longer means anything. Every collapsible
already set it, so those are unaffected. The dismissable callouts did not, and
their dismissal was therefore scoped to the URL directory - dismissing the same
explanatory callout once per project you own. It now sticks the first time.

Existing cookies are not migrated: the state is "has read this help text", so
the cost of a callout reappearing once is a single click, which is cheaper than
a migration shim someone has to remember to delete.

Refs pypi#14950
@aviseth
aviseth requested review from a team as code owners August 28, 2026 15:59
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.

Replace Collapsible Controller Cookie use with LocalStorage

1 participant