Captures: the 'discarded captures' link redirects to Listings, and nothing lists or restores a discarded capture #380
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#380
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, following the link the discard message offers and checking every place that lists captures or changes a capture's status.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atapi/api.py:633-647(list_captures) andjobs/pages.py:800-821(expire_unconfirmed); the capture views, the routes, the Listings view, the templates,notifications/slow.py:106and the two tests have not moved.Related to #260 (closed), which made the discard message link to "the discarded captures" so that a wrong key press would be recoverable, and to #25 (closed), which replaced the capture list with a redirect to Listings. This issue adds that the link #260 wrote points at that redirect, so it never showed a discarded capture, and that no route puts one back. It also touches #336 (open): once the review page refuses decided captures, the last way back, a hand-typed review address, goes too.
The message says "Capture discarded. It is in the discarded captures." and links to
/jobs/captures/?show=all. That address redirects to Listings and drops the query string. Listings shows pending captures only, the API lists pending captures only, and nothing in the interface sets a discarded capture back to pending. The recovery #260 promised does not exist, at the one moment somebody is looking for it. The same block on Listings shows and counts at most 20 pending captures.jobs/capture_views.py:431-440(discarded_link):url = reverse("jobs:capture_list") + "?show=all". Its docstring still says "the list can show what is not pending".jobs/capture_views.py:443-460(CaptureDiscardView) and:463-494(CaptureDiscardSelectedView) send "Capture discarded. It is in {link}." and "Captures discarded: {count}. They are in {link}.".jobs/urls.py:37-42:capture_listisRedirectView.as_view(url=reverse_lazy("listings:list"), permanent=False).RedirectView.query_stringdefaults toFalse, so?show=allis dropped.jobs/listing_views.py:132-136: the Listings page takesCapture.objects.for_user(...).filter(status=CaptureStatus.PENDING), cut to[:20].templates/jobs/listing_list.html:78countspending_captures|lengthfor the heading.api/api.py:631-645(list_captures) filters onPENDINGtoo.jobs/urls.py:38-93: the capture routes are the redirect, create, review, discard, discard-selected, bind and the five page routes. None restores.src,testsand the sibling repositories:jobs/capture_views.py:134-149(CaptureListView, the view that had theshow=allswitch and paginates by 50),jobs/capture_views.py:497(capture_list_url) andtemplates/jobs/capture_list.html, whose strings ("Pending only", "Show all", "Nothing waiting") are still in the catalogues.templates/jobs/capture_list.html:40-57: even were the list routed again, a row gets Review and Discard only whencapture.is_pending, a link only whencapture.applicationis set, and otherwise the bare{{ capture.get_status_display }}. A discarded row has nothing to press, and a capture saved as a listing without an application shows its status with no link tocapture.posting.tests/test_table_caption_and_discard.py:30-48asserts the text of thehrefand never requests it.tests/test_listings.py:169-170asserts thatjobs:capture_listanswers 302 tolistings:list, so the two tests between them pin the broken state.don the wrong capture, or discards a mistaken selection, and follows the discarded captures.GET /jobs/captures/?show=allanswers 302 to/listings/, which shows pending captures and listings. The discarded capture is on neither, and no control on any page lists discarded captures or restores one./jobs/captures/<pk>/review/, which nothing shows, and which works only because the review page does not check the status (#336). Discarding also emptied itslearning(jobs/capture_views.py:451,:480), and its kept page is removedPOSTULO_CAPTURE_PAGE_KEEP_DAYS(30 by default) after it was captured (jobs/pages.py:828-849,expire_unconfirmed).notifications/slow.py:106sends the "Captured N postings" notification of a batch to this same address, so a batch of forty lands on a page that says twenty.jobs:capture_listback toCaptureListView, or add a discarded-captures view reached from the capture block on Listings (for example?captures=discarded) listingfor_user()captures with statusDISCARDED. Pointdiscarded_link()at it and correct its docstring.notifications/slow.py:106should land in the same place.jobs:capture_restorePOST view that, underselect_for_update(), moves aDISCARDEDcapture of the requesting person back toPENDING, refuses any other status, and answers 404 for another account's capture. Show a Put it back button on each discarded row. Land it with or before #336, so that the review page refusing decided captures does not remove the only way back.capture.postingwhen it has no application.CaptureListView,templates/jobs/capture_list.htmlandcapture_list_urlis left unused, and let the catalogues drop the strings..count()for the heading, and link to the full list when there are more than 20.Done when
tests/test_table_caption_and_discard.pydiscards a capture, follows the link in the message, and asserts that the discarded capture's title and a restore control are on the page it reaches.next_pendingfinds it), that restoring a capture that is not discarded is refused, and that another account's capture answers 404.tests/test_listings.pywith 25 pending captures asserts the heading says 25 and that the page links to the full list.