Skip to content

WT-1690 Contact Form block - #1831

Open
maribedran wants to merge 25 commits into
mainfrom
WT-1690-form-block
Open

maribedran wants to merge 25 commits into
mainfrom
WT-1690-form-block

Conversation

@maribedran

@maribedran maribedran commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

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

  • Create the Contact Form block, which renders the form portion of a Contact Page
    • The block uses the page's context to render the form template and posts to the page's URL
    • HTMX swaps the block's HTML with the POST response on submit
  • Add a new document download option to the Contact Page
    • The file is downloaded after a successful submission by JS
  • Add a new option for the Basket endpoint field with the new basic contact endpoint

Issue / Bugzilla link

https://mozilla-hub.atlassian.net/browse/WT-1690

Testing

  • Make sure that you have Basket running
  • Run ./manage.py load_page_fixtures
  • Go to http://localhost:8000/en-US/flare-docs/blocks/test-contact-form-page/ and fill out one of the forms
  • Check that a file is downloaded after submitting the form
  • Check that the form gets replaced with a Thank You message
  • Open the browser inspector and remove the required attribute from any of the required fields to trigger a form error
  • Check that the form renders with the error message
  • Check that the Contact Page still works as before

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

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.95833% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.79%. Comparing base (2cfaa9d) to head (4d95bf4).

Files with missing lines Patch % Lines
springfield/cms/blocks.py 97.36% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@maribedran
maribedran marked this pull request as ready for review September 16, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 named submit also 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 event rather than the single-letter e so 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 event rather than the single-letter e; 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.

Comment thread springfield/cms/blocks.py
Comment thread media/js/cms/components/flare-contact-form.es6.js Outdated
Comment thread springfield/cms/blocks.py
Comment thread springfield/cms/models/pages.py
Comment thread springfield/cms/templates/cms/base-flare.html
Comment thread springfield/cms/templates/cms/blocks/contact-form.html Outdated
Comment thread springfield/cms/templates/cms/includes/contact-form.html
Comment thread tests/unit/spec/cms/components/flare-contact-form.js Outdated
Comment thread media/js/cms/components/flare-contact-form.es6.js Outdated
Comment thread springfield/cms/tests/test_contact_page.py Outdated
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.

3 participants