@cyprnet/node-red-contrib-uibuilder-formgen 0.4.11

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +22 -0
  3. package/README.md +58 -0
  4. package/docs/user-guide.html +565 -0
  5. package/examples/formgen-builder/src/index.html +921 -0
  6. package/examples/formgen-builder/src/index.js +1338 -0
  7. package/examples/portalsmith-formgen-example.json +531 -0
  8. package/examples/schema-builder-integration.json +109 -0
  9. package/examples/schemas/Banking/banking_fraud_report.json +102 -0
  10. package/examples/schemas/Banking/banking_kyc_update.json +59 -0
  11. package/examples/schemas/Banking/banking_loan_application.json +113 -0
  12. package/examples/schemas/Banking/banking_new_account.json +98 -0
  13. package/examples/schemas/Banking/banking_wire_transfer_request.json +94 -0
  14. package/examples/schemas/HR/hr_employee_change_form.json +65 -0
  15. package/examples/schemas/HR/hr_exit_interview.json +105 -0
  16. package/examples/schemas/HR/hr_job_application.json +166 -0
  17. package/examples/schemas/HR/hr_onboarding_request.json +140 -0
  18. package/examples/schemas/HR/hr_time_off_request.json +95 -0
  19. package/examples/schemas/HR/hr_training_request.json +70 -0
  20. package/examples/schemas/Healthcare/health_appointment_request.json +103 -0
  21. package/examples/schemas/Healthcare/health_incident_report.json +82 -0
  22. package/examples/schemas/Healthcare/health_lab_order_request.json +72 -0
  23. package/examples/schemas/Healthcare/health_medication_refill.json +72 -0
  24. package/examples/schemas/Healthcare/health_patient_intake.json +113 -0
  25. package/examples/schemas/IT/it_access_request.json +145 -0
  26. package/examples/schemas/IT/it_dhcp_reservation.json +175 -0
  27. package/examples/schemas/IT/it_dns_domain_external.json +192 -0
  28. package/examples/schemas/IT/it_dns_domain_internal.json +171 -0
  29. package/examples/schemas/IT/it_network_change_request.json +126 -0
  30. package/examples/schemas/IT/it_network_request-form.json +299 -0
  31. package/examples/schemas/IT/it_new_hardware_request.json +155 -0
  32. package/examples/schemas/IT/it_password_reset.json +133 -0
  33. package/examples/schemas/IT/it_software_license_request.json +93 -0
  34. package/examples/schemas/IT/it_static_ip_request.json +199 -0
  35. package/examples/schemas/IT/it_subnet_request_form.json +216 -0
  36. package/examples/schemas/Maintenance/maint_checklist.json +176 -0
  37. package/examples/schemas/Maintenance/maint_facility_issue_report.json +127 -0
  38. package/examples/schemas/Maintenance/maint_incident_intake.json +174 -0
  39. package/examples/schemas/Maintenance/maint_inventory_restock.json +79 -0
  40. package/examples/schemas/Maintenance/maint_safety_audit.json +92 -0
  41. package/examples/schemas/Maintenance/maint_vehicle_inspection.json +112 -0
  42. package/examples/schemas/Maintenance/maint_work_order.json +134 -0
  43. package/index.js +12 -0
  44. package/lib/licensing.js +254 -0
  45. package/nodes/portalsmith-license.html +40 -0
  46. package/nodes/portalsmith-license.js +23 -0
  47. package/nodes/uibuilder-formgen.html +261 -0
  48. package/nodes/uibuilder-formgen.js +598 -0
  49. package/package.json +47 -0
  50. package/scripts/normalize_schema_titles.py +77 -0
  51. package/templates/index.html.mustache +541 -0
  52. package/templates/index.js.mustache +1135 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to this package will be documented in this file.
4
+
5
+ ## 0.4.0
6
+
7
+ - Added **offline-first licensing framework** (Free vs Licensed).
8
+ - Added **PortalSmith License** config node (`portalsmith-license`) that stores a license key in Node-RED credentials.
9
+ - Added **license status indicator** in the `uibuilder-formgen` editor UI (local validation endpoint).
10
+ - Added generated portal **watermark + default branding** in Free mode and gated custom branding/logo when unlicensed.
11
+ - Added MIT license files and npm/Flow Library metadata polish.
12
+
13
+ ## 0.4.2
14
+
15
+ - Added `tools/generate-license.js` (internal helper) to generate signed license strings offline.
16
+
17
+ ## 0.4.3
18
+
19
+ - Added `tools/license-key.js` alias for `tools/generate-license.js`.
20
+
21
+ ## 0.4.4
22
+
23
+ - Show which verifier public key is being used (env vs embedded) in License Status to help troubleshoot `signature_invalid`.
24
+
25
+ ## 0.4.5
26
+
27
+ - Do not include `tools/` in the packaged install `.tgz` (repo-only development utilities).
28
+
29
+ ## 0.4.6
30
+
31
+ - Add `PORTALSMITH_LICENSE_PUBLIC_KEY_PEM_FILE` support for robust license verification in systemd/docker environments.
32
+
33
+
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CyprNet Solutions, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ ## PortalSmith FormGen (uibuilder-formgen)
2
+
3
+ PortalSmith FormGen is a Node-RED contrib module that generates schema-driven uibuilder portals (HTML/JS) from a JSON schema. It is designed for **no-build-step** operation: generate → open in browser → submit back to Node-RED.
4
+
5
+ ### Website
6
+
7
+ CyprNet Solutions: `https://www.cyprnetsolutions.com`
8
+
9
+ ### Features
10
+
11
+ - **Schema-driven forms**: sections + fields + basic validation
12
+ - **Export**: JSON/CSV/HTML (client-side)
13
+ - **Draft save/load**: browser + file workflows
14
+ - **Theme + branding**: light/dark theme support; logo support (licensed)
15
+ - **Results page**: optional result rendering after HTTP submit
16
+
17
+ ### Requirements (dependencies)
18
+
19
+ - **Node.js**: 18+ (20.x recommended)
20
+ - **Node-RED**: 3.1+ (4.x recommended)
21
+ - **node-red-contrib-uibuilder**: v7.x
22
+ - **Browser**: modern Chrome/Firefox/Edge
23
+
24
+ ### Installation
25
+
26
+ Install into your Node-RED userDir:
27
+
28
+ ```bash
29
+ cd ~/.node-red
30
+ npm install @cyprnet/node-red-contrib-uibuilder-formgen
31
+ ```
32
+
33
+ Then restart Node-RED.
34
+
35
+ ### Quick start
36
+
37
+ 1. Create a `uibuilder` instance (example URL: `form-jobapp`) and deploy.
38
+ 2. Send a schema into `uibuilder-formgen` as `msg.schema` (or use the example flow).
39
+ 3. Open `/uibuilder/<instance>/` in your browser.
40
+
41
+ ### Licensing (offline-first)
42
+
43
+ - **Free (default)**: watermarked portal + default PortalSmith branding.
44
+ - **Licensed (PRO)**: allows watermark removal and custom branding/logo (if enabled by your license features).
45
+
46
+ To apply a license, paste the license key provided by CyprNet into the shared **`portalsmith-license`** config node and reference it from your `uibuilder-formgen` nodes. Restart Node-RED after installing/updating the module.
47
+
48
+ ### Documentation & examples
49
+
50
+ - **Offline user guide** (packaged): `docs/user-guide.html`
51
+ - **Example flow**: `examples/portalsmith-formgen-example.json`
52
+ - **Industry schemas**: `examples/schemas/`
53
+ - **Schema Builder frontend files**: `examples/formgen-builder/src/index.html` and `examples/formgen-builder/src/index.js`
54
+
55
+ ### License
56
+
57
+ MIT. See `LICENSE`.
58
+
@@ -0,0 +1,565 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>PortalSmith FormGen - Offline User Guide</title>
7
+ <style>
8
+ :root {
9
+ --bg: #ffffff;
10
+ --text: #111827;
11
+ --muted: #4b5563;
12
+ --border: #e5e7eb;
13
+ --panel: #f9fafb;
14
+ --accent: #2563eb;
15
+ --codebg: #0b1020;
16
+ --codetext: #e5e7eb;
17
+ }
18
+ @media (prefers-color-scheme: dark) {
19
+ :root {
20
+ --bg: #0b1220;
21
+ --text: #e5e7eb;
22
+ --muted: #aab3c2;
23
+ --border: #243041;
24
+ --panel: #0f172a;
25
+ --accent: #60a5fa;
26
+ --codebg: #060913;
27
+ --codetext: #e5e7eb;
28
+ }
29
+ }
30
+ html, body { height: 100%; }
31
+ body {
32
+ margin: 0;
33
+ background: var(--bg);
34
+ color: var(--text);
35
+ font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
36
+ line-height: 1.5;
37
+ }
38
+ a { color: var(--accent); text-decoration: none; }
39
+ a:hover { text-decoration: underline; }
40
+ .container {
41
+ max-width: 1100px;
42
+ margin: 0 auto;
43
+ padding: 28px 18px 60px;
44
+ }
45
+ .topbar {
46
+ border: 1px solid var(--border);
47
+ background: var(--panel);
48
+ border-radius: 10px;
49
+ padding: 14px 16px;
50
+ margin-bottom: 18px;
51
+ }
52
+ h1 { margin: 0 0 6px; font-size: 28px; }
53
+ .subtitle { color: var(--muted); margin: 0; }
54
+ .grid {
55
+ display: grid;
56
+ grid-template-columns: 320px 1fr;
57
+ gap: 18px;
58
+ align-items: start;
59
+ }
60
+ @media (max-width: 980px) {
61
+ .grid { grid-template-columns: 1fr; }
62
+ }
63
+ .toc {
64
+ position: sticky;
65
+ top: 14px;
66
+ border: 1px solid var(--border);
67
+ border-radius: 10px;
68
+ padding: 14px 14px 10px;
69
+ background: var(--panel);
70
+ }
71
+ .toc h2 { margin: 0 0 8px; font-size: 16px; }
72
+ .toc ul { margin: 0; padding-left: 18px; }
73
+ .toc li { margin: 4px 0; }
74
+ .content section {
75
+ border: 1px solid var(--border);
76
+ border-radius: 10px;
77
+ padding: 16px;
78
+ background: rgba(0,0,0,0.01);
79
+ margin-bottom: 14px;
80
+ }
81
+ .content h2 { margin: 0 0 8px; font-size: 20px; }
82
+ .content h3 { margin: 14px 0 6px; font-size: 16px; }
83
+ .note {
84
+ border-left: 4px solid var(--accent);
85
+ background: var(--panel);
86
+ padding: 10px 12px;
87
+ border-radius: 8px;
88
+ margin: 10px 0;
89
+ color: var(--muted);
90
+ }
91
+ .warn {
92
+ border-left: 4px solid #f59e0b;
93
+ }
94
+ .ok {
95
+ border-left: 4px solid #10b981;
96
+ }
97
+ code, pre {
98
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
99
+ }
100
+ pre {
101
+ background: var(--codebg);
102
+ color: var(--codetext);
103
+ padding: 12px 12px;
104
+ border-radius: 10px;
105
+ overflow: auto;
106
+ border: 1px solid rgba(255,255,255,0.08);
107
+ }
108
+ .pill {
109
+ display: inline-block;
110
+ border: 1px solid var(--border);
111
+ border-radius: 999px;
112
+ padding: 2px 10px;
113
+ background: var(--panel);
114
+ font-size: 12px;
115
+ color: var(--muted);
116
+ margin-right: 6px;
117
+ }
118
+ table {
119
+ width: 100%;
120
+ border-collapse: collapse;
121
+ margin: 10px 0;
122
+ border: 1px solid var(--border);
123
+ border-radius: 10px;
124
+ overflow: hidden;
125
+ }
126
+ th, td {
127
+ border-bottom: 1px solid var(--border);
128
+ padding: 10px 10px;
129
+ text-align: left;
130
+ vertical-align: top;
131
+ }
132
+ th { background: var(--panel); }
133
+ .footer {
134
+ margin-top: 22px;
135
+ color: var(--muted);
136
+ font-size: 13px;
137
+ }
138
+ @media print {
139
+ .toc { position: static; }
140
+ a { color: #000; text-decoration: underline; }
141
+ .topbar, .content section { break-inside: avoid; }
142
+ }
143
+ </style>
144
+ </head>
145
+ <body>
146
+ <div class="container">
147
+ <div class="topbar">
148
+ <h1>PortalSmith FormGen - Offline User Guide</h1>
149
+ <p class="subtitle">Everything you need to install, configure, generate portals, use the schema builder, and customize formgen (offline HTML).</p>
150
+ <div class="subtitle">
151
+ <span class="pill">Node-RED contrib: <code>node-red-contrib-uibuilder-formgen</code></span>
152
+ <span class="pill">Works with: <code>uibuilder</code> + Vue 2 portals</span>
153
+ </div>
154
+ </div>
155
+
156
+ <div class="grid">
157
+ <nav class="toc" aria-label="Table of Contents">
158
+ <h2>Contents</h2>
159
+ <ul>
160
+ <li><a href="#what-you-get">What you get</a></li>
161
+ <li><a href="#requirements">Requirements & versions</a></li>
162
+ <li><a href="#install">Install & upgrade</a></li>
163
+ <li><a href="#licensing">Licensing (Free vs Licensed)</a></li>
164
+ <li><a href="#folders">Folder locations (standard + Projects)</a></li>
165
+ <li><a href="#schema-builder">Schema Builder (form designer)</a></li>
166
+ <li><a href="#schemas">Schema examples library (industry templates)</a></li>
167
+ <li><a href="#schema-reference">Schema reference (field types)</a></li>
168
+ <li><a href="#generate">Generating a portal (uibuilder-formgen)</a></li>
169
+ <li><a href="#customize">Customization options (theme, logo, submit, API proxy)</a></li>
170
+ <li><a href="#submit-results">Submitting & results page</a></li>
171
+ <li><a href="#drafts-exports">Drafts & exports</a></li>
172
+ <li><a href="#troubleshooting">Troubleshooting</a></li>
173
+ <li><a href="#security">Security notes</a></li>
174
+ </ul>
175
+ </nav>
176
+
177
+ <main class="content">
178
+ <section id="what-you-get">
179
+ <h2>What you get</h2>
180
+ <p>
181
+ PortalSmith FormGen generates a complete uibuilder portal (HTML + JS) from a simple JSON schema.
182
+ You can design schemas using the Schema Builder and then generate portals on demand.
183
+ </p>
184
+ <ul>
185
+ <li><strong>Schema Builder</strong>: a UI that helps you create schemas without hand-writing JSON.</li>
186
+ <li><strong>Generated Form Portal</strong>: a user-facing form app with:
187
+ <ul>
188
+ <li>Validation</li>
189
+ <li>Draft save/load</li>
190
+ <li>Export JSON/CSV/HTML</li>
191
+ <li>Submit + Result page (Table/JSON)</li>
192
+ </ul>
193
+ </li>
194
+ <li><strong>Industry templates</strong>: ready-to-use example schemas (IT, HR, Banking, Healthcare, Maintenance).</li>
195
+ </ul>
196
+ </section>
197
+
198
+ <section id="requirements">
199
+ <h2>Requirements & versions</h2>
200
+
201
+ <p>
202
+ PortalSmith FormGen generates uibuilder portals that rely on the modern uibuilder client API and
203
+ recent Node.js runtime behavior. The following versions are the recommended baseline for a
204
+ clean install.
205
+ </p>
206
+
207
+ <h3>Minimum versions (recommended baseline)</h3>
208
+ <ul>
209
+ <li><strong>Node.js:</strong> 18.x LTS or newer (recommended: 20.x LTS)</li>
210
+ <li><strong>npm:</strong> use the version bundled with Node.js (Node 18 typically npm 9+, Node 20 typically npm 10+)</li>
211
+ <li><strong>Node-RED:</strong> 3.1+ minimum (4.x recommended)</li>
212
+ <li><strong>node-red-contrib-uibuilder:</strong> v7.x (recommended: latest v7)</li>
213
+ <li><strong>Browser:</strong> modern Chrome / Firefox / Edge</li>
214
+ </ul>
215
+
216
+ <h3>Why these minimums matter</h3>
217
+ <ul>
218
+ <li>
219
+ Generated portals assume the <strong>uibuilder v7 IIFE client</strong>
220
+ (<code>uibuilder.iife.min.js</code>) and use the modern
221
+ <code>onChange('msg', ...)</code> client API style.
222
+ </li>
223
+ <li>
224
+ Draft <strong>Load</strong> uses a browser file picker, which is supported reliably only by
225
+ modern browsers.
226
+ </li>
227
+ </ul>
228
+
229
+ <div class="note ok">
230
+ <strong>Known-good test environment:</strong>
231
+ Node.js 20.19.x, Node-RED 4.0.x, uibuilder v7.x
232
+ </div>
233
+
234
+ <div class="note warn">
235
+ <strong>Browser TLS note:</strong>
236
+ Browsers cannot bypass invalid or self-signed TLS certificates for direct HTTP requests.
237
+ If you must call a self-signed API, use the <strong>server-side API proxy</strong> feature in
238
+ <code>uibuilder-formgen</code>.
239
+ </div>
240
+
241
+ <div class="note">
242
+ <strong>uibuilder sanity check:</strong>
243
+ If a generated portal appears broken or does not receive messages, verify that the page
244
+ successfully loads
245
+ <code>../uibuilder/uibuilder.iife.min.js</code>. This confirms that uibuilder v7 is installed
246
+ and serving the client bundle.
247
+ </div>
248
+ </section>
249
+
250
+ <section id="install">
251
+ <h2>Install & upgrade</h2>
252
+ <h3>Install the node</h3>
253
+ <ol>
254
+ <li>In Node-RED: Menu → Manage palette → Install</li>
255
+ <li>Install <code>node-red-contrib-uibuilder-formgen</code> (or install from a <code>.tgz</code> file)</li>
256
+ <li><strong>Restart Node-RED</strong></li>
257
+ </ol>
258
+
259
+ <h3>Install/upgrade uibuilder</h3>
260
+ <ol>
261
+ <li>In Node-RED: Menu → Manage palette → Install</li>
262
+ <li>Install/upgrade <code>node-red-contrib-uibuilder</code></li>
263
+ <li>Restart Node-RED if prompted</li>
264
+ </ol>
265
+ </section>
266
+
267
+ <section id="licensing">
268
+ <h2>Licensing (Free vs Licensed)</h2>
269
+ <p>
270
+ PortalSmith FormGen supports an <strong>offline-first</strong> licensing model. License validation happens locally in Node-RED.
271
+ There is <strong>no phone-home</strong> and no external verification service.
272
+ </p>
273
+
274
+ <h3>Free mode (default)</h3>
275
+ <ul>
276
+ <li>Fully functional form generation</li>
277
+ <li>Generated portals show a small watermark: <strong>“Powered by PortalSmith FormGen”</strong></li>
278
+ <li>Default PortalSmith branding is used</li>
279
+ <li>Custom logo/branding is disabled (attempts are ignored with a warning)</li>
280
+ </ul>
281
+
282
+ <h3>Licensed (PRO)</h3>
283
+ <ul>
284
+ <li>Allows watermark removal (if enabled in the license features)</li>
285
+ <li>Allows custom branding/logo (if enabled in the license features)</li>
286
+ </ul>
287
+
288
+ <h3>Where to set the license key</h3>
289
+ <ul>
290
+ <li><strong>Shared (recommended):</strong> create a <code>portalsmith-license</code> config node and select it in each <code>uibuilder-formgen</code> node.</li>
291
+ <li><strong>Per-node override:</strong> paste a key into the <code>uibuilder-formgen</code> node’s <strong>License Key</strong> field.</li>
292
+ <li><strong>Environment variable (optional):</strong> <code>PORTALSMITH_LICENSE</code></li>
293
+ </ul>
294
+
295
+ <div class="note">
296
+ <strong>Format:</strong> License keys are deterministic signed strings of the form <code>PSLF1.&lt;payload&gt;.&lt;signature&gt;</code>.
297
+ The payload is not secret; the signature provides authenticity.
298
+ </div>
299
+ </section>
300
+
301
+ <section id="folders">
302
+ <h2>Folder locations (standard + Projects)</h2>
303
+ <p>There are two common layouts:</p>
304
+
305
+ <h3>Standard Node-RED userDir</h3>
306
+ <pre>~/.node-red/
307
+ uibuilder/
308
+ &lt;instance&gt;/
309
+ src/
310
+ index.html
311
+ index.js
312
+ form.schema.json</pre>
313
+
314
+ <h3>Node-RED Projects</h3>
315
+ <pre>~/.node-red/projects/&lt;projectName&gt;/
316
+ uibuilder/
317
+ &lt;instance&gt;/
318
+ src/
319
+ index.html
320
+ index.js
321
+ form.schema.json</pre>
322
+
323
+ <div class="note ok">
324
+ <strong>Tip:</strong> FormGen can write to either layout using path options (Project name / uibRootDir / instanceRootDir).
325
+ </div>
326
+ </section>
327
+
328
+ <section id="schema-builder">
329
+ <h2>Schema Builder (form designer)</h2>
330
+ <p>The Schema Builder is a uibuilder instance that you host like any other uibuilder page.</p>
331
+
332
+ <h3>What it does</h3>
333
+ <ul>
334
+ <li>Create/edit sections and fields visually</li>
335
+ <li>Validate schema structure</li>
336
+ <li>Generate JSON preview</li>
337
+ <li>Send schema to Node-RED (“Generate Form”)</li>
338
+ <li><strong>New Schema</strong> button resets your current schema</li>
339
+ </ul>
340
+
341
+ <h3>How to host it</h3>
342
+ <ol>
343
+ <li>Create a uibuilder instance (example name: <code>formgen-builder</code>)</li>
344
+ <li>Copy the builder files into that instance’s <code>src/</code> folder</li>
345
+ <li>Deploy and open: <code>/uibuilder/formgen-builder/</code></li>
346
+ </ol>
347
+
348
+ <div class="note">
349
+ <strong>Builder dependencies:</strong> the builder’s HTML includes scripts for Vue/Bootstrap/Bootstrap-Vue/jQuery via CDN in the builder page itself.
350
+ </div>
351
+
352
+ <div class="note ok">
353
+ <strong>Where to get the Schema Builder files:</strong>
354
+ After installing <code>node-red-contrib-uibuilder-formgen</code>, copy these files from the package:
355
+ <ul>
356
+ <li><code>examples/formgen-builder/src/index.html</code></li>
357
+ <li><code>examples/formgen-builder/src/index.js</code></li>
358
+ </ul>
359
+ Into your uibuilder instance folder:
360
+ <ul>
361
+ <li><code>&lt;userDir&gt;/uibuilder/formgen-builder/src/</code></li>
362
+ <li>or Projects: <code>&lt;userDir&gt;/projects/&lt;projectName&gt;/uibuilder/formgen-builder/src/</code></li>
363
+ </ul>
364
+ </div>
365
+ </section>
366
+
367
+ <section id="schemas">
368
+ <h2>Schema examples library (industry templates)</h2>
369
+ <p>Example schemas are included with the node package under:</p>
370
+ <pre>node-red-contrib-uibuilder-formgen/examples/schemas/</pre>
371
+
372
+ <h3>Industry folders</h3>
373
+ <ul>
374
+ <li><strong>IT</strong>: <code>examples/schemas/IT/</code></li>
375
+ <li><strong>Maintenance</strong>: <code>examples/schemas/Maintenance/</code></li>
376
+ <li><strong>HR</strong>: <code>examples/schemas/HR/</code></li>
377
+ <li><strong>Banking</strong>: <code>examples/schemas/Banking/</code></li>
378
+ <li><strong>Healthcare</strong>: <code>examples/schemas/Healthcare/</code></li>
379
+ </ul>
380
+
381
+ <h3>How to use a template</h3>
382
+ <ol>
383
+ <li>Pick a schema JSON file from the templates folder</li>
384
+ <li>Paste it into an Inject node as <code>msg.schema</code></li>
385
+ <li>Inject → <code>uibuilder-formgen</code> to generate a portal</li>
386
+ <li>Open the portal URL in a browser</li>
387
+ </ol>
388
+ </section>
389
+
390
+ <section id="schema-reference">
391
+ <h2>Schema reference (field types)</h2>
392
+ <p>Each schema is a JSON object with:</p>
393
+ <ul>
394
+ <li><code>schemaVersion</code></li>
395
+ <li><code>formId</code></li>
396
+ <li><code>title</code></li>
397
+ <li><code>description</code> (optional)</li>
398
+ <li><code>sections[]</code> → each section has <code>fields[]</code></li>
399
+ <li><code>actions[]</code> (optional)</li>
400
+ </ul>
401
+
402
+ <h3>Supported field types</h3>
403
+ <table>
404
+ <thead><tr><th>Type</th><th>Description</th></tr></thead>
405
+ <tbody>
406
+ <tr><td><code>text</code></td><td>Single-line input (supports email/tel/url/password via <code>inputType</code>)</td></tr>
407
+ <tr><td><code>textarea</code></td><td>Multi-line text input (<code>rows</code>)</td></tr>
408
+ <tr><td><code>number</code></td><td>Numeric input (<code>min</code>/<code>max</code>/<code>step</code>)</td></tr>
409
+ <tr><td><code>select</code></td><td>Dropdown with <code>options</code></td></tr>
410
+ <tr><td><code>radio</code></td><td>Radio group with <code>options</code></td></tr>
411
+ <tr><td><code>checkbox</code></td><td>Boolean checkbox</td></tr>
412
+ <tr><td><code>date</code></td><td>Date picker</td></tr>
413
+ <tr><td><code>keyvalue</code></td><td>Key/value entry. Two modes: pairs or delimiter text.</td></tr>
414
+ </tbody>
415
+ </table>
416
+
417
+ <h3>Key/value fields (keyvalue)</h3>
418
+ <p><strong>Pairs mode</strong> stores an array of objects:</p>
419
+ <pre>{
420
+ "id": "labels",
421
+ "type": "keyvalue",
422
+ "label": "Labels",
423
+ "keyvalueMode": "pairs",
424
+ "pairs": [{ "key": "env", "value": "prod" }]
425
+ }</pre>
426
+ <p><strong>Delimiter mode</strong> uses a textarea in the UI, and submits as <strong>array of strings</strong> (one per line):</p>
427
+ <pre>{
428
+ "id": "udfs",
429
+ "type": "keyvalue",
430
+ "label": "UDF lines",
431
+ "keyvalueMode": "delimiter",
432
+ "keyvalueDelimiter": "="
433
+ }</pre>
434
+ </section>
435
+
436
+ <section id="generate">
437
+ <h2>Generating a portal (uibuilder-formgen)</h2>
438
+ <p>You generate portals by sending a schema into the <code>uibuilder-formgen</code> node.</p>
439
+
440
+ <h3>Minimum input</h3>
441
+ <pre>{
442
+ "schema": { ... }
443
+ }</pre>
444
+
445
+ <h3>Recommended input shape</h3>
446
+ <pre>{
447
+ "schema": { ...schema json... },
448
+ "uibuilder": "my-portal-instance",
449
+ "options": {
450
+ "overwrite": true
451
+ }
452
+ }</pre>
453
+ </section>
454
+
455
+ <section id="customize">
456
+ <h2>Customization options (theme, logo, submit, API proxy)</h2>
457
+
458
+ <h3>Theme</h3>
459
+ <ul>
460
+ <li><code>themeMode</code>: <code>auto</code>, <code>light</code>, or <code>dark</code></li>
461
+ </ul>
462
+
463
+ <h3>Logo</h3>
464
+ <ul>
465
+ <li><code>logoPath</code>: absolute path (copied into <code>src/images/</code>) or filename (assumed in <code>src/images/</code>)</li>
466
+ <li><code>logoAlt</code>: alt text</li>
467
+ </ul>
468
+
469
+ <h3>Submit modes</h3>
470
+ <ul>
471
+ <li><strong>uibuilder</strong>: send to Node-RED via uibuilder messages (recommended)</li>
472
+ <li><strong>http</strong>: browser fetch POST (HTTPS only for secure pages; cannot bypass invalid certs)</li>
473
+ </ul>
474
+
475
+ <h3>Server-side API proxy (recommended for TLS control)</h3>
476
+ <p>
477
+ When enabled, Node-RED receives form submissions and calls an external API.
478
+ This is where you can allow self-signed TLS if needed.
479
+ </p>
480
+ <ul>
481
+ <li><code>apiUrl</code> (required to enable)</li>
482
+ <li><code>apiMethod</code>: POST/PUT/PATCH</li>
483
+ <li><code>apiHeadersJson</code>: JSON headers</li>
484
+ <li><code>apiInsecureTls</code>: allow self-signed certs (server-side only)</li>
485
+ <li><code>apiTimeoutMs</code></li>
486
+ </ul>
487
+ </section>
488
+
489
+ <section id="submit-results">
490
+ <h2>Submitting & results page</h2>
491
+ <p>After Submit, the portal shows a Result page with:</p>
492
+ <ul>
493
+ <li><strong>Table view</strong> and <strong>JSON view</strong> toggle</li>
494
+ <li><strong>Download JSON</strong></li>
495
+ </ul>
496
+ <p>Table view formatting:</p>
497
+ <ul>
498
+ <li>Top-level object keys show as rows</li>
499
+ <li>Arrays show as <code>a | b | c</code></li>
500
+ </ul>
501
+ </section>
502
+
503
+ <section id="drafts-exports">
504
+ <h2>Drafts & exports</h2>
505
+ <h3>Drafts</h3>
506
+ <ul>
507
+ <li><strong>Save Draft</strong>: downloads a draft JSON, and uses browser localStorage if available</li>
508
+ <li><strong>Load Draft</strong>: loads from localStorage if available; otherwise loads from a selected draft JSON file</li>
509
+ </ul>
510
+
511
+ <h3>Exports</h3>
512
+ <ul>
513
+ <li>JSON/CSV/HTML exports download directly in the browser</li>
514
+ </ul>
515
+
516
+ <h3>Clear Form</h3>
517
+ <ul>
518
+ <li><strong>Clear Form</strong> resets all fields to defaults (with confirmation)</li>
519
+ </ul>
520
+ </section>
521
+
522
+ <section id="troubleshooting">
523
+ <h2>Troubleshooting</h2>
524
+ <h3>“I don’t see my result page”</h3>
525
+ <ul>
526
+ <li>Ensure the message returned to the portal is shaped as <code>msg.payload.type = "submit:ok"</code> and includes <code>msg.payload.result</code>.</li>
527
+ <li>If you set <code>msg.type</code> instead, the portal will ignore it.</li>
528
+ </ul>
529
+
530
+ <h3>“HTTPS works, but my self-signed API fails”</h3>
531
+ <ul>
532
+ <li>Direct browser submit cannot ignore cert errors.</li>
533
+ <li>Use server-side API proxy and enable insecure TLS there (if required).</li>
534
+ </ul>
535
+
536
+ <h3>uibuilder warning about <code>sioUse.js</code></h3>
537
+ <ul>
538
+ <li>That warning means the uibuilder root path is pointing at a folder with an invalid <code>.config/sioUse.js</code>.</li>
539
+ <li>Fix by correcting the uibuilder root path (Projects vs standard) or disabling the file.</li>
540
+ </ul>
541
+ </section>
542
+
543
+ <section id="security">
544
+ <h2>Security notes</h2>
545
+ <div class="note warn">
546
+ Generated portals are not authenticated by default. Put authentication in front of Node-RED/uibuilder if required.
547
+ </div>
548
+ <ul>
549
+ <li>Do not enable insecure TLS in production unless you fully understand the risk.</li>
550
+ <li>Prefer trusted certificates (reverse proxy, internal CA, or public CA) wherever possible.</li>
551
+ <li>License keys (if used) are stored in the Node-RED credentials store (encrypted at rest when <code>credentialsSecret</code> is configured).</li>
552
+ </ul>
553
+ </section>
554
+
555
+ <div class="footer">
556
+ <div>File: <code>docs/user-guide.html</code></div>
557
+ <div>This guide is designed to be viewed offline and printed.</div>
558
+ </div>
559
+ </main>
560
+ </div>
561
+ </div>
562
+ </body>
563
+ </html>
564
+
565
+