← All stories

BRANCH · ef-032-canvas-contact-form

Contact Form button

EF-032Persona: OrganizerRoots in: event-setupMatrix: AbsentEF reference: EventFarm doc

EventFarm exposes a Canvas contact-form button that opens a request modal and emails the organizer. The matrix marks EF-032 matrix=Absent, so this branch ships as a parity-gap probe while specifying the desired form, anti-abuse, email routing, and audit contract.

Preconditions

The organizer is authenticated in the event-setup trunk, has edit access to a fixture event, and the event has a Canvas draft page with at least one root block.

Happy path

  1. Open the Canvas editor from Event Setup.

    The editor loads the draft page, root block sequence, autosave state, and preview pane.

  2. Compose, preview, and publish.

    The organizer edits the capability surface for Contact Form button (Canvas contact modal sends request email), previews desktop and mobile, then confirms publish or schedule.

  3. Verify public version semantics.

    Publish creates a versioned snapshot; scheduled publish leaves the prior public version intact until its activation time.

Failure modes

Every Canvas branch includes the cluster E rubric: undo/redo, paste-from-other-page, asset isolation, missing-token fallback, preview parity, scheduled publish, autosave recovery, and two-editor conflict. Capability-specific probes bring each story to 10-12 failure modes.

EF-032 not implemented

Trigger: matrix=Absent.

A visible EF-032 not implemented panel is required as the parity-gap probe until the documented contract ships.

Undo/redo correctness across block ops

Trigger: the organizer inserts a block, deletes another, reorders the root block sequence, and edits one block property before using undo twice.

Resolution: each block operation creates exactly one undo entry; multi-step undo restores the prior root block sequence and block props exactly, then redo reapplies the same sequence without duplicating blocks.

Paste from other page

Trigger: the organizer copies a block from page A and pastes into page B, then tries the same paste from a different event.

Resolution: page-local references are remapped to the destination slug and asset URLs; cross-event paste opens an explicit confirmation before any draft mutation happens.

Asset upload failure isolated

Trigger: three assets upload while one fails with a transient R2 or connector error.

Resolution: the two successful uploads continue and bind to their blocks; the failed asset renders inline with retry and the page draft JSON remains valid.

Dynamic token rendering missing data

Trigger: preview resolves {guest.firstName} for a contact with no first name and {event.location} before location is configured.

Resolution: missing values fall back to "Guest" or configured fallback copy; no rendered sentence contains an empty merge or doubled punctuation.

Mobile preview vs published

Trigger: organizer previews at 375x667 and publishes the same draft.

Resolution: the public page matches mobile preview within layout-shift and viewport tolerances; differences surface as preview warnings before publish.

Scheduled publish vs immediate

Trigger: organizer schedules a draft for a future time instead of publishing immediately.

Resolution: before the scheduled time, the public URL serves the previous active version or 404 for first publish; at the scheduled time the new draft becomes live atomically.

Autosave recovery

Trigger: browser refreshes or crashes after an edit but before manual save.

Resolution: latest autosave is offered in a recovery banner with restore/discard; restore is the default and rehydrates the exact block tree.

Two-editor conflict resolution

Trigger: two organizers edit the same page; one publishes while the other saves a stale draft.

Resolution: the second organizer sees a conflict modal listing changed blocks and can merge or accept last-write-with-warning; both sessions converge to a deterministic state.

Contact form block captures name, email, and message

Trigger: guest clicks the Canvas contact button.

Resolution: a modal form opens with required name/email/message fields, inline validation, and no public disclosure of organizer internals.

Anti-abuse, routing, and audit are required

Trigger: the guest submits the contact form repeatedly.

Resolution: CAPTCHA or rate limit gates abuse, email routes to the event contact address, and one audit/log row is written per accepted submission.

Parity gap: EF-032 not implemented

Trigger: matrix=Absent for Contact Form button.

Resolution: a visible "EF-032 not implemented" panel remains until the Canvas contact form block, anti-abuse controls, email routing, and audit logging ship.

Stable test attributes

Visibility teeth. Each attribute must be effectively visible when active and must match the agent probes.

data-testWherePurpose
canvas-canvas-contact-form-editorCanvas editorMain organizer-side Canvas editor surface
canvas-canvas-contact-form-stepperCanvas editorCreate/edit/preview/publish lifecycle indicator
canvas-canvas-contact-form-block-treeCanvas editorRoot block sequence and selected block tree
canvas-canvas-contact-form-previewCanvas editorPreview pane for desktop and mobile layouts
canvas-canvas-contact-form-publish-ctaCanvas editorPublish or schedule publish action
canvas-canvas-contact-form-publish-confirmationCanvas editorConfirmation dialog for publish or risky action
canvas-canvas-contact-form-autosave-bannerCanvas editorAutosave recovery and restore/discard banner
canvas-canvas-contact-form-conflict-modalCanvas editorTwo-editor conflict resolution modal
canvas-canvas-contact-form-upload-rowCanvas editorPer-asset upload progress/failure row
canvas-canvas-contact-form-token-warningCanvas editorDynamic token validation or fallback warning
canvas-canvas-contact-form-gap-panelCanvas editorVisible parity gap panel when matrix is absent or partial
canvas-canvas-contact-form-mobile-preview-warningCanvas editorPreview discrepancy warning for mobile vs published
canvas-canvas-contact-form-contact-modalCanvas editorContact form modal
canvas-canvas-contact-form-contact-formCanvas editorName/email/message contact form
canvas-canvas-contact-form-email-fieldCanvas editorRequester email input
canvas-canvas-contact-form-contact-submitCanvas editorContact form submit CTA

Agent test plan

Inherits event-setup trunk preconditions. Component contract chaining applies through usesComponents.

- open-canvas-surface
- edit-preview-publish-flow
- published-version-recorded
- undo-redo-block-ops
- paste-cross-page
- asset-upload-isolated
- dynamic-token-fallback
- mobile-preview-published-match
- scheduled-vs-immediate-publish
- autosave-recovery
- two-editor-conflict
- contact-form-fields-contract
- contact-anti-abuse-routing-audit
- ef032-not-implemented
- evaluate-canvas-editor