json-object-editor 0.10.657 → 0.10.662

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,299 @@
1
+ # React Form Integration - Usage Example
2
+
3
+ ## Overview
4
+
5
+ This document shows how to set up a JOE page with a React-powered form using JSON form definitions.
6
+
7
+ ## Setup Steps
8
+
9
+ ### 1. Create JSON Form Definition Include
10
+
11
+ 1. In JOE, go to **Includes** schema
12
+ 2. Create a new include:
13
+ - **Name**: "Harmonious Wellness Form Definition"
14
+ - **Filetype**: `json`
15
+ - **Content**: Paste your `form-qs.json` content
16
+ - **Fill Template**: `false` (or `true` if you want to use `${this.}` variables)
17
+ 3. Save and note the `_id` of the include
18
+
19
+ ### 2. Create JOE Form Record
20
+
21
+ 1. Go to **Forms** schema
22
+ 2. Create a new form:
23
+ - **Name**: "Harmonious Wellness Health Questionnaire"
24
+ - **Save Submission**: `true`
25
+ - **Meta** (optional): Add `json_definition_include: "{include_id}"` if you want to link it
26
+ 3. Save and note the `_id` of the form
27
+
28
+ ### 3. Create React Form JS Include (if not already created)
29
+
30
+ 1. Go to **Includes** schema
31
+ 2. Create a new include:
32
+ - **Name**: "JOE React Form Renderer"
33
+ - **Filetype**: `js`
34
+ - **Content**: Copy content from `js/joe-react-form.js`
35
+ 3. Save and note the `_id` of the include
36
+
37
+ ### 4. Create JOE Page
38
+
39
+ 1. Go to **Pages** schema
40
+ 2. Create a new page:
41
+ - **Name**: "Health Questionnaire"
42
+ - **Site**: Select your site
43
+ - **Path**: `/health-questionnaire` (or your desired path)
44
+ - **Content Type**: `code` (or `module` for dynamic generation - see examples below)
45
+ - **Form**: Select the form you created in step 2
46
+ - **Includes**:
47
+ - Add the React Form JS include from step 3
48
+ - Add the JSON Form Definition include from step 1 (optional - formDefinition plugin can find it automatically)
49
+ - **Content**: Use the template below
50
+ - **Layout**: Select a layout (or create one with minimal structure)
51
+
52
+ **Note:** When using `${INCLUDES}` in your page content, JOE will automatically generate `<script>` and `<link>` tags for all JS and CSS includes you add here. The JSON include is accessed via the formDefinition API endpoint, not as a direct include.
53
+
54
+ ### 5. Page Content Template
55
+
56
+ **Option A: Using Code Content Type with Template Variables (Recommended)**
57
+
58
+ Set `content_type: 'code'` and use JOE template variables:
59
+
60
+ ```html
61
+ <!DOCTYPE html>
62
+ <html>
63
+ <head>
64
+ <meta charset="utf-8">
65
+ <meta name="viewport" content="width=device-width, initial-scale=1">
66
+ <title>${this.PAGE.name}</title>
67
+
68
+ <!-- Tailwind CSS (for styling) - Optional -->
69
+ <script src="https://cdn.tailwindcss.com"></script>
70
+
71
+ <!-- React from CDN - MUST load before ${INCLUDES} (which contains joe-react-form.js) -->
72
+ <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
73
+ <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
74
+
75
+ <!-- JOE automatically includes all JS/CSS from page.includes here -->
76
+ <!-- Note: joe-react-form.js will wait for React if needed, but loading React first is recommended -->
77
+ ${INCLUDES}
78
+ </head>
79
+ <body>
80
+ <div id="react-form-root"></div>
81
+ <script>
82
+ // Wait for joeReactForm to be available (script may still be loading)
83
+ function initForm() {
84
+ if (typeof joeReactForm !== 'undefined') {
85
+ joeReactForm.init({
86
+ rootId: 'react-form-root',
87
+ formDefinitionUrl: '/API/plugin/formBuilder/definition?formid=${this.PAGE.form}&pageid=${this.PAGE._id}',
88
+ formId: '${this.PAGE.form}'
89
+ });
90
+ } else {
91
+ // If not ready, wait for DOMContentLoaded or check again shortly
92
+ if (document.readyState === 'loading') {
93
+ document.addEventListener('DOMContentLoaded', initForm);
94
+ } else {
95
+ setTimeout(initForm, 50);
96
+ }
97
+ }
98
+ }
99
+ initForm();
100
+ </script>
101
+ </body>
102
+ </html>
103
+ ```
104
+
105
+ **Benefits:**
106
+ - `${INCLUDES}` automatically includes all JS/CSS from page's includes array
107
+ - `${this.PAGE.form}` and `${this.PAGE._id}` automatically use linked form and page IDs
108
+ - No hardcoded IDs to maintain!
109
+
110
+ **Option B: Using Module Content Type**
111
+
112
+ Set `content_type: 'module'` - see the "Alternative: Using Module Content Type" section below.
113
+
114
+ ### Alternative: Using Module Content Type (Recommended)
115
+
116
+ You can use `content_type: 'module'` to generate HTML dynamically using JOE's template patterns:
117
+
118
+ ```javascript
119
+ module.exports = function(content) {
120
+ var page = content.PAGE;
121
+ var form = page.form ? JOE.Cache.findByID('form', page.form) : null;
122
+
123
+ if (!form) {
124
+ return '<div>Error: No form linked to this page</div>';
125
+ }
126
+
127
+ // Use formDefinition plugin to auto-find JSON include from page
128
+ // This will find the JSON include from page.includes automatically
129
+ var formDefUrl = '/API/plugin/formBuilder/definition?formid=' + form._id + '&pageid=' + page._id;
130
+
131
+ return `<!DOCTYPE html>
132
+ <html>
133
+ <head>
134
+ <meta charset="utf-8">
135
+ <meta name="viewport" content="width=device-width, initial-scale=1">
136
+ <title>${page.name}</title>
137
+ <script src="https://cdn.tailwindcss.com"></script>
138
+ <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
139
+ <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
140
+ ${content.INCLUDES}
141
+ </head>
142
+ <body>
143
+ <div id="react-form-root"></div>
144
+ <script>
145
+ // Wait for joeReactForm to be available (script may still be loading)
146
+ function initForm() {
147
+ if (typeof joeReactForm !== 'undefined') {
148
+ joeReactForm.init({
149
+ rootId: 'react-form-root',
150
+ formDefinitionUrl: '${formDefUrl}',
151
+ formId: '${form._id}'
152
+ });
153
+ } else {
154
+ if (document.readyState === 'loading') {
155
+ document.addEventListener('DOMContentLoaded', initForm);
156
+ } else {
157
+ setTimeout(initForm, 50);
158
+ }
159
+ }
160
+ }
161
+ initForm();
162
+ </script>
163
+ </body>
164
+ </html>`;
165
+ };
166
+ ```
167
+
168
+ **Key improvements:**
169
+ - Uses `${content.INCLUDES}` - automatically includes all JS/CSS from page's includes array
170
+ - Uses `formBuilder.definition` endpoint with `pageid` - automatically finds JSON include from page
171
+ - No need to manually specify include IDs
172
+
173
+ ### Alternative: Using Code Content Type with Template Variables
174
+
175
+ You can also use `content_type: 'code'` with JOE template variables:
176
+
177
+ ```html
178
+ <!DOCTYPE html>
179
+ <html>
180
+ <head>
181
+ <meta charset="utf-8">
182
+ <meta name="viewport" content="width=device-width, initial-scale=1">
183
+ <title>${this.PAGE.name}</title>
184
+ <script src="https://cdn.tailwindcss.com"></script>
185
+ <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
186
+ <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
187
+ ${INCLUDES}
188
+ </head>
189
+ <body>
190
+ <div id="react-form-root"></div>
191
+ <script>
192
+ // Wait for joeReactForm to be available (script may still be loading)
193
+ function initForm() {
194
+ if (typeof joeReactForm !== 'undefined') {
195
+ joeReactForm.init({
196
+ rootId: 'react-form-root',
197
+ formDefinitionUrl: '/API/plugin/formBuilder/definition?formid=${this.PAGE.form}&pageid=${this.PAGE._id}',
198
+ formId: '${this.PAGE.form}'
199
+ });
200
+ } else {
201
+ if (document.readyState === 'loading') {
202
+ document.addEventListener('DOMContentLoaded', initForm);
203
+ } else {
204
+ setTimeout(initForm, 50);
205
+ }
206
+ }
207
+ }
208
+ initForm();
209
+ </script>
210
+ </body>
211
+ </html>
212
+ ```
213
+
214
+ This automatically:
215
+ - Uses `${INCLUDES}` to inject all page includes (JS/CSS)
216
+ - Uses `${this.PAGE.form}` and `${this.PAGE._id}` to pass form and page IDs
217
+ - No hardcoded IDs needed!
218
+
219
+ ## API Endpoints
220
+
221
+ ### Get Form Definition
222
+
223
+ ```
224
+ GET /API/plugin/formBuilder/definition?include_id={include_id}
225
+ GET /API/plugin/formBuilder/definition?formid={form_id}&field=json_definition_include
226
+ ```
227
+
228
+ Returns: JSON form definition (form-qs.json format)
229
+
230
+ ### Submit Form
231
+
232
+ ```
233
+ POST /API/plugin/formBuilder/submission
234
+ Content-Type: application/json
235
+
236
+ {
237
+ "formid": "{form_id}",
238
+ "submission": {
239
+ "first_name": "John",
240
+ "last_name": "Doe",
241
+ ...
242
+ }
243
+ }
244
+ ```
245
+
246
+ Returns: Submission confirmation or error
247
+
248
+ ## How It Works
249
+
250
+ 1. **Page loads** → Includes React CDN and form renderer JS
251
+ 2. **Form renderer initializes** → Fetches JSON form definition from include
252
+ 3. **React renders form** → Based on JSON structure (sections, fields, visibility rules)
253
+ 4. **User fills form** → React manages state and conditional visibility
254
+ 5. **User submits** → Data sent to `/API/plugin/formBuilder/submission`
255
+ 6. **JOE saves submission** → Creates `submission` record linked to form
256
+
257
+ ## Customization
258
+
259
+ ### Styling
260
+
261
+ The form uses Tailwind CSS classes. You can:
262
+ - Include Tailwind CDN (as shown above)
263
+ - Add custom CSS via include
264
+ - Modify classes in `joe-react-form.js`
265
+
266
+ ### Form Definition Template Variables
267
+
268
+ If you enable `fillTemplate` on the JSON include, you can use variables like:
269
+ ```json
270
+ {
271
+ "formName": "${this.SITE.name} - Health Questionnaire",
272
+ "version": "${this.WEBCONFIG.version}"
273
+ }
274
+ ```
275
+
276
+ ### Form Callbacks
277
+
278
+ The JOE form record supports:
279
+ - **Callback**: Client-side function called after submission
280
+ - **Server Action**: Server-side function called during submission
281
+ - **Validate**: Client-side validation function
282
+
283
+ These can be added to the form record and will be executed as configured.
284
+
285
+ ## Troubleshooting
286
+
287
+ ### Form not loading
288
+ - Check browser console for errors
289
+ - Verify all include IDs are correct
290
+ - Ensure React CDN is loading (check Network tab)
291
+
292
+ ### Submission errors
293
+ - Verify form ID is correct
294
+ - Check that form has `save_submission: true`
295
+ - Check server logs for submission errors
296
+
297
+ ### Styling issues
298
+ - Ensure Tailwind CSS is loaded (or adjust classes)
299
+ - Check that Tailwind CDN version supports all classes used
@@ -0,0 +1,397 @@
1
+ # React Form Integration Strategy for JOE
2
+
3
+ ## Executive Summary
4
+
5
+ This document outlines strategy options for integrating:
6
+ 1. **JSON-based form definitions** (from `form-qs.json` format)
7
+ 2. **React Single Page Application** as a page type in JOE
8
+ 3. **Form submission storage** into JOE's submission system
9
+
10
+ ---
11
+
12
+ ## Current State Analysis
13
+
14
+ ### JOE Form System (Current)
15
+ - **Schema**: `form` schema with `sections` (objectList), `questions` (references to question schema)
16
+ - **Rendering**: `formBuilder` plugin renders HTML forms server-side
17
+ - **Submission**: POST to `/API/plugin/formBuilder/submission` with `{formid, submission: {...}}`
18
+ - **Storage**: Creates `submission` items with `data`, `form_name`, `form` (reference), `visitor`, `submission_date`
19
+
20
+ ### JOE Page System (Current)
21
+ - **Content Types**: `wysiwyg`, `code`, `plugin`, `module`
22
+ - **Module Type**: Server-side JS function that returns HTML string
23
+ - **Includes**: Can load JS/CSS files via `include` schema (served at `/_include/{id}`)
24
+ - **Layouts**: Templates with `${this.PAGE.content}` placeholder
25
+
26
+ ### Target Requirements
27
+ 1. Use JSON file (`form-qs.json`) for form structure and rules
28
+ 2. Embed React SPA as a page in JOE
29
+ 3. Submit to JOE submission storage on form completion
30
+
31
+ ---
32
+
33
+ ## Strategy Options
34
+
35
+ ### **Option 1: React SPA as Code Page with API Bridge** ⭐ **RECOMMENDED**
36
+
37
+ #### Architecture
38
+ - **Page Type**: `content_type: 'code'`
39
+ - **React App**: Compiled/bundled React app loaded via includes or inline
40
+ - **JSON Loading**: React app fetches form definition JSON via API endpoint
41
+ - **Submission**: React app posts to JOE submission API endpoint
42
+
43
+ #### Implementation Details
44
+
45
+ **1. Create Form Definition API Endpoint**
46
+ ```javascript
47
+ // server/plugins/formBuilder.js
48
+ this.definition = function(req, res) {
49
+ var formId = req.query.formid || req.params.formid;
50
+ // Load form-qs.json format, return as JSON
51
+ // Could be stored as include or in a new form_definition schema
52
+ }
53
+ ```
54
+
55
+ **2. Create Submission API Endpoint** (extend existing or new)
56
+ ```javascript
57
+ // Extend server/plugins/formBuilder.js or create formSubmission.js
58
+ this.submit = function(data, req) {
59
+ // Accept JSON form submission, map to JOE submission format
60
+ // Create submission record with form reference
61
+ }
62
+ ```
63
+
64
+ **3. React App Integration**
65
+ - React app bundled (webpack/vite) and stored as an `include` (JS file)
66
+ - Page content: `<div id="react-form-root"></div><script src="/_include/{react-bundle-id}"></script>`
67
+ - React app:
68
+ - Fetches form definition from `/API/plugin/formBuilder/definition?formid={id}`
69
+ - Renders form using `react-form-spa-ex.js` logic
70
+ - Submits to `/API/plugin/formBuilder/submission` (or new endpoint)
71
+
72
+ #### Pros
73
+ - ✅ Leverages existing JOE infrastructure
74
+ - ✅ React app is independent and can be versioned/updated separately
75
+ - ✅ Works with existing submission storage
76
+ - ✅ Minimal changes to JOE core
77
+ - ✅ Can reuse existing form validation/storage logic
78
+
79
+ #### Cons
80
+ - ⚠️ Requires bundling React app separately
81
+ - ⚠️ Two API endpoints to maintain (form definition + submission)
82
+ - ⚠️ React app needs to know JOE API structure
83
+
84
+ #### Estimated Effort
85
+ - **Low-Medium**: ~2-3 days
86
+ - API endpoint for form definitions: 4-6 hours
87
+ - Submission endpoint extension: 2-4 hours
88
+ - React app integration/hooking: 4-6 hours
89
+ - Testing: 4-6 hours
90
+
91
+ ---
92
+
93
+ ### **Option 2: New "spa" Content Type with Form Plugin**
94
+
95
+ #### Architecture
96
+ - **Page Type**: New `content_type: 'spa'` option
97
+ - **Form Plugin**: New `reactForm` plugin that handles React app bootstrapping
98
+ - **Configuration**: Page stores React component path and form definition reference
99
+
100
+ #### Implementation Details
101
+
102
+ **1. Extend Page Schema**
103
+ ```javascript
104
+ // server/schemas/page.js
105
+ { name:'content_type', type:'string', enumValues:['wysiwyg','code','plugin','module','spa'] }
106
+ // Add fields: spa_component, form_definition_id
107
+ ```
108
+
109
+ **2. Create React Form Plugin**
110
+ ```javascript
111
+ // server/plugins/reactForm.js
112
+ this.render = function(data, req) {
113
+ var page = data.page;
114
+ var formDef = loadFormDefinition(page.form_definition_id);
115
+ // Return HTML with:
116
+ // - React libraries (CDN or includes)
117
+ // - Form definition as JSON in <script> tag
118
+ // - React component mount point
119
+ // - Submission handler that calls JOE API
120
+ }
121
+ ```
122
+
123
+ **3. Submission Handling**
124
+ - Plugin generates submission handler that posts to existing formBuilder endpoint
125
+ - Maps JSON form format to JOE submission format
126
+
127
+ #### Pros
128
+ - ✅ Native JOE integration
129
+ - ✅ Form definitions can be stored as JOE items
130
+ - ✅ Consistent with other page content types
131
+ - ✅ Can be configured through JOE UI
132
+
133
+ #### Cons
134
+ - ⚠️ Requires schema changes to page
135
+ - ⚠️ More complex implementation
136
+ - ⚠️ Need to handle React bundling/delivery
137
+
138
+ #### Estimated Effort
139
+ - **Medium**: ~4-5 days
140
+ - Schema extensions: 2-4 hours
141
+ - React form plugin: 1-2 days
142
+ - React bundling strategy: 4-8 hours
143
+ - UI for configuring SPA pages: 4-6 hours
144
+ - Testing: 1 day
145
+
146
+ ---
147
+
148
+ ### **Option 3: Module Type with Server-Side React Rendering**
149
+
150
+ #### Architecture
151
+ - **Page Type**: `content_type: 'module'`
152
+ - **SSR**: Use React server-side rendering (via `react-dom/server`)
153
+ - **Hydration**: Client-side React app for interactivity
154
+
155
+ #### Implementation Details
156
+
157
+ **1. Module Function**
158
+ ```javascript
159
+ // Page content (module type)
160
+ module.exports = async function(content) {
161
+ var React = require('react');
162
+ var ReactDOMServer = require('react-dom/server');
163
+ var FormApp = require('./path/to/react-form-spa-ex.js');
164
+ var formDef = loadFormDefinition(content.PAGE.meta.form_definition_id);
165
+
166
+ var html = ReactDOMServer.renderToString(
167
+ React.createElement(FormApp, { formDefinition: formDef })
168
+ );
169
+
170
+ return `<div id="root">${html}</div>
171
+ <script>window.__FORM_DEF__ = ${JSON.stringify(formDef)};</script>
172
+ <script src="/_include/{react-bundle-id}"></script>`;
173
+ }
174
+ ```
175
+
176
+ **2. Client Hydration**
177
+ - React app mounts and hydrates the server-rendered HTML
178
+ - Handles form submission to JOE API
179
+
180
+ #### Pros
181
+ - ✅ SEO-friendly (server-rendered)
182
+ - ✅ Faster initial render
183
+ - ✅ Uses existing module type
184
+
185
+ #### Cons
186
+ - ⚠️ Requires React SSR dependencies on server
187
+ - ⚠️ More complex build/deployment
188
+ - ⚠️ Node.js React dependencies add overhead
189
+ - ⚠️ Hydration complexity
190
+
191
+ #### Estimated Effort
192
+ - **Medium-High**: ~5-7 days
193
+ - SSR setup: 1-2 days
194
+ - Hydration logic: 1 day
195
+ - Build configuration: 1 day
196
+ - Testing/debugging: 2-3 days
197
+
198
+ ---
199
+
200
+ ### **Option 4: Hybrid - Form Definition Schema + React Include**
201
+
202
+ #### Architecture
203
+ - **New Schema**: `form_definition` schema to store JSON form definitions
204
+ - **Form Mapping**: Bridge between JSON form format and JOE form/question schemas
205
+ - **Page**: Code or module type that loads React app and form definition
206
+
207
+ #### Implementation Details
208
+
209
+ **1. Create Form Definition Schema**
210
+ ```javascript
211
+ // server/schemas/form_definition.js
212
+ {
213
+ name: 'form_definition',
214
+ fields: [
215
+ { name: 'form_id', type: 'string' }, // matches form-qs.json formId
216
+ { name: 'definition', type: 'object' }, // full form-qs.json structure
217
+ { name: 'form', type: 'string', isReference: true } // link to JOE form
218
+ ]
219
+ }
220
+ ```
221
+
222
+ **2. Form Bridge Service**
223
+ ```javascript
224
+ // server/plugins/formBridge.js
225
+ // Convert form-qs.json format to JOE form/questions
226
+ // Or: Store JSON format, map on-the-fly for submissions
227
+ ```
228
+
229
+ **3. React App**
230
+ - Loads form definition from API
231
+ - Renders form
232
+ - Submits in format compatible with JOE submissions
233
+
234
+ #### Pros
235
+ - ✅ JSON form definitions stored as first-class JOE items
236
+ - ✅ Can sync/import from external JSON files
237
+ - ✅ Separation of concerns (definition vs. rendering)
238
+ - ✅ Can potentially auto-generate JOE forms from JSON
239
+
240
+ #### Cons
241
+ - ⚠️ Additional schema to maintain
242
+ - ⚠️ Need mapping/bridge logic
243
+ - ⚠️ More moving parts
244
+
245
+ #### Estimated Effort
246
+ - **Medium**: ~4-5 days
247
+ - Form definition schema: 4-6 hours
248
+ - Bridge/mapping logic: 1-2 days
249
+ - React integration: 1 day
250
+ - Testing: 1 day
251
+
252
+ ---
253
+
254
+ ## Recommended Approach: **Option 1 with Option 4 Enhancements**
255
+
256
+ ### Phase 1: Quick Win (Option 1)
257
+ 1. Create API endpoint to serve form definitions (store JSON in includes or files)
258
+ 2. Extend formBuilder submission endpoint to accept JSON format submissions
259
+ 3. Create React app that:
260
+ - Loads form definition from API
261
+ - Renders form (based on react-form-spa-ex.js)
262
+ - Submits to JOE endpoint
263
+ 4. Embed React app in a JOE page via includes
264
+
265
+ ### Phase 2: Enhanced (Option 4 additions)
266
+ 1. Create `form_definition` schema to store JSON form definitions in JOE
267
+ 2. Add UI to import/manage form definitions
268
+ 3. Optionally: Auto-create JOE forms from JSON definitions for reporting/admin
269
+
270
+ ### Why This Approach?
271
+ - ✅ **Fastest to implement**: Leverages existing infrastructure
272
+ - ✅ **Low risk**: Minimal changes to core JOE systems
273
+ - ✅ **Flexible**: Can evolve to Option 4 later without breaking changes
274
+ - ✅ **Testable**: Can test React app independently
275
+
276
+ ---
277
+
278
+ ## Technical Implementation Details
279
+
280
+ ### JSON Form Format Mapping
281
+
282
+ The `form-qs.json` format has:
283
+ - `formId`, `formName`, `version`
284
+ - `sections[]` with `fields[]`
285
+ - `visibility` rules with `whenAll`/`whenAny` conditions
286
+ - `dataExport` settings
287
+
288
+ **Mapping to JOE Submissions:**
289
+ ```javascript
290
+ {
291
+ itemtype: 'submission',
292
+ form: {joe_form_id}, // reference to JOE form
293
+ form_name: formDef.formName,
294
+ data: {
295
+ // Flattened field values
296
+ first_name: "...",
297
+ last_name: "...",
298
+ // ... all field values
299
+ },
300
+ submission_date: new Date().toISOString(),
301
+ visitor: visitor_id, // from form if configured
302
+ source: req.headers.referer
303
+ }
304
+ ```
305
+
306
+ ### React App Submission Handler
307
+
308
+ ```javascript
309
+ async function submitForm(formData, formId) {
310
+ const response = await fetch('/API/plugin/formBuilder/submission', {
311
+ method: 'POST',
312
+ headers: { 'Content-Type': 'application/json' },
313
+ body: JSON.stringify({
314
+ formid: formId, // JOE form ID
315
+ submission: formData // { first_name: "...", ... }
316
+ })
317
+ });
318
+ return response.json();
319
+ }
320
+ ```
321
+
322
+ ### Form Definition API
323
+
324
+ ```javascript
325
+ // GET /API/plugin/formBuilder/definition?formid={id}
326
+ // Returns: form-qs.json format
327
+ {
328
+ formId: "...",
329
+ formName: "...",
330
+ sections: [...],
331
+ settings: {...}
332
+ }
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Migration Path
338
+
339
+ 1. **Week 1**: Implement Option 1 (API endpoints + React integration)
340
+ 2. **Week 2**: Test with example form, refine submission mapping
341
+ 3. **Week 3** (Optional): Implement Option 4 enhancements (form_definition schema)
342
+ 4. **Week 4**: Documentation and production deployment
343
+
344
+ ---
345
+
346
+ ## Open Questions
347
+
348
+ 1. **Form Definition Storage**: Store JSON in includes, files, or new schema?
349
+ - **Recommendation**: Start with includes/files, move to schema in Phase 2
350
+
351
+ 2. **React Bundling**: Use CDN, bundle via build process, or serve from includes?
352
+ - **Recommendation**: Bundle React app, store as include for versioning
353
+
354
+ 3. **Form ID Mapping**: How to map `form-qs.json` `formId` to JOE `form._id`?
355
+ - **Recommendation**: Add `form_json_id` field to form schema, or store mapping in form_definition
356
+
357
+ 4. **Visitor Tracking**: How to identify visitors in React SPA context?
358
+ - **Recommendation**: Use existing visitor_id_field mechanism, pass via form definition
359
+
360
+ 5. **Validation**: Use React-side validation only, or also JOE-side?
361
+ - **Recommendation**: Client-side for UX, server-side for security (both)
362
+
363
+ ---
364
+
365
+ ## Next Steps
366
+
367
+ 1. **Decision**: Review options and select approach
368
+ 2. **Prototype**: Build minimal POC of selected option
369
+ 3. **Refine**: Iterate based on prototype feedback
370
+ 4. **Implement**: Full implementation
371
+ 5. **Test**: Comprehensive testing with example forms
372
+ 6. **Deploy**: Production deployment
373
+
374
+ ---
375
+
376
+ ## Appendix: File Structure
377
+
378
+ ```
379
+ server/
380
+ plugins/
381
+ formBuilder.js (extend - serves JSON form definitions via .definition() method, handles JSON submissions)
382
+
383
+ schemas/
384
+ form_definition.js (optional - Phase 2)
385
+
386
+ includes/
387
+ react-form-bundle.js (bundled React app)
388
+
389
+ pages/
390
+ react-form-example (page with React form)
391
+ ```
392
+
393
+ ---
394
+
395
+ **Document Version**: 1.0
396
+ **Date**: 2026-01-04
397
+ **Author**: AI Assistant + User Collaboration
package/dummy CHANGED
@@ -1,5 +1,13 @@
1
1
  {
2
- "cells": [],
2
+ "cells": [
3
+ {
4
+ "cell_type": "raw",
5
+ "metadata": {},
6
+ "source": [
7
+ "noop"
8
+ ]
9
+ }
10
+ ],
3
11
  "metadata": {
4
12
  "language_info": {
5
13
  "name": "python"