Skip to content

Fix URL parameter leakage from listing pages to DLP + extend listing of parameters on DLP for permalinking#2772

Draft
yarikoptic wants to merge 9 commits into
dandi:masterfrom
yarikoptic:bf-1460-urlparams
Draft

Fix URL parameter leakage from listing pages to DLP + extend listing of parameters on DLP for permalinking#2772
yarikoptic wants to merge 9 commits into
dandi:masterfrom
yarikoptic:bf-1460-urlparams

Conversation

@yarikoptic
Copy link
Copy Markdown
Member

@yarikoptic yarikoptic commented Apr 5, 2026

Summary

Fixes #1460 — listing query params (page, sortOption, sortDir, showDrafts, showEmpty, search, pos) were leaking into Dandiset Landing Page URLs when navigating from listing/search pages, producing ugly unshareable URLs like /dandiset/000027?page=2&sortOption=0&sortDir=NaN&showDrafts=true&showEmpty=false.

  • Introduce a Pinia store (listingContext) to hold listing navigation context in memory, so the DLP "page through dandisets" feature works without URL pollution
  • Stop spreading $route.query into DLP links in DandisetList.vue; save position to store via @click instead
  • Add a defensive beforeEach router guard that strips listing params from the dandisetLanding route

Commits

  • 1e28cbd Add e2e tests for URL parameter isolation between listing and DLP
  • 280c8b1 Fix URL parameter leakage from listing pages to DLP

Test plan

Didn't do the dance locally, might just test on preview:

  • Set up local dev instance (Django + Vue) and run cd e2e && npx playwright test tests/urlParams.spec.ts
  • Verify the e2e tests FAIL when run against only the first commit (tests without fix)
  • Verify the e2e tests PASS when run against both commits (tests + fix)
  • Manual: navigate listing → DLP → confirm clean URL in browser bar
  • Manual: use DLP prev/next pagination → confirm URL stays clean
  • Manual: navigate directly to /dandiset/XXXXXX → confirm no pagination controls shown
  • Manual: browser back from DLP → confirm listing state preserved
  • Run full existing e2e suite to check for regressions

🤖 Generated with Claude Code

yarikoptic and others added 6 commits April 4, 2026 14:12
These tests verify that listing-specific query params (page, sortOption,
sortDir, showDrafts, showEmpty, search, pos) do not leak into Dandiset
Landing Page URLs when navigating from listing/search pages.

Expected to FAIL on current code and PASS after the fix in the next commit.

Ref: dandi#1460

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
Listing query params (page, sortOption, sortDir, showDrafts, showEmpty,
search, pos) were spread into DLP URLs via `...$route.query` in
DandisetList.vue, producing ugly unshareable URLs like:
/dandiset/000027?page=2&sortOption=0&sortDir=NaN&showDrafts=true&...

Fix: move listing navigation context into a Pinia store so the DLP
"page through dandisets" feature works without polluting the URL.
Add a defensive router guard to strip any listing params that reach
the DLP route.

Fixes: dandi#1460

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
Tests that clicking tabs updates the URL ?tab= param, that navigating
directly to ?tab=how-to-cite opens the correct tab, and that the param
survives page reload.

Expected to FAIL on current code and PASS after the next commit.

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
The DLP now reflects the selected tab in the URL so links to specific
tabs are shareable and survive page reload.  The default Overview tab
uses no param to keep the base URL clean.

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
Tests that ?format= reflects the selected citation style on the
How to Cite tab, and that ?overlay=meditor opens/closes the metadata
editor dialog.

Expected to FAIL on current code and PASS after the next commit.

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
- ?format=bibtex (etc.) on How to Cite tab reflects the selected
  citation style; default APA uses no param for clean URLs
- ?overlay=meditor opens the metadata editor dialog on page load
  and is removed when the dialog closes

Together with ?tab=how-to-cite, this allows full DLP state recall:
/dandiset/000027/draft?tab=how-to-cite&format=harvard
/dandiset/000027/draft?overlay=meditor

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
@yarikoptic
Copy link
Copy Markdown
Member Author

yarikoptic commented Apr 6, 2026

before I proceed, query to @dandi/archive-maintainers and @bendichter (potentially for AI PR review ? ;) ) on either I should strive to polish it etc for this direction to not only leak seemingly unused pos= (see below) but also to expose info about position in DLP. Ideally should extend with info on the tab within meditor!

https://deploy-preview-2772--sandbox-dandiarchive-org.netlify.app/dandiset/214527/draft?tab=how-to-cite&format=harvard&overlay=meditor

image

edit -- detected issue, likely due to killing pos -- reload by that url removes prev/next navigation

@yarikoptic yarikoptic added UX Affects usability of the system client/meditor Issues with the metadata editor (meditor) client/dlp Issues with the Dandiset Landing Page (DLP) labels Apr 6, 2026
@bendichter
Copy link
Copy Markdown
Member

@yarikoptic tbh I didn't know about those buttons for stepping through dandisets and honestly I don't think they are that useful. I would be in favor of simply removing that feature and adding params for DLP state (?tab=, ?format=, ?overlay=). That would turn this from a complex state-management change into a straightforward deletion + a small addition of DLP permalink params.

@yarikoptic
Copy link
Copy Markdown
Member Author

@yarikoptic tbh I didn't know about those buttons for stepping through dandisets and honestly I don't think they are that useful.

I think they might be useful to review results of the search so you could go through them one by one. And that seems to be how they work when there is search results, e.g. try on https://dandiarchive.org/dandiset/search?search=halchenko

But even there it is buggy as pos parameter doesn't change :-/ and I followed up on #2364 with more of odd behaviors. IMHO it at large boils down to storing current indexing result in session variable ("full" as a list of dandiset ids -- should work for any reasonable future) and then referring to it and index within it -- both (search result id + position) could then go into URL params. Let's see if claude could figure smth out there...

yarikoptic and others added 3 commits April 6, 2026 11:22
Replace the Pinia listingContext store with browser history.state to
carry search/filter context between listing and DLP.  Only ?pos= appears
in the URL (lightweight, bookmarkable position indicator); the full
listing context (sort, search, filters) travels invisibly via
history.state and survives page reload.

The listing page now caches identifiers from the current page (up to 8)
in history.state so prev/next within that window is instant — no extra
API call to discover the next identifier.  Outside the cache window the
DLP falls back to a single API call.

Removes web/src/stores/listingContext.ts (no longer needed).

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
- Make history.state reads reactive (via computed + route.fullPath dep)
  so the listing context updates correctly when navigating between
  dandisets via prev/next
- Sync page ref with route.query.pos on route changes
- Preserve ?search= on DLP URLs so the search bar shows the query
  context (matches original master behavior)
- Use fully programmatic navigation in DandisetList (remove :to binding)
  to avoid double-navigation with @click.prevent on router-link
- Update e2e tests: search and pos are legitimate DLP params
- Fix TypeScript HistoryState compatibility for ListingCtx

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
- Fix meditor button selector: use getByText("Metadata") instead of
  getByRole("button") since Vuetify v-list-item has role="listitem"
- Fix meditor dialog selector: use .v-overlay--active .v-card which
  works reliably in Vuetify 3
- Add .stop to StarButton @click to prevent event bubbling to the
  parent list-item's @click handler (would cause unwanted navigation)

Co-Authored-By: Claude Code 2.1.92 / Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client/dlp Issues with the Dandiset Landing Page (DLP) client/meditor Issues with the metadata editor (meditor) UX Affects usability of the system

Projects

None yet

Development

Successfully merging this pull request may close these issues.

params in dandiset URL

2 participants