Repository navigation
feat: browse files from the viewer sidebar, and remove datasets from Views - #465
Open
allison-truhlar wants to merge 26 commits into
Open
allison-truhlar wants to merge 26 commits into
allison-truhlar wants to merge 26 commits into
Conversation
allison-truhlar
marked this pull request as ready for review
October 9, 2026 16:42
allison-truhlar
added this pull request to stack #429
October 9, 2026 16:42
allison-truhlar
added a commit
to JaneliaSciComp/fileglancer-hub
that referenced
this pull request
Oct 9, 2026
Dev runs the ngviews prerelease so the editable Views work in JaneliaSciComp/fileglancer#465 can be tested against real data and Okta before release. Co-Authored-By: Claude Fable 5.1 <[email protected]>
…a sidebar Extract the file selector dialog's browser (breadcrumbs, toolbar, file list, path field) into FileSelectorBrowser so the viewer sidebar renders the same widget. The table gains an optional checkbox column for picking several datasets to add to the Layer Cart, and a failed Load more keeps its loaded rows.
The sidebar splits into Add data and Layer Cart tabs, both kept mounted so switching keeps the browser's folder and checks, and sits in a resizable panel beside the viewer like the Browse page's side panels.
Neuroglancer splits a multichannel auto layer into per-channel layers on load, and the next Save stores the split state. Counting saved layer rows made the number jump from one per dataset to one per channel without any data being added. Count distinct datasets instead, using the same de-dupe as the Sources column, and rename the column to Datasets.
The embedded viewer's sidebar hid how many datasets were in the cart until you opened the Layer Cart tab. Show the count as a badge on the tab, using the same dataset count as the toolbar's cart badge. The badge stays rendered, hidden, when the cart is empty so the trigger's width doesn't change under the tab indicator.
POST /api/neuroglancer/views/{short_key}/remove-sources drops each listed
dataset's Neuroglancer layers and view_layers rows, unsupported and broken
ones included, in one commit.
The unsupported-source warning icon is now a button that opens a remove confirmation, and a new "Remove datasets" row action opens a checklist of the View's datasets. The Sources column's de-dupe and path formatting move into getViewSources and useSourceDisplayPath so the dialog shares them.
Every View is readable through its read link and sharing_mode is not enforced, so a per-row sharing label suggests a choice that does not exist yet. The Sources column starts 420px wide to take over the freed space.
Fixed pixel tracks made the table scroll sideways on narrower screens even before anyone resized a column. The tracks now use minmax so they start at their full width and shrink toward a floor, and Sources switches to a fixed width only after the user drags it. TableCard rows use min-w-min instead of min-w-max so minmax tracks can shrink at all; the Views table is the only gridColsStyle caller.
Between 768px and 900px, the pagination controls and the search input shared one cramped row in every TableCard. Stacking them up to 900px gives the search the full card width.
A long file name pushed the name column wider than its container, so the table overflowed narrow layouts like the Add data sidebar. A fixed table layout lets the name column take the width the other columns leave and truncate the rest.
The name link rendered inline, so truncate had no width to clip against and a long name overflowed its cell. Rendering it as a block lets it clip with an ellipsis.
The View page reads the Neuroglancer iframe's window.viewer, which browsers allow only when the iframe shares the page's origin. The docs mentioned that rule but only described the local-development passthrough, so a deployment had no guidance on how to meet it. Setting up fileglancer-dev showed two gaps: nginx serves /neuroglancer/ before the app sees the request, so FGC_NEUROGLANCER_URL silently does nothing there, and Vite bundles frontend/viewers.config.yaml whenever it exists on disk, so a developer's local override once shipped in a dev build. Document the production, dev-host, and local setups side by side, with the nginx proxy block that dev uses and the check that confirms it works. Co-Authored-By: Claude Fable 5.1 <[email protected]>
…Go to the Add data browser The file selector table showed every row at the zones and zone levels as "Folder". Those rows now read "Zone" and "File share". The Views Add data sidebar gets the editable path field back, placed between the toolbar and the file table with a Go button. The file selector dialog keeps its path field at the bottom.
Pull the segment-boundary regex and the source-URL walk out of rewriteDataLinkSegment into segmentPattern and mapSourceUrls, and add layerUsesSegment on top of them. The viewer's Sources tab needs to map layers to datasets the same way the server's ngstate.layer_uses_segment does, without rewriting anything. No behavior change to rewriteDataLinkSegment.
DatasetRow renders the header, layer-status icon and axis table for one
dataset, with an onRemove callback and an optional renderChannels slot.
CartDatasetRow becomes a wrapper that keeps the cart removal and the
channel checkboxes.
DatasetRow takes a tense ("Will load" / "Loads as") so the same row can
describe datasets already in a View.
Unsupported sources have no Neuroglancer layer, so reconciling view_layers from ng_state can never remove them. Add removed_unsupported_sharing_keys to ViewUpdateRequest; update_view drops those unsupported rows after reconciling and reindexes the rest. This lets the viewer remove an unsupported source locally and record it on Save, instead of calling remove-sources, which commits immediately and would clash with unsaved edits.
…rces Replace the viewer sidebar's cart round trip with a direct add, and the Layer Cart tab with a Sources tab that shows what the viewer holds. Add data: only the checked rows are probed (Zarr/OME detection and the dimension check), so the expensive checks still never run on every row. "Add N to this View" reuses the mismatch and Data Link consent dialog, and summarizes datasets that can't load as a layer or whose dimensions differ. The viewer no longer touches the cart. Sources: useViewSources groups Neuroglancer's layers into datasets by Data Link segment, using the saved rows plus datasets added this session, and follows state.changed (throttled; camera-only changes are ignored), so layers removed in Neuroglancer drop out of the list. Removing a source deletes its layers from Neuroglancer; removing an unsupported one is held in the edit state and sent as removed_unsupported_sharing_keys on Save. Both stay local until Save, and Discard undoes them. After Save the views cache is updated in place, so the Sources tab maps layers through the new rows right away.
The broken-link icon only offered a relink, while the unsupported icon offered removal, which applies to a broken link too. Every broken source now opens a "Broken source" dialog with both actions. A source whose Data Link was never recorded, which used to show an inert icon, gets the same dialog with removal only. Removal goes through the same mutation as removing an unsupported source.
Cover adding a dataset with differing dimensions and no Data Link while automatic Data Links are off: the dialog has to ask for both.
Vite bundled frontend/viewers.config.yaml whenever it existed on disk, even though git ignored it, so a developer's local override could ship in a PyPI build. The runtime viewers_config setting (FGC_VIEWERS_CONFIG) already covers local customization without a rebuild, so it is now the only override. The docs, CLAUDE.md, and config.yaml.template describe it, and .gitignore ignores a root-level viewers.config.yaml for local use.
allison-truhlar
force-pushed
the
ngviews-15-sidebar-browser
branch
from
October 13, 2026 14:26
23dee2f to
0aaa581
Compare
The "Unsaved changes" banner under the toolbar appeared on every pan or zoom, so in practice it was always there and cost the visualization vertical space. Replace it with a Save button that always sits in the toolbar next to the View name and is disabled until there are unsaved changes, with Discard appearing beside it only while dirty. The explanation that saving updates the View for everyone moves to the Save tooltip.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The owner of a View can browse for data without leaving the embedded viewer, and can remove datasets from a View on the Views page. This builds on #464, which adds the "Add data" sidebar. The branch also tidies the Views table: it counts datasets instead of layers, drops the Sharing column, and sizes its columns to the screen.
What changed
Viewer sidebar
Removing datasets from a View
Before this change, the only way to remove a dataset from a View was to delete its layer inside Neuroglancer. That doesn't work for a dataset with no Neuroglancer layer, such as a plain directory.
POST /api/neuroglancer/views/{short_key}/remove-sourcestakes{"sources": [{"fsp_name", "path"}]}. For each dataset,remove_view_sourcesdrops every Neuroglancer layer whose source uses one of the dataset's Data Link segments, and everyview_layersrow for it, including unsupported and broken rows. Everything happens in one database commit. A row that never recorded its key falls back to itslayer_index. Only the owner can call it, and it returns a 404 when the View has none of the listed datasets.Views table fixes
sharing_modeisn't yet implemented (only a View's owner can edit it). A per-row sharing label suggests a choice that doesn't exist yet. The column comes back once sharing modes are enforced.minmaxtracks. They start at their full width and shrink toward a minimum on narrower screens.Testing
The backend suite (1129) and frontend suite (569) pass. New tests cover
remove_view_sources, the remove-sources endpoint, the warning-icon button, the "Remove datasets" menu item, andRemoveDatasetsDialog.Manually smoke-tested in local development.
@krokicki