Extract form-builder-api.js out of form-builder.js - #11
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors the JavaScript form builder by extracting API-related methods (load/save/preview/templates) into a dedicated module and wiring them into the existing BuilderStore-backed state. It also fixes two multi-step-specific regressions (undo snapshot when adding fields to a step, and preview refresh when reordering fields within a step) and adds Vitest coverage for the new/changed behaviors.
Changes:
- Extracts preview/load/save/template methods from
form-builder.jsintoform-builder-api.jsand mixes them intoFormBuilder.prototype. - Fixes multi-step undo by pushing an undo snapshot before adding a field to a step.
- Fixes multi-step reorder preview updates and adds JS unit tests for step reorder, step drop/undo, and API methods.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests_js/form-builder/updateFieldOrderInStep.test.js | Adds coverage ensuring step reorder rewrites step field order from DOM order and refreshes preview. |
| tests_js/form-builder/handleFieldDroppedToStep.test.js | Adds coverage ensuring multi-step palette drop pushes undo and updates fields/step membership. |
| tests_js/form-builder-api/apiMethods.test.js | Adds coverage for extracted API methods (preview debounce, preview rendering/error states, load/save, templates). |
| django_forms_workflows/static/django_forms_workflows/js/form-builder.js | Mixes in apiMethods, proxies fieldIdCounter to the store, and fixes undo/preview update in multi-step flows. |
| django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js | New extracted API module implementing preview/load/save/template behaviors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js:326
template.idis inserted unescaped into adata-template-idattribute. If it contains quotes or other special characters, it can break out of the attribute context and inject HTML. Escape/cast it before interpolation.
<div class="card template-card h-100" style="cursor: pointer;" data-template-id="${template.id}">
django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js:332
template.usage_countis interpolated into HTML without escaping. Even if it is expected to be numeric, escaping/casting avoids HTML injection if the API ever returns unexpected data.
<i class="bi bi-people"></i> Used ${template.usage_count} times
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js:317
- Grouping templates by
category_displayuses a plain object ({}) with an untrusted key. A value like"__proto__"can prototype-pollutegroupedand cause hard-to-debug behavior. UseObject.create(null)(or aMap) and normalize the key to a string before indexing.
const grouped = {};
data.templates.forEach(template => {
if (!grouped[template.category_display]) {
grouped[template.category_display] = [];
}
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
django_forms_workflows/static/django_forms_workflows/js/form-builder-api.js:93
error.messageis interpolated directly intoinnerHTMLhere. If the server (or an upstream error) includes user-controlled text in the message, this can become an XSS vector; escape it before rendering.
<strong>Preview unavailable</strong><br>
${this.fields.length} field(s) configured<br>
<small class="text-muted">${error.message}</small>
Uh oh!
There was an error while loading. Please reload this page.