Skip to content

[Studio UI] Implement batch edit for advanced many-to-many relation columns - #4041

Open
idaiv wants to merge 7 commits into
2026.xfrom
batch-edit-advanced-object-relations
Open

[Studio UI] Implement batch edit for advanced many-to-many relation columns#4041
idaiv wants to merge 7 commits into
2026.xfrom
batch-edit-advanced-object-relations

Conversation

@idaiv

@idaiv idaiv commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Implements batch edit for custom columns in advanced many-to-many relation fields ([Data Object Editor] Advanced Many-to-many relation fields - Enable Batch Edit for Columns #1053)
  • When "Enable Batch Edit for Columns" is on in the class definition, the relation grid shows row selection checkboxes and an "Apply to all" / "Apply to selection" dropdown
  • Dropdown menu: Batch edit (opens modal with column picker + value editors) and Delete (removes selected or all rows)
  • Follows the same UX pattern as the listing grid's batch actions
  • Supports text, number, bool, select, and multiselect column types
  • Applies to both advancedManyToManyRelation and advancedManyToManyObjectRelation
  • Shared components only gain optional passthrough props (off by default) — no behavior change for other relation types

Test plan

  • Open a class definition with an Advanced Many-to-Many Relation field
  • Enable "Enable Batch Edit for Columns" and define custom columns (text, number, select)
  • Open a data object with that field, add several relation items
  • Verify row selection checkboxes appear
  • With no selection: verify "Apply to all" label, Batch edit applies to all rows, Delete clears all
  • Select some rows: verify "Apply to selection" label, "X selected" indicator, Batch edit applies only to selected, Delete removes only selected
  • Verify the same behavior for Advanced Many-to-Many Object Relation fields
  • Verify normal many-to-many relations (without enableBatchEdit) are unaffected

🤖 Generated with Claude Code

…olumns (#1053)

When "Enable Batch Edit for Columns" is turned on in the class
definition of advanced many-to-many relation fields, the relation
grid now supports batch editing of custom columns and batch deletion.

Features:
- Row selection checkboxes in the relation grid (multi-select)
- "Apply to all" / "Apply to selection" dropdown button in toolbar,
  matching the listing grid's UX pattern
- Batch edit: opens a modal with column picker and value editors
  supporting text, number, bool, select, and multiselect column types
- Batch delete: removes selected rows or all rows from the relation
- Selection count indicator with checkbox to deselect all
- Empty/clear button hidden when batch edit is active (replaced by
  the dropdown's Delete action)

Applies to both advancedManyToManyRelation and
advancedManyToManyObjectRelation field types. All shared components
(ManyToManyRelation, ManyToManyRelationGrid, toolbar) only gain
optional passthrough props that default to off — no behavior change
for other relation types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings August 27, 2026 17:40
@idaiv idaiv added the Skip Milestone Check Exempts this PR from the mandatory milestone requirement label Aug 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Verdict: Needs changes. The PR adds batch editing and deletion to both advanced many-to-many relation variants, but row targeting and multi-column updates are currently incorrect.

Changes:

  • Adds selection-based batch actions to both advanced relation types.
  • Adds a modal supporting several custom-column editors.
  • Extends shared relation grid and toolbar components with optional passthrough props.

Review contract:

  • Intent: Implement optional batch editing and deletion for advanced relation columns.
  • Root cause/boundary: Correctly placed in relation components, but duplicated handlers and a non-atomic modal API cause defects.
  • Call sites: Both advanced relation variants are covered; shared behavior remains opt-in.
  • Compatibility: New shared props are optional, so no breaking API change was identified.
  • Tests: No automated coverage was added for selection, filtering, duplicate assignments, or multi-column updates.
  • Docs/changelog: None included; confirm release-note requirements.
  • Key risks: Incorrect row identifiers, overwritten multi-column edits, inherited-field mutation, stale selections, and unconfirmed deletion.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/many-to-many-object-relation/many-to-many-object-relation.tsx Adds optional batch-selection passthrough props.
assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/advanced-many-to-many-relation/batch-edit/batch-edit-modal.tsx Adds the column-picker and value-editor modal.
assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/advanced-many-to-many-relation/batch-edit/batch-edit-action.tsx Adds batch action controls and deletion.
assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/advanced-many-to-many-relation/advanced-many-to-many-relation.tsx Integrates batch behavior for mixed relations.
assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/advanced-many-to-many-object-relation/advanced-many-to-many-object-relation.tsx Integrates batch behavior for object relations.
assets/js/src/core/components/many-to-many-relation/many-to-many-relation.tsx Forwards selection state into the shared grid.
assets/js/src/core/components/many-to-many-relation/grid.tsx Enables controlled multi-row selection.
assets/js/src/core/components/many-to-many-relation/components/toolbar/toolbar.tsx Adds an extension point for toolbar actions.
Suppressed comments (2)

assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/advanced-many-to-many-relation/advanced-many-to-many-relation.tsx:74

  • Selection is controlled but never cleared or pruned when props.value changes. If a selected row is removed with its row action or the relation is reordered, the toolbar retains stale selection keys and subsequent batch actions can no-op or target a different row. Reset selection when the source value changes.
  const [selectedRows, setSelectedRows] = useState<RowSelectionState>({})

assets/js/src/core/modules/element/dynamic-types/definitions/objects/data-related/components/advanced-many-to-many-object-relation/advanced-many-to-many-object-relation.tsx:68

  • Selection is controlled but never cleared or pruned when props.value changes. Removing or reordering a selected relation leaves stale keys in the toolbar, so later batch operations can no-op or affect a different row. Reset selection when the source value changes.
  const [selectedRows, setSelectedRows] = useState<RowSelectionState>({})

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread assets/js/src/core/components/many-to-many-relation/grid.tsx
idaiv and others added 4 commits August 27, 2026 18:19
Fixes all issues flagged in PR #4041 review:

HIGH:
- Row selection keyed by element ID, not array index — shared hook
  resolves selected element IDs to value array positions via Set lookup
- Multi-column batch apply only kept last column — onApply now receives
  all entries as a single array and applies them in one map pass
- Delete without confirmation — added confirm dialog matching the
  existing relation clear UX

MEDIUM:
- Inherited fields now disable batch edit (added inherited check)
- Text columns without explicit type no longer filtered out
- Boolean entries initialize to false instead of undefined

LOW:
- Remove button in batch edit modal has accessible title
- Extracted shared useBatchEditActions hook to deduplicate logic
  between both advanced relation variants

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… column picker panel

Replaces the simple Modal+Select approach with the same UX pattern
used by the listing grid's batch edit:

- WindowModal instead of regular Modal (draggable, no mask)
- Left panel with ColumnPicker tree for "Fields to add" (with
  header, collapse control, and search)
- "+ Add a column" toggle button in footer to show/hide the panel
- ModalTitle component for proper header styling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rows were keyed by element id. With allowMultipleAssignments one element can
occupy several rows, so the id is not unique: the grid emitted duplicate row
ids, and resolving a selection by id matched every occurrence rather than the
row the user ticked — batch edit and delete then hit the wrong rows.

Rows are now keyed by originalIndex, the position in the unfiltered value that
use-value stamps before search and column filters run, so a key identifies one
occurrence and survives filtering. The relation grid's `value` prop is typed as
the display value it has always been handed, which is what makes originalIndex
available. Selection keys are therefore already positions, so the hook no
longer maps ids and instead discards keys that fall outside the current value.

Adds use-batch-edit-actions.test.ts covering the cases the review called out:
editing and deleting the right occurrence of a duplicated element, out-of-range
keys, multi-column updates landing in a single onChange, multiselect joining,
apply-to-all, and selection being cleared so it cannot go stale.

Also resolves the Sonar finding in the batch edit modal by using a default
parameter instead of reassigning the type inside getDefaultValue.

Refs #1053

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@idaiv
idaiv requested a review from ValeriaMaltseva August 28, 2026 09:04
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Skip Milestone Check Exempts this PR from the mandatory milestone requirement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants