Repository navigation
feat(workflow-form): render Projection's drag-reorder list in the form, with the drag - #8843
Conversation
Automated Reviewer SuggestionsBased on the
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8843 +/- ##
=========================================
Coverage 92.60% 92.60%
- Complexity 5044 5045 +1
=========================================
Files 1252 1252
Lines 53580 53582 +2
Branches 6672 6672
=========================================
+ Hits 49616 49622 +6
+ Misses 2317 2314 -3
+ Partials 1647 1646 -1
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
7b5aa23 to
60053dc
Compare
|
/request_review: @mengw15 |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The enabled reorder widget lacks the keyboard Move up/down path required by #8761.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Enables Projection column drag-reordering in Form View and fixes repeat-list state synchronization.
Changes:
- Enables
repeat-section-dndin Form View. - Re-keys rows after reordering and makes callbacks optional.
- Prevents widget buttons from submitting forms and expands tests.
| File | Description |
|---|---|
custom-formly-type.ts |
Enables drag-reorder widgets in forms. |
custom-formly-type.spec.ts |
Updates canvas-only type expectations. |
workflow-form.component.ts |
Updates fallback documentation. |
workflow-form.component.spec.ts |
Tests Projection widget selection. |
repeat-dnd.component.ts |
Synchronizes reordered models, fields, controls, and keys. |
repeat-dnd.component.spec.ts |
Expands component behavior coverage. |
repeat-dnd.component.html |
Marks controls as non-submit buttons. |
repeat-dnd.component.formly.spec.ts |
Adds real Formly integration coverage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…m, with the drag An exposed drag-reorder property (Projection's columns, formly type repeat-section-dnd) fell back to a plain repeated list in the Form View: the rows could be edited but not reordered. The fallback assumed the drag had nowhere to attach on a form; the widget carries its own drop list, and the row template comes from the operator schema the form already builds. Take it out of CANVAS_ONLY_FORMLY_TYPES, which now holds the code editor only. The widget renders on the form exactly as on the operator property panel; the panel's reorder callback stays optional, since the card's form persists a drop through valueChanges. Two defects of the widget itself, in reach of the form for the first time: its buttons carried no type, so inside a form (the card's, the panel's) Enter in a row's input clicked the first one and removed a row; and the rows kept their build-time keys after a drop, so a value typed into a moved row landed on the row that used to be there (formly keys rows by position and writes by that key path, re-keying on its own remove(); a drop now re-keys the same way). Closes apache#8761 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
60053dc to
7a4c601
Compare


What changes were proposed in this PR?
Closes #8761. Part of the Form View feature (#8011); from the #8439 refinements (item 2).
An exposed drag-reorder property -- Projection's columns, formly type
repeat-section-dnd-- fell back to a plain repeated list in the Form View (CANVAS_ONLY_FORMLY_TYPES): a reader could edit the rows but not reorder them, which is what the widget is for. The fallback assumed the drag had nowhere to attach on a form; the widget carries its own CDK drop list, and the row template it needs comes from the operator's own schema (the per-instance one, with the upstream columns), which the form already builds.repeat-section-dndleavesCANVAS_ONLY_FORMLY_TYPES; the set now holds the code editor only. On the form the widget renders exactly as on the operator property panel, drag handle and all, and a drop reaches the operator through the card'svalueChangeswrite-back; the panel'sreordercallback stays optional (the widget calls it only when the host provides one), so the same widget serves both hosts without a form-specific branch. Nothing is added to the widget's UI.type="button"--nz-buttonsets no type, so inside a form (the card's, the panel's) a typeless button is the submit button and Enter in a row's input clicked it, removing the first row (the fallback the form used before had typed buttons; the panel has had this since the widget exists); and the rows are re-keyed to their positions after a drop, as formly's ownremove()does -- formly keys rows by position and writes a cell's value into the model by that key path, so a value typed into a moved row landed on the row that used to be there (the same after a drag on the panel, until the operator was re-selected).Any related issues, documentation, discussions?
Closes #8761. Raised by @mengw15 on #8436; filed from #8439. Builds on the sub-field walk from #8438. #8760 (proper) also shrinks
CANVAS_ONLY_FORMLY_TYPES; whichever lands second deletes the then-empty set. Known limitation, not this PR's code: the Form View rebuilds every card on every compilation, including the one a card's own write triggers, so on the form a drop's write redraws the rows about a second later, and a second drop made in the last 150 ms before that redraw is undone. The canvas panel has no such rebuild. Filed as #8844 and fixed in #8845 (the form rebuilds only when the schema, the set of inputs or a value it does not hold changed); this PR is independent of it. Other follow-ups: a card's model is seeded once and never re-seeded from a co-editor's edit of the same property, so a reorder writes the whole array back over such an edit (pre-existing for every array/object property; a reorder is one more trigger); the HuggingFace and codearea widgets also carry typeless buttons.How was this PR tested?
Unit tests (vitest). The widget's spec: a drop reorders the model, the field configs and the form controls and then tells the parent; a section without a reorder callback still reorders; a keyless row's children are re-keyed to the row's new position, as formly's own remove() does; every button carries
type="button"; the existing rendering tests (one row per entry, draggable rows, remove, add, disabled section) still hold. A second spec stands the widget up under real formly (FormlyModule.forRoot, a form, a model): a drop changes the model and the cells and keeps the rows' keys in step with their positions, and a value typed into a moved row lands on that row's entry. The form's spec: Projection'sattributesrenders throughrepeat-section-dnd.custom-formly-type's spec pins the set. Each guard was deletion-checked (the re-keying dropped; the callback called unguarded; the remove button typeless; the type back in the canvas-only set) and turned a named test red. eslint, prettier and the production (AOT) build pass; the full frontend suite passes; every statement, function and branch this PR adds is covered.Checked on a flag-on instance (main-demo; a Python source with four columns feeding a Projection whose
attributesis exposed), with the canvas and the form open side by side: on main the card is a plain list (no handle); with this PR the card shows the drag handles, as the panel does. Dragging the last row to the top: the operator's order follows in the canvas tab's panel within a second and in the saved workflow. An alias typed into the moved row lands on that column, not its neighbour; Enter in an alias input removes no row; a reload shows the same order. A drop made on the canvas panel reaches the form within a second.Video
Before
Screen.Recording.2026-10-04.at.2.04.31.PM.mov
After
Screen.Recording.2026-10-04.at.2.14.49.PM.mov
Was this PR authored or co-authored using generative AI tooling?
Yes. Generated-by: Claude Code (Claude Fable 5.1, Anthropic). Co-authored with Claude, reviewed line by line by the author before submission.
🤖 Generated with Claude Code