WT-1690 Contact Form block - #1831
maribedran wants to merge 25 commits into
Conversation
The block references a Contact Page and renders the form portion of the page's template. The form action POSTs to the page URL. Users with no-js will be sent to the contact page on submit. The block sets the needs_fresh_csrf flag to the request on get_context. The flag tells AbstractSpringfieldCMSPage to add the never cache header to the response, so that a page using this block is never cached and each user gets a fresh CSRF token.
Add the opttion to download a file after a successful form submission. The file is downloaded by JS and a link to it is displayed in the thank you message as a fallback in case JS is disabled.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1831 +/- ##
==========================================
+ Coverage 90.72% 90.79% +0.07%
==========================================
Files 195 196 +1
Lines 14205 14290 +85
==========================================
+ Hits 12887 12975 +88
+ Misses 1318 1315 -3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved browser fallback, access-control, redirect/download, and multi-instance accessibility issues affect core form behavior.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds an HTMX-powered reusable Contact Form block, basic Basket endpoint support, and post-submission document downloads.
Changes:
- Adds shared form templates, HTMX integration, caching protections, and block registration.
- Extends ContactPage with document-download fields and basic Basket validation.
- Adds fixtures and backend/Jasmine coverage; removes the legacy contact-form bundle.
File summaries
| File | Description |
|---|---|
springfield/cms/models/pages.py |
Contact block registration, endpoint fields, downloads, HTMX handling |
springfield/cms/blocks.py |
Defines the reusable Contact Form block |
springfield/cms/templates/cms/includes/contact-form.html |
Shared form and success markup |
springfield/cms/templates/cms/contact_page.html |
Uses shared form template |
springfield/cms/templates/cms/blocks/contact-form.html |
Nested block rendering |
springfield/cms/templates/cms/blocks/sections/contact-form-section.html |
Top-level section wrapper |
springfield/cms/templates/cms/base-flare.html |
Loads HTMX |
springfield/cms/models/base.py |
Prevents caching CSRF-bearing pages |
springfield/cms/migrations/0154_contactpage_document_download_and_more.py |
Adds document fields and endpoint choice |
springfield/cms/fixtures/contact_page_fixtures.py |
Updates contact-page fixture data |
springfield/cms/fixtures/contact_form_fixtures.py |
Adds Contact Form block fixtures |
springfield/cms/fixtures/registry.py |
Registers new fixture |
springfield/cms/tests/test_contact_page.py |
Tests endpoint, HTMX, and downloads |
springfield/cms/tests/test_blocks.py |
Tests block rendering and caching |
media/js/cms/components/flare-contact-form.es6.js |
Adds HTMX form behavior |
media/js/cms/flare.es6.js |
Initializes Contact Form behavior |
tests/unit/spec/cms/components/flare-contact-form.js |
Adds Jasmine coverage |
media/css/cms/components/flare-form-fields.css |
Adds grid and two-column layouts |
springfield/base/templatetags/helpers.py |
Exposes the HTMX helper |
springfield/settings/base.py |
Registers django-htmx |
requirements/prod.in |
Adds django-htmx dependency |
requirements/prod.txt |
Locks production dependency |
requirements/dev.txt |
Locks development dependency |
media/static-bundles.json |
Removes legacy contact bundle |
media/js/cms/contact-form.js |
Removes legacy implementation |
Review details
Suppressed comments (3)
media/js/cms/components/flare-contact-form.es6.js:59
- bug: The fallback repeats the shadowable
form.submit()call, so a valid field namedsubmitalso breaks the network-error path. Apply the same safe native-submit helper here.
const fallback = (e) => {
const form = e.target;
form.action = form.getAttribute('hx-post');
form.submit();
media/js/cms/components/flare-contact-form.es6.js:57
- naming (non-blocking): Use
eventrather than the single-lettereso this delegated error handler states what the callback receives.
const fallback = (e) => {
const form = e.target;
media/js/cms/components/flare-contact-form.es6.js:72
- naming (non-blocking): Use
eventrather than the single-lettere; this callback handles a swap event and the explicit name clarifies the target lookup.
document.body.addEventListener('htmx:afterSwap', (e) => {
const wrapper = e.target.closest('.fl-contact-form-wrapper');
- Files reviewed: 25/25 changed files
- Comments generated: 10
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
One-line summary
Add a new Contact Form block to render a Contact Page's form with HTMX. Add a new document download option to the Contact Page and a new Basket endpoint.
Significant changes and points to review
Issue / Bugzilla link
https://mozilla-hub.atlassian.net/browse/WT-1690
Testing
./manage.py load_page_fixturesrequiredattribute from any of the required fields to trigger a form error