mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 13:37:22 +00:00
fix: handle select-all (exclusion) mode in delete command conditional availability
https://sonarly.com/issue/21546?type=bug When users select all records (exclusion mode), the delete option never appears in the command menu because the `noneDefined(selectedRecords, "deletedAt")` check in the conditional availability expression evaluates to `false` on empty arrays, and `selectedRecords` is always `[]` in exclusion mode. Fix: Modified the `conditionalAvailabilityExpression` for the three bulk record commands (delete, restore, destroy) in `standard-command-menu-item.constant.ts` to handle the "select all" (exclusion) mode. **Problem:** When "select all" is used, the context store switches to exclusion mode where `selectedRecords` is always `[]` (empty array). The `noneDefined()` and `everyDefined()` functions in the expression parser return `false` for empty arrays by design. This caused the delete/restore/destroy commands to never appear in the command menu during "select all". **Fix:** Wrapped each `selectedRecords` array check with `(isSelectAll or ...)` so that: - In **selection mode** (individual records selected): the original `noneDefined`/`everyDefined` checks still apply, verifying each record's `deletedAt` status - In **exclusion mode** (select all): the `selectedRecords` check is bypassed since individual records aren't available in the context, and the backend handles filtering during the actual operation The `isSelectAll` boolean is already computed and available in the `commandMenuContextApi` (set in `useCommandMenuContextApi.ts` line 116 as `contextStoreTargetedRecordsRule.mode === 'exclusion'`). Changes: 1. **deleteRecords**: `noneDefined(selectedRecords, "deletedAt")` → `(isSelectAll or noneDefined(selectedRecords, "deletedAt"))` 2. **restoreRecords**: `everyDefined(selectedRecords, "deletedAt")` → `(isSelectAll or everyDefined(selectedRecords, "deletedAt"))` 3. **destroyRecords**: `everyDefined(selectedRecords, "deletedAt")` → `(isSelectAll or everyDefined(selectedRecords, "deletedAt"))` Note: For restore/destroy in select-all mode, the commands will appear even though we can't verify all records have `deletedAt` set. This is acceptable because these commands already require `hasAnySoftDeleteFilterOnView` (restore) or the user being in a deleted records view, and the backend filters appropriately during execution. Existing workspaces will need a `workspace:sync-metadata` run to pick up the updated expressions.
This commit is contained in:
parent
119014f86d
commit
a9d8defccd
1 changed files with 3 additions and 3 deletions
|
|
@ -59,7 +59,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
|||
shortLabel: 'Delete',
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
conditionalAvailabilityExpression:
|
||||
'numberOfSelectedRecords >= 1 and not hasAnySoftDeleteFilterOnView and objectPermissions.canSoftDeleteObjectRecords and noneDefined(selectedRecords, "deletedAt") and numberOfSelectedRecords < 10000',
|
||||
'numberOfSelectedRecords >= 1 and not hasAnySoftDeleteFilterOnView and objectPermissions.canSoftDeleteObjectRecords and (isSelectAll or noneDefined(selectedRecords, "deletedAt")) and numberOfSelectedRecords < 10000',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.DELETE_RECORDS,
|
||||
|
|
@ -74,7 +74,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
|||
shortLabel: 'Restore',
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
conditionalAvailabilityExpression:
|
||||
'numberOfSelectedRecords >= 1 and everyDefined(selectedRecords, "deletedAt") and objectPermissions.canSoftDeleteObjectRecords and (pageType == "RECORD_PAGE" or hasAnySoftDeleteFilterOnView) and numberOfSelectedRecords < 10000',
|
||||
'numberOfSelectedRecords >= 1 and (isSelectAll or everyDefined(selectedRecords, "deletedAt")) and objectPermissions.canSoftDeleteObjectRecords and (pageType == "RECORD_PAGE" or hasAnySoftDeleteFilterOnView) and numberOfSelectedRecords < 10000',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.RESTORE_RECORDS,
|
||||
|
|
@ -89,7 +89,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
|||
shortLabel: 'Destroy',
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
conditionalAvailabilityExpression:
|
||||
'numberOfSelectedRecords >= 1 and objectPermissions.canDestroyObjectRecords and everyDefined(selectedRecords, "deletedAt") and numberOfSelectedRecords < 10000',
|
||||
'numberOfSelectedRecords >= 1 and objectPermissions.canDestroyObjectRecords and (isSelectAll or everyDefined(selectedRecords, "deletedAt")) and numberOfSelectedRecords < 10000',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.DESTROY_RECORDS,
|
||||
|
|
|
|||
Loading…
Reference in a new issue