Skip to content

Show recently updated capture sets first in pickers, and stop them waiting on counts they never show - #1381

Draft
mihow wants to merge 2 commits into
mainfrom
fix/capture-set-picker-choices
Draft

Show recently updated capture sets first in pickers, and stop them waiting on counts they never show#1381
mihow wants to merge 2 commits into
mainfrom
fix/capture-set-picker-choices

Conversation

@mihow

@mihow mihow commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Picking a capture set when starting a job is meant to be the easy part of the form, and
in a project that has accumulated a lot of capture sets it currently is not. The dropdown
loads one page of results in whatever order the database happens to return them, so a set
a user created minutes ago may not be in the list at all, and there is no way to reach it
from the form. The same dropdown also waits on the number of captures, occurrences and
taxa in every capture set in the project — figures it never displays — which is why it
sits disabled for a long time before it becomes usable.

This changes both. Capture sets now come back most recently updated first, so the sets
someone is actively working with are at the top of every picker and filter. And the
pickers read from a new endpoint that returns just enough to name a capture set, so they
no longer pay for counts they do not show. The endpoint follows the pattern introduced
for the occurrence algorithm filter in #1368: a small, purpose-built sub-action that
serves a filter's choices, separate from the full list endpoint the table page uses.

Reported against a project whose capture set list had grown past one page.

List of Changes

# Change How
1 Capture sets are listed most recently updated first, in the job form, the export form, the capture set filter, and the API by default ordering = ["-updated_at"] on SourceImageCollectionViewSet. The capture sets table page asks for its own sort order and is unaffected
2 Capture set dropdowns no longer wait on counts they never display New GET /api/v2/captures/collections/choices/ returning id, name and sampling method per set, serialized with the existing SourceImageCollectionNestedSerializer. CaptureSetPicker and CaptureSetFilter read from it
3 The job and export form still reports how many captures the selected set holds useCaptureSetDetails fetches the selected set on its own, the same shape the taxon filter uses for its selected taxon
4 A capture set that is already selected stays visible in the picker even if it falls outside the loaded page The picker adds the selected set back into its options when the choices page does not contain it
5 Pages of capture sets are stable across requests The viewset had no default ordering at all, so page boundaries were undefined

Detailed Description

The capture set list endpoint annotates three counts on every row —
source_images_count, source_images_with_detections_count and
source_images_processed_count — each of which joins through captures to detections and
de-duplicates. Grouping happens before LIMIT, so asking for 20 rows still costs the
whole project. Two measurements from a local copy of production data, on a project with
46 capture sets:

Query Time
list(qs[:20]) with no count annotations 0.022s
list(qs[:20]) with the three count annotations 24.8s

End to end over HTTP on the same machine, the list endpoint took 51.8s cold against 1.8s
for the new choices endpoint. Both numbers include local development middleware, so treat
them as indicative of the gap rather than as production figures; the ORM timings above are
the direct measurement.

The counts themselves are untouched — the capture sets table still reports all of them,
and ?with_counts=true still adds occurrence and taxa counts. The annotations simply
moved from the viewset's class-level queryset into get_queryset() so the choices action
can opt out of them. Sorting by a count is still available on the list endpoint and is
excluded from the choices action, where the annotations do not exist.

Testing

  • ami.main.tests and ami.exports: 322 tests, all passing.
  • New TestCaptureSetChoices (8 tests) pins the contract the pickers depend on: most
    recently updated first, names without counts, scoped to the requested project, a
    project is required, capture sets in a draft project stay hidden from non-members, and
    the list endpoint keeps both its counts and its ability to sort by them.
  • Frontend: tsc --noEmit, eslint and prettier --check all clean.
  • No model change, so no migration. makemigrations --check passes.

What has not been verified

The change has not been clicked through in a browser. The local ui container serves a
pre-built bundle rather than a dev server, and the host dev server would not start against
this checkout. The requests the pickers make were exercised directly instead, against a
local copy of production data:

  • GET /captures/collections/choices/?project_id=…&limit=200&offset=0 → 46 of 46 sets,
    most recently updated first, no count fields.
  • GET /captures/collections/{id}/?project_id=…&with_counts=false → the selected set
    with source_images_count populated, in 0.3s.

Worth a click-through on the job form and the occurrences page filter before merge.

Follow-up

#1380 proposes replacing the dropdown with a searchable field like the taxon filter, which
is the real fix for a project with more capture sets than one page can hold. This change
makes the common case work; it does not make an arbitrarily long list navigable.

mihow and others added 2 commits July 27, 2026 07:23
The capture set list endpoint reports the number of captures, occurrences and
taxa in each set. Filters and pickers only need to name a set, so serving their
options from that endpoint made every dropdown wait on counts nobody reads.

/api/v2/captures/collections/choices/ returns the id, name and sampling method
of each capture set in a project, following the same pattern as the occurrence
algorithm filter's choices at /occurrences/algorithms/. The list endpoint keeps
its counts.

The viewset also gains a default ordering of most recently updated first. It had
none, so row order came back in whatever order Postgres produced, which left
pagination unstable and could put a capture set a user had just created outside
the first page of a picker.

Co-Authored-By: Claude <noreply@anthropic.com>
The job form, the export form and the capture set filter now read their options
from /captures/collections/choices/, so they no longer wait on counts they do
not display, and the most recently updated capture sets come first.

The job and export picker still shows how many captures the selected set holds.
That count now comes from a single-record fetch of the selected set, the same
shape the taxon filter uses for its selected taxon. A set that was picked before
it fell off the end of the list is added back to the options, so an existing
selection never disappears from the form.

Co-Authored-By: Claude <noreply@anthropic.com>
@netlify

netlify Bot commented Jul 27, 2026

Copy link
Copy Markdown

Deploy Preview for antenna-preview ready!

Name Link
🔨 Latest commit 4ff7292
🔍 Latest deploy log https://app.netlify.com/projects/antenna-preview/deploys/6a676aea82171a000822e786
😎 Deploy Preview https://deploy-preview-1381--antenna-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 52 (🔴 down 13 from production)
Accessibility: 81 (🔴 down 8 from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 92 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jul 27, 2026

Copy link
Copy Markdown

Deploy Preview for antenna-ssec ready!

Name Link
🔨 Latest commit 4ff7292
🔍 Latest deploy log https://app.netlify.com/projects/antenna-ssec/deploys/6a676aeae0ed930008d03c35
😎 Deploy Preview https://deploy-preview-1381--antenna-ssec.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: acfa6e7f-2600-4f63-bae1-cf94f740d350

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/capture-set-picker-choices

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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