Skip to content

Commit b10dba6

Browse files
committed
feat: integrate form submissions into content management system
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
1 parent 2250de9 commit b10dba6

80 files changed

Lines changed: 4717 additions & 1337 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- Migration 032: Form-Content Integration
2+
-- Adds bridge columns to link forms to collections and submissions to content items
3+
4+
-- Add source_type and source_id to collections for form-derived collections
5+
ALTER TABLE collections ADD COLUMN source_type TEXT DEFAULT 'user';
6+
ALTER TABLE collections ADD COLUMN source_id TEXT;
7+
8+
-- Index for efficient lookup of form-derived collections
9+
CREATE INDEX IF NOT EXISTS idx_collections_source ON collections(source_type, source_id);
10+
11+
-- Add content_id to form_submissions for linking to content items
12+
ALTER TABLE form_submissions ADD COLUMN content_id TEXT REFERENCES content(id);
13+
14+
-- Index for efficient lookup by content_id
15+
CREATE INDEX IF NOT EXISTS idx_form_submissions_content_id ON form_submissions(content_id);
16+
17+
-- Create system user for anonymous form submissions
18+
INSERT OR IGNORE INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, created_at, updated_at)
19+
VALUES ('system-form-submission', 'system-forms@sonicjs.internal', 'system-forms', 'Form', 'Submission', NULL, 'viewer', 0, strftime('%s','now') * 1000, strftime('%s','now') * 1000);
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,13 @@ CREATE INDEX IF NOT EXISTS idx_forms_turnstile ON forms(turnstile_enabled);
17001700
filename: "031_ai_search_plugin.sql",
17011701
description: "Migration 031: Ai Search Plugin",
17021702
sql: "-- AI Search plugin settings\nCREATE TABLE IF NOT EXISTS ai_search_settings (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n enabled BOOLEAN DEFAULT 0,\n ai_mode_enabled BOOLEAN DEFAULT 1,\n selected_collections TEXT, -- JSON array of collection IDs to index\n dismissed_collections TEXT, -- JSON array of collection IDs user chose not to index\n autocomplete_enabled BOOLEAN DEFAULT 1,\n cache_duration INTEGER DEFAULT 1, -- hours\n results_limit INTEGER DEFAULT 20,\n index_media BOOLEAN DEFAULT 0,\n index_status TEXT, -- JSON object with status per collection\n last_indexed_at INTEGER,\n created_at INTEGER DEFAULT (strftime('%s', 'now') * 1000),\n updated_at INTEGER DEFAULT (strftime('%s', 'now') * 1000)\n);\n\n-- Search history/analytics\nCREATE TABLE IF NOT EXISTS ai_search_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n query TEXT NOT NULL,\n mode TEXT, -- 'ai' or 'keyword'\n results_count INTEGER,\n user_id INTEGER,\n created_at INTEGER DEFAULT (strftime('%s', 'now') * 1000)\n);\n\n-- Index metadata tracking (per collection)\nCREATE TABLE IF NOT EXISTS ai_search_index_meta (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n collection_id INTEGER NOT NULL,\n collection_name TEXT NOT NULL, -- Cache collection name for display\n total_items INTEGER DEFAULT 0,\n indexed_items INTEGER DEFAULT 0,\n last_sync_at INTEGER,\n status TEXT DEFAULT 'pending', -- 'pending', 'indexing', 'completed', 'error'\n error_message TEXT,\n UNIQUE(collection_id)\n);\n\n-- Indexes for performance\nCREATE INDEX IF NOT EXISTS idx_ai_search_history_created_at ON ai_search_history(created_at);\nCREATE INDEX IF NOT EXISTS idx_ai_search_history_mode ON ai_search_history(mode);\nCREATE INDEX IF NOT EXISTS idx_ai_search_index_meta_collection_id ON ai_search_index_meta(collection_id);\nCREATE INDEX IF NOT EXISTS idx_ai_search_index_meta_status ON ai_search_index_meta(status);\n"
1703+
},
1704+
{
1705+
id: "032",
1706+
name: "Form Content Integration",
1707+
filename: "032_form_content_integration.sql",
1708+
description: "Migration 032: Form Content Integration",
1709+
sql: "-- Migration 032: Form-Content Integration\n-- Adds bridge columns to link forms to collections and submissions to content items\n\n-- Add source_type and source_id to collections for form-derived collections\nALTER TABLE collections ADD COLUMN source_type TEXT DEFAULT 'user';\nALTER TABLE collections ADD COLUMN source_id TEXT;\n\n-- Index for efficient lookup of form-derived collections\nCREATE INDEX IF NOT EXISTS idx_collections_source ON collections(source_type, source_id);\n\n-- Add content_id to form_submissions for linking to content items\nALTER TABLE form_submissions ADD COLUMN content_id TEXT REFERENCES content(id);\n\n-- Index for efficient lookup by content_id\nCREATE INDEX IF NOT EXISTS idx_form_submissions_content_id ON form_submissions(content_id);\n\n-- Create system user for anonymous form submissions\nINSERT OR IGNORE INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, created_at, updated_at)\nVALUES ('system-form-submission', 'system-forms@sonicjs.internal', 'system-forms', 'Form', 'Submission', NULL, 'viewer', 0, strftime('%s','now') * 1000, strftime('%s','now') * 1000);\n"
17031710
}
17041711
];
17051712
var migrationsByIdMap = new Map(
@@ -2108,5 +2115,5 @@ var MigrationService = class {
21082115
};
21092116

21102117
exports.MigrationService = MigrationService;
2111-
//# sourceMappingURL=chunk-2YRNPIU4.cjs.map
2112-
//# sourceMappingURL=chunk-2YRNPIU4.cjs.map
2118+
//# sourceMappingURL=chunk-2JX5LHCH.cjs.map
2119+
//# sourceMappingURL=chunk-2JX5LHCH.cjs.map

packages/core/dist/chunk-2JX5LHCH.cjs.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/dist/chunk-2YRNPIU4.cjs.map

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ function buildQuery(table, filter) {
421421
// package.json
422422
var package_default = {
423423
name: "@sonicjs-cms/core",
424-
version: "2.7.0",
424+
version: "2.8.0",
425425
description: "Core framework for SonicJS headless CMS - Edge-first, TypeScript-native CMS built for Cloudflare Workers",
426426
type: "module",
427427
main: "./dist/index.cjs",
@@ -617,5 +617,5 @@ exports.renderTemplate = renderTemplate;
617617
exports.sanitizeInput = sanitizeInput;
618618
exports.sanitizeObject = sanitizeObject;
619619
exports.templateRenderer = templateRenderer;
620-
//# sourceMappingURL=chunk-DMZI7OU3.cjs.map
621-
//# sourceMappingURL=chunk-DMZI7OU3.cjs.map
620+
//# sourceMappingURL=chunk-5HMR2SJW.cjs.map
621+
//# sourceMappingURL=chunk-5HMR2SJW.cjs.map
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/dist/chunk-5PH7K7YR.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/core/dist/chunk-5TO3OUFT.cjs.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)