Skip to content

explorer: sync #facetNote on URL deep-link + mode transitions (#234 step 1)#235

Merged
rdhyee merged 1 commit into
isamplesorg:mainfrom
rdhyee:fix/facetnote-url-load
May 23, 2026
Merged

explorer: sync #facetNote on URL deep-link + mode transitions (#234 step 1)#235
rdhyee merged 1 commit into
isamplesorg:mainfrom
rdhyee:fix/facetnote-url-load

Conversation

@rdhyee
Copy link
Copy Markdown
Contributor

@rdhyee rdhyee commented May 23, 2026

Summary

Roadmap step 1 of #234 (filter-semantics architectural direction). Pure bug fix, no behavior change beyond making the cluster-mode honesty note (#facetNote) honest in two cases where it had drifted out of sync.

  • URL deep-link: arriving at /explorer.html?material=… restored checkbox state via setCheckedValues, which doesn't fire the change event, so #facetNote stayed hidden even with active filters. A user opening a shared URL saw dimmed cluster dots with no explanation.
  • Mode transitions: the note was only updated inside handleFacetFilterChange. A user in cluster mode with the note showing kept seeing it after zooming to point mode (and vice versa).

Fix: extract syncFacetNote() as the single source of truth for the visibility invariant

visible ⇔ (any facet active) ∧ (mode === 'cluster')

and call it from the four state-mutation sites:

  • facetFilters cell (URL deep-link restore)
  • handleFacetFilterChange (user toggles a facet checkbox)
  • enterPointMode / exitPointMode (mode transitions)

Test plan

  • New spec tests/playwright/facetnote-url-load.spec.js:
    • cluster mode + ?material=<uri>#facetNote visible
    • cluster mode + no facet params → #facetNote hidden (negative control)
  • Fault-injection: confirmed the new spec FAILS against pre-fix code (expected: 'block', received: 'none') and PASSES against the fix.
  • Full tests/playwright/url-roundtrip.spec.js (5 tests, includes point-mode deep-link and cross-context round-trip) passes — no regression.
  • Manual: open /explorer.html?material=<any URI> and confirm note appears under the cluster legend.

Notes for review

This PR is intentionally scoped to step 1 of the #234 roadmap (the 1–2 hour bug fix). It does not touch:

  • applyQueryToFacetFilters itself (the URL-param read path is unchanged)
  • The refreshFacetCounts cross-filter live-query path (B1 work, step 3)
  • The cluster-mode H3-summary-vs-filter honesty story (C3 work, step 8)

The roadmap synthesis with sign-off and revised sequencing is in issue #234.

🤖 Generated with Claude Code

@rdhyee
Copy link
Copy Markdown
Contributor Author

rdhyee commented May 23, 2026

Code review result: no code-level issues found in this PR.

I checked the PR patch around the centralized syncFacetNote() logic and the new Playwright regression spec. The implementation matches the intended invariant: facet note visible only when a facet filter is active and Explorer is in cluster mode.

Validation run locally:

  • quarto render explorer.qmd passed
  • git diff --check upstream/main...HEAD passed
  • CI=1 ./node_modules/.bin/playwright test tests/playwright/facetnote-url-load.spec.js tests/playwright/url-roundtrip.spec.js --project=chromium --reporter=line passed: 7 passed in 1.3m

Merge blocker: GitHub currently reports mergeable=CONFLICTING / mergeStateStatus=DIRTY, and git merge-tree HEAD upstream/main confirms a content conflict in explorer.qmd. This needs a rebase or conflict resolution before merge.

…esorg#234 step 1)

Restoring facet checkboxes from `?material=…&context=…` runs through
`setCheckedValues`, which does not fire the `change` event — so the
cluster-mode honesty note (`#facetNote`, "filter takes effect at
neighborhood zoom") stayed hidden on shared deep-links even with active
filters. A user arriving via a URL saw dimmed cluster dots with no
explanation.

While there, the same visibility logic was missing from the mode
transitions: a user in cluster mode with the note showing kept seeing it
after zooming to point mode, and vice versa.

Fix: extract `syncFacetNote()` as the single source of truth for the
visibility invariant

    visible ⇔ (any facet active) ∧ (mode === 'cluster')

and call it from the four state-mutation sites:

  - facetFilters cell (URL deep-link restore)
  - handleFacetFilterChange (user toggles a facet checkbox)
  - enterPointMode / exitPointMode (mode transitions)

Validation:

  - New spec `tests/playwright/facetnote-url-load.spec.js` covers the
    deep-link case (note visible with `?material=`) and the negative
    control (note hidden with no facet params). Confirmed the spec
    fails against pre-fix code and passes against the fix.
  - Full `url-roundtrip.spec.js` (5 tests, including point-mode
    deep-link and back/forward) passes — no regression.

Roadmap step 1 of isamplesorg#234.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rdhyee rdhyee force-pushed the fix/facetnote-url-load branch from 40555bd to 230e763 Compare May 23, 2026 02:38
@rdhyee
Copy link
Copy Markdown
Contributor Author

rdhyee commented May 23, 2026

Rebased onto upstream/main (was branched off a stale fork-main). Single conflict was in exitPointMode: upstream replaced the cachedBounds = null; … cache-invalidation block with a ++requestId stale-guard (#221 round 2). Resolution kept upstream's version and inserted syncFacetNote() right after the pushState call, before the requestId bump.

Re-ran both suites against the rebased commit (230e763):

✓ tests/playwright/facetnote-url-load.spec.js (2 tests)
✓ tests/playwright/url-roundtrip.spec.js (5 tests)
7 passed (1.3m)

mergeable=MERGEABLE now per gh pr view. Thanks for the catch, codex.

@rdhyee rdhyee merged commit 88c0191 into isamplesorg:main May 23, 2026
1 check 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