Conversation
File names in the WBPP quality table are now preview links, matching the session frame table. Clicking one opens the shared FilePreviewModal, and the arrow keys walk every row in the table's current sort order from the clicked frame, so sorting by verdict lets you flip through all excluded frames in sequence. The modal gains an optional per-file metadata strip, passed as a generic label/value array so it stays ignorant of WBPP concepts. The WBPP panel fills it with a mirror of the table row: the verdict (with failure detail in the tooltip), filter, the five quality metrics with the same baseline band colors and failure marks, and the session date. With the master filter toggle off, every strip reads Copy. Other callers of the modal pass nothing and are unaffected.
…ctiveJob projection
…atus store so jobs are visible off the Settings page Extracts rebuild polling out of ScanManager into store/rebuild.ts, and promotes scan status/stop/refresh to module-level exports in store/scan.ts. This lets an always-mounted job monitor read scan and rebuild state and stop a scan from anywhere in the app, not only while Settings is open. ScanManager keeps its existing wiring into the dashboard ActivityFeed unchanged; behavior for scan/rebuild polling is byte-for-byte the same, just relocated.
… through the copy job store
…rip progress Adds the aggregation layer the nav-bar job monitor renders from: a single monitorJobs() list combining the existing scan/rebuild/Celery activeJobs registry with the WBPP browser copy job, and aggregateProgress() to reduce that list to one strip-level fraction (mean of determinate jobs, null when every running job is indeterminate so the strip falls back to a shimmer). wireGlobalJobSources() replaces the per-page ScanManager wiring so jobs stay visible across the whole app rather than only the page that started them.
… commit The prior commit's staging accidentally swept in another in-progress change's already-staged deletion of this file. Restoring it here so that work stays untouched and can be committed on its own terms.
…ors store Task 4 (shared activity-errors store) landed the replacement in b8ffb4a but a concurrent commit from another in-progress task restored this file while untangling an unrelated staging collision. Removing it now that the replacement is confirmed in place and no code references it.
startWbppCopy silently no-oped when a copy was already running, which would have been a dead end for future callers like the job monitor that have no pre-check of their own. It now toasts the same way a failure does, and state from the in-flight copy is proven to survive the rejected call. Also adds executable coverage for why the copy lives in a module-level store: a fresh mount reflects an already-running copy's live progress immediately, and the store keeps running independent of any component.
…ity chip, and job-center panel
…tach test The spy on runBrowserCopy was never restored, and the mock ignored the abort signal, leaving store state dirty across tests (wbppCopyFinished remained 4, stopWbppCopy was a no-op). Updated the mock to listen for abort events on opts.signal and reject the promise when triggered, allowing stopWbppCopy to properly clean up. Added mockRestore call to close the spy after test runs.
The abort-listener mock rejected with a plain Error("Aborted") instead of
the CopyCancelledError the real copy throws on cancellation, so the store's
catch treated the test's own cleanup as a genuine failure: it set an error
banner and fired an error toast that then leaked into whatever test ran
next. Reject with the real CopyCancelledError from wbppBrowserCopy instead,
drop the resolveCopy/rejectCopy captures nothing ever called, move the spy
restore into a finally so a failed assertion can't strand it, and drop the
dead try/catch around the cleanup await (startWbppCopy never rethrows).
startRebuildPolling from store/rebuild.ts had no callers, so the ambient nav-bar job monitor only learned about a repair/retry/backfill/full-rebuild task through its own 30s idle check. Call it once each maintenance action's task starts successfully, so the shared store flips to "running" and the 2s poll kicks in immediately instead of leaving the job monitor stale for up to half a minute. Drops the now-fixed import that ScanManager carried without ever calling it.
JobMonitor's 30s idle timer fired its scan/rebuild status checks regardless of tab visibility, burning a request every 30s on tabs left open in the background. Skip the tick entirely when the document isn't visible.
…ep by step The export modal now works for SIRIL as well as WBPP, so the modal title and the target page export menu item are renamed Export For Stacking. An info popover next to the title walks through the process, and the sections are numbered in click order: the library root picker moves out of the footer into a Step 1 section, followed by the folders to copy and the filter options. The stray session-count badge on the folders header is gone, the quality table shows roughly twice as many rows, and the baseline toggle is renamed Overall with hover text explaining that it only grades cell colors against session stats or the rig's catalog history. Also lets the job monitor's active-job status line wrap instead of clipping the warning that closing the tab cancels the copy.
The in-browser copy used to stream one file at a time, which topped out around 300 Mbps on a 2.5GbE link. Files now flow through a bounded pool of eight concurrent copies, and each file is read in 16 MB slices with explicit writes instead of piping the blob stream, cutting the per-chunk IPC round trips that capped a single stream. Benchmarked against an SMB source this saturates the link at roughly 2700 Mbps. Abort still raises CopyCancelledError and stops new files from starting, a failed file settles all in-flight writables before the run rejects, and progress reporting is unchanged. New test suite covers correctness, the pool bound, chunked writes, zero-byte files, abort, and failures.
The copy progress line used to show the current filename, which was mostly clipped and said nothing about pace. It now shows the transfer rate next to the file counts, computed over a rolling three second window of completed files, as integer Mbps or one-decimal Gbps once past a gigabit. The nav-bar job monitor picks up the same figure. While a copy runs, the tab title mirrors the counts and speed so progress stays visible from other tabs; the original title is restored when the run finishes, fails, or is cancelled.
Faster Copies, Job Monitoring, and Export Improvements
Cold /api/stats took around 31 seconds because several full-table aggregates derived arcsec/px on the fly from raw_headers JSONB with a per-row regex expression, a cost introduced by the arcsec normalization work. The value is static per frame, so it is now stored as images.arcsec_per_pixel at ingest: extract_metadata computes it for FITS and XISF frames, the scan worker persists it, alembic 0021 adds the column, and data migration v15 backfills existing rows from raw_headers. The stats and analysis aggregates now read the column instead of regex-parsing JSONB per row, so a cold Statistics or Analysis page load drops to plain column aggregates and no longer hangs on Loading.
Fixed Slow Statistics Loading
Sync effect tracked saving() as well as props.value, so a finished save re-ran it with the stale prop and clobbered the just-committed value: the checkbox flicked back unchecked until a page reload. Effect now fires only when props.value changes. Failed saves also left the DOM checkbox out of sync with the committed value; onChange now snaps it back and lets a successful save re-check it via signal.
Spinner rendered inline next to the checkbox/select, so in the right-aligned cell it pushed the control ~18px left while a save was in flight and snapped back on completion. Spinner is now absolutely positioned outside the layout flow; controls stay put during saves.
Spinner mounted beside the control flashed on fast LAN saves and read as a rendering artifact next to the checkbox. Saving feedback is now the control itself greyed out (disabled at 40% opacity) with a Saving... tooltip; nothing mounts or unmounts around it.
Improved Custom Field Saving and Display
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.
What's new
What's fixed
What's changed