Find logo and Refresh logo in a dialog on the company's page, not on a page of their own #674
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#674
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?
From the list: “When capturing a logo, don't take user to a new page. Use a dialog instead.” Pressing Find logo or Refresh logo on a company's page sends the person to a page that only shows a spinner and then a link back.
What exists today
company_detail.htmldraws Find logo (a company with a website and no logo) and Refresh logo (one with a remembered source address) as small forms posting tojobs:company_logo_action(src/postulo/templates/jobs/company_detail.html:48-58). The view hands the work to the errand layer and redirects tocore:errand(src/postulo/jobs/views.py:437-468, the redirect at:468); Remove logo is instant and stays on the page (:457-460).core/errand.htmlshows the work's name and the state, polled every two seconds by the fragmentcore/partials/errand_state.html; on success it offers “Take me to it” (src/postulo/templates/core/errand.html,src/postulo/templates/core/partials/errand_state.html,src/postulo/core/views_errands.py:41-51). The state fragment is already ownership-checked and already degrades without a script (a “Check again” link).find_a_logo, registered as thelogoerrand: it reads the company's site and tries up to six images, or fetches the remembered address again (src/postulo/jobs/slow.py:130-157). An instance with no worker does the work in the request and answers “done”, with the same page (src/postulo/core/errands.py).<c-dialog>is a<dialog popover>that is a popover with no script and modal with one, takes aliveform that htmx posts, and has atone="plain"variant for a dialog that holds something to do (src/postulo/templates/cotton/dialog.html,src/postulo/static/js/app.js:1798-1862, #303). It is used today on Your details for removing a row (src/postulo/templates/accounts/profile.html:231) and tested with and without scripts (tests/e2e/test_dialog.py).find_on_websiteraises, which today drops the reasons it collected (#526, open); the reason a site blocked or served nothing usable is lost either way.src/postulo/jobs/forms.py:291-314); this issue does not touch them.tests/test_logos.py::test_find_logo_and_refresh_are_only_ever_pressed_by_a_person(:393) andtest_logo_actions_are_private_to_the_owner(:430), the isolation sweep (tests/security/test_isolation_sweep.py:384),tests/test_slow_requests.py:38.Checked against
mainatf09b6010b.Proposal
popovertargetbutton, the dialog is<c-dialog tone="plain">containing the same POST form. It says what will happen in the person's own terms: “Postulo will read example.com and keep the first image that works as the logo” (for Refresh: “Postulo will fetch the logo again from ”), then offers Find logo beside Cancel. With no script it is a popover and the form posts as it does now.CompanyLogoActionView.postanswers a plain POST as today (redirect tocore:errand) and an htmx POST with the errand-state fragment, so the dialog's body becomes the progress line and then the result. This is the shapeaccounts/views.pyalready uses for the row removal (request.htmx).aria-labelledby,aria-describedby, which the component already sets).Decisions
popovertargetdoes not make a request, so one press needs more script than the rest of the interface has; and Postulo's rule is that fetching is “only ever pressed by a person” (tests/test_logos.py:393), with the host named before it happens, which a second press makes visible.Builds on
Issues #21 (finding a logo), #247 (the errand and its “working…” state), #303 (the dialog component and its script), #526 (the failures never shown). Related: #525 and #355 (the logo file's lifecycle), #407 (limits on person-chosen fetches).
Done when
tests/test_logos.py: an htmx POST tojobs:company_logo_actionanswers 200 with the errand state and no redirect; a plain POST still redirects tocore:errand; both still 404 for another owner (extendtest_logo_actions_are_private_to_the_owner).tests/e2e/test_dialog.py: the dialog opens from Find logo, is modal with scripts and a popover without, shows progress then the result, gives focus back, and passes axe in both themes; a failure shows its reason.tests/test_slow_requests.py:38still holds (the action does not run inside the request's transaction), and the page's entries intests/test_page_coverage.pyandtests/security/test_isolation_sweep.pyare unchanged because no address is added.f09b6010b) and the candidate format (4) stay as they are. New strings are in the working catalogues (en-GB, fr-FR, pt-PT as drafts) and Weblate (#349); the wiki's company page (Tracking applications) says where the logo is found.From the list of improvements of 2026-10-02.