[Batch Delete] Use the batch delete-info endpoint in the grid delete confirmation - #3961
Conversation
…confirmation
The grid batch-delete confirm dialog fired one delete-info request per
selected row (N parallel requests) to decide between "Delete" and
"Delete permanently", and only opened once all of them resolved - large
selections hit browser connection limits and froze the UI without any
loading indicator.
The dialog now opens immediately with the OK button in loading state and
fetches the aggregated info with a single
POST /elements/{elementType}/batch-delete-info request
(pimcore/studio-backend-bundle#1954, released in 2026.2.1):
- canUseRecycleBin decides the OK label as before
- the aggregated hasDependencies drives the dependency warning: the
concrete "have child objects or other dependencies" line only shows
when dependencies actually exist; if the request fails, the previous
generic warning and the "Delete" label are kept as a safe fallback
- the batch-info call is a read-only pre-check, so the enhanced slice
drops its "Elements" cache invalidation to avoid spurious refetches
- OpenAPI snapshot: only the new batch-delete-info path was spliced in
(taken from a freshly generated spec); SDK regenerated via
build-api-client
Refs #3666
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates batch-delete confirmation to use the backend’s aggregated delete-info endpoint, avoiding per-row requests.
Changes:
- Opens the dialog immediately while one batch pre-check runs.
- Updates permanence and dependency warnings from the response.
- Adds generated API support and localized warning text.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
translations/studio.sv.yaml |
Adds Swedish warning text. |
translations/studio.no.yaml |
Adds Norwegian warning text. |
translations/studio.it.yaml |
Adds Italian warning text. |
translations/studio.fr.yaml |
Adds French warning text. |
translations/studio.es.yaml |
Adds Spanish warning text. |
translations/studio.en.yaml |
Adds English warning text. |
translations/studio.de.yaml |
Adds German warning text. |
assets/js/src/core/modules/element/element-api-slice.gen.ts |
Generates the batch delete-info endpoint. |
assets/js/src/core/modules/element/element-api-slice-enhanced.ts |
Prevents read-only pre-check cache invalidation. |
assets/js/src/core/modules/element/actions/delete/use-batch-delete-confirm.tsx |
Implements asynchronous modal loading and aggregated warnings. |
| } catch { | ||
| return { isPermanent: false, hasDependencies: null } |
65685ea to
df28622
Compare
…handler The batch pre-check swallowed request failures silently (inherited from the old per-id code). API-shaped failures now go through trackError(new ApiError()) like the other element hooks; the safe fallback (Delete label + generic dependency warning) is unchanged. Addresses review feedback on #3961. Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🌐 Translations synced automaticallyThe key changes below were generated for all target languages, passed the Added (1):
Removed (1):
🧹 Pre-existing translation errors (backlog partly cleared)18 validation error(s) predating this PR were present at the merge base. This run also fixed 6 of them; 12 still remain. The remainder is not blocking — later runs keep chipping at it. |
antd's hook modal (App.useApp().modal) ignores the function form of ConfigUpdate - update() merges the argument with Object.assign, so a function updater copies no properties and the modal silently never leaves its loading state. Use the plain-object form, which antd shallow-merges into the current config. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…k fails Replace unwrap() with the plain initiate-result pattern used elsewhere (await the request, check the error member). On a failed pre-check the dialog no longer settles into a possibly under-warning "Delete" state: the API error is raised via the central error handler and the dialog closes. This removes the unknown-state fallback, so the now-unused generic warning key element.delete.batch.dependencies-warning is dropped from all languages. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… preflight The batch pre-check passed a possibly-undefined RTK error into ApiError (TS2345 in check-types); guard it like use-open-saved-search does. The single-folder delete flow had the same preflight bug class the batch flow just fixed, but worse: elementGetDeleteInfo failures were entirely unhandled, silently falling back to the harmless recoverable-delete wording even when deletion would be permanent, and the query subscription was never released. Failures now raise the API error and abort instead of opening a possibly under-warning dialog; the two almost-identical modal configs are merged. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the open-then-update() flow with fetch-first: the batch delete-info request runs while the triggering dropdown item shows a loading state (same pattern as locate-in-tree), and the confirm dialog opens once, fully formed. This drops the placeholder content state, the destroy-on-error modal flash and the antd ConfigUpdate workaround, and matches the folder-delete flow. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…item MenuItemType.isLoading is declared but never rendered by any menu/dropdown component (the existing useDelete and locate-in-tree usages are equally inert), and the menu closes on click anyway. Remove the no-op plumbing - the flow is plain fetch-first like the folder delete. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…handler The batch pre-check swallowed request failures silently (inherited from the old per-id code). API-shaped failures now go through trackError(new ApiError()) like the other element hooks; the safe fallback (Delete label + generic dependency warning) is unchanged. Addresses review feedback on #3961. Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
antd's hook modal (App.useApp().modal) ignores the function form of ConfigUpdate - update() merges the argument with Object.assign, so a function updater copies no properties and the modal silently never leaves its loading state. Use the plain-object form, which antd shallow-merges into the current config. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…k fails Replace unwrap() with the plain initiate-result pattern used elsewhere (await the request, check the error member). On a failed pre-check the dialog no longer settles into a possibly under-warning "Delete" state: the API error is raised via the central error handler and the dialog closes. This removes the unknown-state fallback, so the now-unused generic warning key element.delete.batch.dependencies-warning is dropped from all languages. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… preflight The batch pre-check passed a possibly-undefined RTK error into ApiError (TS2345 in check-types); guard it like use-open-saved-search does. The single-folder delete flow had the same preflight bug class the batch flow just fixed, but worse: elementGetDeleteInfo failures were entirely unhandled, silently falling back to the harmless recoverable-delete wording even when deletion would be permanent, and the query subscription was never released. Failures now raise the API error and abort instead of opening a possibly under-warning dialog; the two almost-identical modal configs are merged. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the open-then-update() flow with fetch-first: the batch delete-info request runs while the triggering dropdown item shows a loading state (same pattern as locate-in-tree), and the confirm dialog opens once, fully formed. This drops the placeholder content state, the destroy-on-error modal flash and the antd ConfigUpdate workaround, and matches the folder-delete flow. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…item MenuItemType.isLoading is declared but never rendered by any menu/dropdown component (the existing useDelete and locate-in-tree usages are equally inert), and the menu closes on click anyway. Remove the no-op plumbing - the flow is plain fetch-first like the folder delete. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
888ebaf to
959249b
Compare
"These items have dependencies, delete anyway?" replaces the longer child-objects wording, in English and all six languages. Refs #3961 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Joining the permanence note and the dependencies question produced
clunky text ("These items ... These items ...") and fragment
composition does not translate cleanly. The warning is now one full
sentence per state: permanent + dependencies, permanent only (which
also gains the previously missing "Delete anyway?"), and dependencies
only. The element.delete.batch.note key is replaced by
note.permanent and note.permanent-dependencies in all languages.
Refs #3961
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Every warning state starts with "Please note:" and is a plain
statement; the trailing "Delete anyway?" is gone - the modal's own
question line already asks for confirmation.
- The permanent-only state reuses the element.delete.batch.note key
("... will be deleted permanently and can not be restored.").
- All three warnings are pluralized via i18next count suffixes
(_one/_other), like the existing question line - single selections
read "This item ...".
- In the permanent-with-dependencies state the restore sentence sits
on its own line (\n in the translation, white-space: pre-line on
the warning style).
Refs #3961
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|



Changes in this pull request
Resolves #3666
The grid batch-delete confirm dialog fired one
delete-inforequest per selected row (N parallel requests) to decide between "Delete" and "Delete permanently", and only opened once all of them resolved — large selections hit browser connection limits and froze the UI without any loading indicator.It now uses the aggregated endpoint from pimcore/studio-backend-bundle#1954 (released in 2026.2.1, already covered by the composer constraint
^2026.2.1):POST /elements/{elementType}/batch-delete-inforequest runs first; the confirm dialog then opens once, fully formed — the same fetch-first shape as the folder delete flow, no post-openupdate()patching.canUseRecycleBindecides the OK label as before.hasDependenciesnow drives the dependency warning: a concrete "These items have child objects or other dependencies" line shows only when dependencies actually exist, and no line when there are none. If the pre-check request fails, the API error is raised via the central error handler and the dialog closes (no under-warning "Delete" state); the now-unused genericelement.delete.batch.dependencies-warningkey was removed from all languages.Elementscache invalidation (same pattern aselementLock/elementUnlock); the request handle isreset()afterwards, which also fixes the previously never-unsubscribed per-id cache entries.batch-delete-infopath was spliced in (taken from a freshly generated spec); SDK regenerated viabuild-api-client.element.delete.batch.dependencies-warning.confirmed, translated for en/de/fr/it/es/sv/no.Additional info
build-appare green.🤖 Generated with Claude Code