Overview
Add batch selection and deletion to the root-page tables for Experiments, Feature Flags, and Segments, allowing users to delete multiple items without opening each item individually.
This initial release supports Delete only. Additional batch actions, such as Archive where supported and Export, may be added later.
The behavior below uses Experiments as the example. Apply the same interaction pattern to Feature Flags and ordinary public Segments, using the appropriate entity names and deletion rules. The separate Global Segments / Global Excludes table is not included.
Design References
Figma
https://www.figma.com/design/dq46R3ukbLauwWCSQg2TkR/UpGrade-UI-Latest-21--Batch-Actions-?node-id=42201-25177
No selection, with a checkbox revealed on hover Updated: Checkboxes remain visible without hover.
Partial selection and Delete menu
All loaded items selected
Batch delete confirmation dialog
Expected Behavior
1. Row selection and checkbox visibility
- Show selection checkboxes only to users with delete permission for that entity:
- Admin and Creator: Experiments, Feature Flags, and Segments.
- User Manager: Segments only.
- Reader: none.
- For users with delete permission, add a checkbox to the left of each item's name and a selection checkbox in the table header.
- When nothing is selected:
Show each row's checkbox when that row is hovered.
Show the header checkbox when the header is hovered.
- Keep all row checkboxes and the header checkbox visible without hover.
- If the table is empty, keep the header checkbox hidden, including on hover.
- When at least one item is selected, keep all row checkboxes and the header checkbox visible, including when the current search displays no matching items.
Reserve checkbox space for users who can select items so hover does not shift the content. For other users, omit the checkboxes without reserving their space.
- Reserve checkbox space for users who can select items. For other users, omit the checkboxes without reserving their space.
- Make selection controls accessible through keyboard focus and usable on devices without hover.
- Clicking a row checkbox toggles that item's selection without opening the item or triggering sorting. Existing name links continue to work normally.
- Users with delete permission can select items whose state prevents deletion. Item-state restrictions affect action availability, not selection.
2. Column heading and selection count
- With no selection, the first column heading remains
Name.
- With one or more items selected, replace the label with
N Selected.
- The count represents the total selection, including selected items hidden by the current search or filters.
- Clicking the heading continues to sort by Name. Preserve the sort indicator and make this behavior identifiable when the label reads
N Selected.
- Clicking the header checkbox must not trigger sorting.
When the selection becomes empty, restore the Name label and the default checkbox visibility.
- When the selection becomes empty, restore the
Name label. Checkboxes remain visible unless the table is empty, in which case hide the header checkbox.
3. Header checkbox behavior
The table currently loads items incrementally as the user scrolls. Select-all applies to all items loaded for the current search and filters at the time of the click, including rows outside the visible viewport.
The header checkbox reflects selection as follows:
| State |
Appearance |
Clicking the checkbox |
| Nothing is selected |
Unchecked |
Select all currently loaded items for the current search and filters |
| At least one item is selected, but the currently loaded list is not fully selected |
Indeterminate (−) |
Clear all selections, including hidden items |
| Every item in the nonempty, currently loaded list is selected |
Checked |
Clear all selections, including hidden items |
- Derive the header state from the current selection and loaded list, regardless of how items were selected.
- Manually selecting every loaded item changes the header to checked.
- Deselecting an item from a fully selected list changes the header to indeterminate.
- Loading additional items does not select them automatically. If the header was checked, it changes to indeterminate when new, unselected items are added.
- If selected items exist but none are displayed under the current search or filters, keep the header indeterminate so the user can still clear all selections.
- Use these header checkbox tooltips:
- Nothing selected:
Select all loaded items
- Any selection present:
Clear all selections
The header checkbox provides the way to clear the entire selection; no separate Clear selection control is needed.
4. Sorting, searching, filtering, and scrolling
Sorting, searching, filtering, and loading more items affect the displayed list without changing existing selections.
Leaving a root page clears its selection. Returning through browser Back or the side navigation starts with no selection. Refreshing the browser also clears selections. Leaving the page does not cancel an already submitted deletion request.
For example:
- Select three experiments.
- Enter a search that displays only one of those experiments.
- The heading still reads
3 Selected.
- Choosing Delete targets all three selected experiments.
For incremental loading:
- Select all 20 currently loaded experiments.
- The heading reads
20 Selected, and the header checkbox is checked.
- Scroll to load 20 additional experiments.
- The additional experiments remain unselected.
- The heading still reads
20 Selected, and the header checkbox becomes indeterminate.
The selection count, header checkbox, and actions menu remain available even when the current search or filters display no matching items.
5. Actions menu and deletion eligibility
- With nothing selected, preserve the existing default overflow menu and its permission-based visibility.
- With one or more items selected, show Delete as the only batch action.
- Enable batch Delete only when every selected item satisfies the UI deletion rules, including retained data for items hidden by search or filters:
- Experiments: allow Draft, Inactive, Completed, and Archived; block Preview, Scheduled, Running, and Paused.
- Feature Flags: block Enabled flags.
- Ordinary public Segments: block Used segments.
- Apply the same experiment state rule to the details page, hiding its Delete menu item in blocked states. Preserve the existing rules for other menu actions.
- Draft remains a legacy state; this change does not introduce new Draft UI support.
- When any selected item's state prevents deletion, disable the root-page menu button and use the existing accessible tooltip to explain the restriction.
- While deletion is pending, keep the menu button disabled without a tooltip.
- Do not add polling or eligibility requests when switching browser tabs, returning focus to the app, or opening confirmation.
- Show restrictions through the existing menu-button tooltip, without an additional message or refresh button above the table.
- Restore the default menu and its existing permission rules when the selection becomes empty.
Use plural menu labels even when only one item is selected:
Delete Experiments
Delete Feature Flags
Delete Segments
These state and usage restrictions are UI-only and use cached data. If another user changes an item's state after it was loaded or confirmation opened, the backend still attempts deletion through the existing workflow. Neither single-item nor batch deletion adds server-side state, usage, or segment-type restrictions.
6. Delete confirmation
- Reuse the existing shared text-validation confirmation modal with
ModalSize.SMALL.
- Keep the title plural:
Delete Experiments, Delete Feature Flags, or Delete Segments.
- Show the total selection count, including hidden selections, using singular or plural wording in the message.
Are you sure you want to delete 1 experiment?
Are you sure you want to delete 3 experiments?
- Require the user to type
delete to enable the red Delete button, with autocomplete disabled.
- Cancel and the close button leave items and selections unchanged. Escape and backdrop clicks do not dismiss the dialog, matching existing confirmation dialogs.
- Confirming closes the dialog and submits the selection represented by it.
- Prevent duplicate submissions and selection changes while the request is pending.
- Use the existing table loading behavior and snackbar notifications; do not add progress or result screens inside the modal.
7. Completion and errors
- Remove items confirmed deleted or already absent from the table and selection.
- Retain the selection of remaining items while the user stays on the root page.
- Restore the default header and the default menu's existing permission rules when the selection becomes empty.
- Preserve the current search, filters, and sorting.
- Report results through the existing snackbar components:
- Success: all requested items were deleted or already absent.
- Warning: some deletion or prior absence is confirmed, but errors or incomplete work remain.
- Error: no deletion or prior absence is confirmed.
- Include applicable result counts without listing zero counts.
- Missing items do not stop deletion of subsequent items.
- Example: three feature flags are selected, and another user deletes one before submission. Delete the remaining two and report that one was already absent.
- An execution error, such as a database or external-service failure, stops processing the remaining items. Report those items as not attempted, separately from items that failed.
- Do not report an uncertain outcome as a successful deletion or automatically retry deletion. Retain uncertain items in the selection and report the uncertainty through the existing result snackbar. Refresh the list normally after a successful HTTP response, without a separate eligibility request.
- Network and HTTP request failures use the existing error snackbar, including
Network call failed. See console for details. for network errors. Preserve the current rows and selection and release the pending controls.
- Do not add a duplicate warning snackbar, recovery banner, or reload button above the table for HTTP failures.
Implementation Considerations
Reuse shared selection behavior, existing overflow controls, the shared text-validation confirmation modal, and existing snackbar/error handling across the three root pages.
Add POST /{experiments,flags,segments}/batch-delete under the existing API prefix. Each endpoint accepts a nonempty array of unique UUIDs and returns an outcome for each requested ID. Use the same authentication behavior as the existing single-item endpoints. Role-based delete permissions remain enforced in the UI; neither API adds backend role checks.
Process items sequentially in separate transactions so that a failed item does not roll back earlier successful deletions. Continue past missing targets; stop after execution failures. Preserve target locking, owned-list cleanup, transactional audit writes, cache/recompute handling, and Mooclet orchestration. Use existing database timeout settings without a batch-specific admission deadline or lock-wait override.
Keep state and usage restrictions in the UI, based on cached item data. Do not add backend eligibility preflight, eligibility endpoints, or state/usage/segment-type deletion guards.
Preserve existing single-item endpoint permissions and response formats. Internal private-list deletion continues through its existing endpoints.
Backend role and state/usage enforcement for both single-item and batch deletion is deferred to a separate issue/PR, coordinated with the load-testing setup and existing API callers.
Overview
Add batch selection and deletion to the root-page tables for Experiments, Feature Flags, and Segments, allowing users to delete multiple items without opening each item individually.
This initial release supports Delete only. Additional batch actions, such as Archive where supported and Export, may be added later.
The behavior below uses Experiments as the example. Apply the same interaction pattern to Feature Flags and ordinary public Segments, using the appropriate entity names and deletion rules. The separate Global Segments / Global Excludes table is not included.
Design References
Figma
https://www.figma.com/design/dq46R3ukbLauwWCSQg2TkR/UpGrade-UI-Latest-21--Batch-Actions-?node-id=42201-25177
No selection,
with a checkbox revealed on hoverUpdated: Checkboxes remain visible without hover.Partial selection and Delete menu
All loaded items selected
Batch delete confirmation dialog
Expected Behavior
1. Row selection and checkbox visibility
Show each row's checkbox when that row is hovered.Show the header checkbox when the header is hovered.Reserve checkbox space for users who can select items so hover does not shift the content. For other users, omit the checkboxes without reserving their space.2. Column heading and selection count
Name.N Selected.N Selected.When the selection becomes empty, restore theNamelabel and the default checkbox visibility.Namelabel. Checkboxes remain visible unless the table is empty, in which case hide the header checkbox.3. Header checkbox behavior
The table currently loads items incrementally as the user scrolls. Select-all applies to all items loaded for the current search and filters at the time of the click, including rows outside the visible viewport.
The header checkbox reflects selection as follows:
−)Select all loaded itemsClear all selectionsThe header checkbox provides the way to clear the entire selection; no separate Clear selection control is needed.
4. Sorting, searching, filtering, and scrolling
Sorting, searching, filtering, and loading more items affect the displayed list without changing existing selections.
Leaving a root page clears its selection. Returning through browser Back or the side navigation starts with no selection. Refreshing the browser also clears selections. Leaving the page does not cancel an already submitted deletion request.
For example:
3 Selected.For incremental loading:
20 Selected, and the header checkbox is checked.20 Selected, and the header checkbox becomes indeterminate.The selection count, header checkbox, and actions menu remain available even when the current search or filters display no matching items.
5. Actions menu and deletion eligibility
Use plural menu labels even when only one item is selected:
Delete ExperimentsDelete Feature FlagsDelete SegmentsThese state and usage restrictions are UI-only and use cached data. If another user changes an item's state after it was loaded or confirmation opened, the backend still attempts deletion through the existing workflow. Neither single-item nor batch deletion adds server-side state, usage, or segment-type restrictions.
6. Delete confirmation
ModalSize.SMALL.Delete Experiments,Delete Feature Flags, orDelete Segments.Are you sure you want to delete 1 experiment?Are you sure you want to delete 3 experiments?deleteto enable the red Delete button, with autocomplete disabled.7. Completion and errors
Network call failed. See console for details.for network errors. Preserve the current rows and selection and release the pending controls.Implementation Considerations
Reuse shared selection behavior, existing overflow controls, the shared text-validation confirmation modal, and existing snackbar/error handling across the three root pages.
Add
POST /{experiments,flags,segments}/batch-deleteunder the existing API prefix. Each endpoint accepts a nonempty array of unique UUIDs and returns an outcome for each requested ID. Use the same authentication behavior as the existing single-item endpoints. Role-based delete permissions remain enforced in the UI; neither API adds backend role checks.Process items sequentially in separate transactions so that a failed item does not roll back earlier successful deletions. Continue past missing targets; stop after execution failures. Preserve target locking, owned-list cleanup, transactional audit writes, cache/recompute handling, and Mooclet orchestration. Use existing database timeout settings without a batch-specific admission deadline or lock-wait override.
Keep state and usage restrictions in the UI, based on cached item data. Do not add backend eligibility preflight, eligibility endpoints, or state/usage/segment-type deletion guards.
Preserve existing single-item endpoint permissions and response formats. Internal private-list deletion continues through its existing endpoints.
Backend role and state/usage enforcement for both single-item and batch deletion is deferred to a separate issue/PR, coordinated with the load-testing setup and existing API callers.