Skip to content

feat: Neuroglancer Views cart pipeline (PR 5a, ngviews-05a-cart-pipeline) - #426

Draft
allison-truhlar wants to merge 14 commits into
ngviews-04-views-pagefrom
ngviews-05a-cart-pipeline
Draft

feat: Neuroglancer Views cart pipeline (PR 5a, ngviews-05a-cart-pipeline)#426
allison-truhlar wants to merge 14 commits into
ngviews-04-views-pagefrom
ngviews-05a-cart-pipeline

Conversation

@allison-truhlar

Copy link
Copy Markdown
Collaborator

Neuroglancer Views — PR 5a (ngviews-05a-cart-pipeline)

Stacked on #425 (ngviews-04-views-page). Read-only scope. PR 5 was split into 5a + 5b; this is 5a — the file-browser → Layer Cart → saved View pipeline. (5b will add the right-edge Properties↔Cart rail, the Data Link delete-409 dialog, and Properties "Appears in N Views".)

What's in it

  • CartProvider hoisted app-wide (MainLayout, inside PreferencesProvider; removed the route-scoped copy) so the file browser can use the cart.
  • Checkout engine:
    • getOmeZarrChannels(url) — lazy channel list for a dataset.
    • buildViewState(datasets) — merges per-dataset omezarr-helper generated states into one ng_state object + ViewLayerInput[] (decode + concat layers; one dataset's failure is skipped, not fatal).
    • useCartCheckout() — resolves/creates one Data Link per unique (fsp_name, path) (shared datasetKey + normalizeFspRootPath so no duplicate links), builds state, createView.
    • CreateViewButton — consent-gated batch checkout (reuses areDataLinksAutomatic; "don't ask again" toggles the pref). Reused by both entry points.
  • Entry points:
    • Row "Add to Neuroglancer cart" (folders only).
    • Floating selection bar — first consumer of PR 3's checkedFiles: Add N to cart · New View from selection · Clear.
    • Full Layer Cart tab — datasets grouped, expandable to lazy-load + select channels (MT Collapse), Create View + Clear cart. CartContext gained a batch removeManyFromCart.

Notable review catches (fixed on-branch)

  • One broken/stale cart dataset no longer aborts the whole checkout build (per-dataset try/catch).
  • addToCart now awaited + toast.error on failure (was a false-success toast + unhandled rejection).
  • Fixed a stale-closure bug where removing a multi-entry dataset only dropped the last entry (root-caused with a batch removeManyFromCart).
  • Base+channel double-layering: a dataset's base entry is dropped at checkout when specific channels are selected.

Deferred / carry items

  • sharing_mode is a stored label only (not enforced) — per PR 2.
  • Known ceiling: synthesized "Channel N" labels don't name-match generated layers, so buildViewState's channel filter falls back to keep-all (over-inclusive, never drops/crashes); omero-labelled datasets filter correctly. Accepted for read-only-first.
  • Cart-created Data Links don't honor a custom dataLinkSubpathMode prefix (cosmetic; links still work). Follow-up.
  • Channel expansion in the cart tab is disabled for a dataset that has no Data Link yet (no link created just to browse).

Testing

  • Full frontend suite green: 343/343. New tests: getOmeZarrChannels, viewCheckout (incl. skip-on-throw + channel-narrow), useCartCheckout, CreateViewButton, FileBrowserCartItem, SelectionBar, CartTab, CartContext. node-prettier-check + node-eslint-check clean (one pre-existing unrelated lint warning).
  • Note: node-check shows 5 pre-existing type errors in files 5a does not touch (base-branch types mismatch) — reconcile at the stack level.

Built via subagent-driven development from docs/superpowers/plans/2026-08-07-ngviews-05a-cart-pipeline.md.

Wire useCartContext into FileBrowser and add a context-menu item that
adds the right-clicked folder to the Neuroglancer cart, guarded by the
same is_dir && !is_symlink condition the existing folder-only menu
items (Set favorite, Convert to OME-Zarr) already use.

Also add CartProvider to the shared test harness (test-utils.tsx),
matching its real nesting in MainLayout -- FileBrowser is a shared
surface and now depends on CartContext, which the harness didn't
provide, breaking FileTableSelectColumn.test.tsx.
The "Add to Neuroglancer cart" menu item called addToCart without
awaiting it and toasted success unconditionally, so a rejected
preference mutation left an unhandled rejection and a false-positive
success toast. Await it in a try/catch and mirror the sibling
Set favorite item's error-toast pattern.
removeFromCart in a loop closed over the same pre-loop cart snapshot on
every awaited iteration, so removing a multi-entry dataset (base + checked
channels) only persisted the last removal - earlier entries got
reintroduced. Add removeManyFromCart (single filter, single persist) and
use it from CartDatasetRow's remove-all. Also stop a channel-only entry's
label from leaking into the dataset row header when no base entry exists.
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