Skip to content

Comments

feat: Forms as Collections, Submissions as Content#623

Open
mmcintosh wants to merge 1 commit intoSonicJs-Org:mainfrom
mmcintosh:feature/forms-as-content-upstream
Open

feat: Forms as Collections, Submissions as Content#623
mmcintosh wants to merge 1 commit intoSonicJs-Org:mainfrom
mmcintosh:feature/forms-as-content-upstream

Conversation

@mmcintosh
Copy link
Contributor

Description

Integrates form submissions into the unified content management system. Each form auto-creates a "shadow collection" in the
collections table. When a submission arrives, it dual-writes to both form_submissions (preserving metadata like IP, user agent, UTM)
and content (enabling unified listing). Form submissions appear at /admin/content, filterable by model, status, and searchable — just
like regular content.

Changes

Database Migration (032_form_content_integration.sql)

  • Add source_type and source_id columns to collections for form-derived collections
  • Add content_id column to form_submissions to link submissions to content items
  • Create system-form-submission user for anonymous submissions (satisfies author_id FK constraint)

New Service (form-collection-sync.ts)

  • Derives collection JSON schema from Form.io component definitions
  • Creates/updates shadow collections (form_{name}) for each form
  • Dual-writes form submissions to content table with _submission_metadata
  • Backfills existing submissions that lack content items on bootstrap
  • Maps form statuses to content statuses (submissions default to published)

Bootstrap Integration

  • syncAllFormCollections() runs after syncCollections() on worker startup
  • Ensures all forms have shadow collections and backfills existing submissions

Admin UI Updates

  • Content list: "Form" badge on model column for form-sourced content
  • Content edit: read-only Submission Info panel (form name, email, IP, user agent, timestamp)
  • Model filter: form collections appear in the content filter dropdown
  • Submissions page: /admin/forms/:id/submissions redirects to /admin/content?model=form_{name}

Collection Isolation

  • Form-derived collections hidden from /admin/collections page
  • Form-derived collections excluded from new-content picker (users can't manually create content in form collections)
  • getManagedCollections() excludes source_type='form' so cleanupRemovedCollections won't deactivate shadow collections

Form API Enhancement

  • PUT /admin/forms/:id now accepts optional turnstile_enabled and turnstile_settings fields

Testing

Unit Tests

  • Added/updated unit tests
  • All unit tests passing (1237 tests)

E2E Tests

  • Added/updated E2E tests (53-forms-as-content.spec.ts — 12 tests)
  • All E2E tests passing (282 E2E tests, 0 failures)

E2E coverage:

  • Create form with real Form.io fields (contact, feedback), set schema, disable turnstile via API
  • Submit form data via public API, verify content item created with correct title
  • Verify Form badge on content list model column
  • Verify submission metadata panel in content edit view
  • Verify submissions page redirects to content list
  • Verify form collections hidden from collections page and new-content picker
  • Verify content search finds form submissions by name
  • Verify published status default for submissions
  • Verify multiple form models appear in content filter

Screenshots/Videos

New-Forms 1- SonicJS AI Admin New-Content-Management-Form- SonicJS AI Admin

Checklist

  • Code follows project conventions
  • Tests added/updated and passing
  • Type checking passes
  • No console errors or warnings
  • Documentation updated (if needed)

Each form auto-creates a shadow collection in the collections table.
Submissions dual-write to both form_submissions and content, enabling
unified listing at /admin/content with form badge, submission metadata
panel, and full search/filter support.

- New migration (032): source_type/source_id on collections, content_id on form_submissions, system user
- New service (form-collection-sync.ts): shadow collection management, schema derivation, dual-write, backfill
- Bootstrap integration: syncs form collections on startup
- Content list: form badge, submitter metadata, form collections in filter
- Content edit: read-only Submission Info panel
- Submissions redirect: /admin/forms/:id/submissions → /admin/content?model=form_{name}
- Collection isolation: form-derived collections hidden from /admin/collections and new-content picker
- Cleanup protection: getManagedCollections() excludes source_type='form'
- Turnstile settings: PUT /admin/forms/:id accepts turnstile_enabled/turnstile_settings
- 82 unit tests (98.3% statement coverage) + 12 E2E tests covering full integration flow
@mmcintosh mmcintosh force-pushed the feature/forms-as-content-upstream branch from eff2aaa to b10dba6 Compare February 24, 2026 04:37
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.

1 participant