CommandMenuItem overridable entity (#21486)
## Context Second PR of the overridable-entities track (after #21436 for views): command menu items become overridable so that edits on non-owned items are stored as overrides instead of mutating the row, and deletion/deactivation becomes reversible. ## What this does - `CommandMenuItemEntity` now extends `OverridableEntity<CommandMenuItemOverrides>` (adds `isActive` + `overrides`). All editable properties are overridable for now (to discuss). - **Update**: mutations on a command item not owned by the caller (standard items) are written into `overrides`; reads merge them in the DTO. The command palette edit mode (pin, reorder, shortLabel) now preserves standard values, "Reset label to default" gains true post-save semantics. - **Delete**: protected items are deactivated (`isActive = false`) instead of deleted; custom items still hard-delete. - **Object deactivate/enable toggle**: now flips `isActive` on the command item (merged into the main migration call) instead of delete/recreate; a create-if-missing fallback covers legacy deactivated objects. - **Front**: inactive command items are filtered out of the palette selector. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21486?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+31
-14
@@ -138,7 +138,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
isDefined(existingFlatObjectMetadata) &&
|
||||
existingFlatObjectMetadata.isActive;
|
||||
|
||||
const { commandMenuItemsToCreate, commandMenuItemsToDelete } =
|
||||
const { commandMenuItemsToCreate, commandMenuItemsToUpdate } =
|
||||
this.computeCommandMenuItemChangesForActiveToggle({
|
||||
isBeingEnabled,
|
||||
isBeingDisabled,
|
||||
@@ -175,6 +175,11 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: flatViewFieldsToUpdate,
|
||||
},
|
||||
commandMenuItem: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: commandMenuItemsToUpdate,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
@@ -190,18 +195,14 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
);
|
||||
}
|
||||
|
||||
const hasCommandMenuItemChanges =
|
||||
commandMenuItemsToCreate.length > 0 ||
|
||||
commandMenuItemsToDelete.length > 0;
|
||||
|
||||
if (hasCommandMenuItemChanges) {
|
||||
if (commandMenuItemsToCreate.length > 0) {
|
||||
const commandMenuItemMigrationResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
commandMenuItem: {
|
||||
flatEntityToCreate: commandMenuItemsToCreate,
|
||||
flatEntityToDelete: commandMenuItemsToDelete,
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
@@ -919,12 +920,14 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
applicationId: string;
|
||||
}): {
|
||||
commandMenuItemsToCreate: FlatCommandMenuItem[];
|
||||
commandMenuItemsToDelete: FlatCommandMenuItem[];
|
||||
commandMenuItemsToUpdate: FlatCommandMenuItem[];
|
||||
} {
|
||||
if (!isDefined(existingFlatObjectMetadata)) {
|
||||
return { commandMenuItemsToCreate: [], commandMenuItemsToDelete: [] };
|
||||
return { commandMenuItemsToCreate: [], commandMenuItemsToUpdate: [] };
|
||||
}
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
if (isBeingEnabled) {
|
||||
const existingCommandMenuItem =
|
||||
this.findNavigationCommandMenuItemForObject({
|
||||
@@ -943,28 +946,42 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
flatCommandMenuItemMaps,
|
||||
}),
|
||||
],
|
||||
commandMenuItemsToDelete: [],
|
||||
commandMenuItemsToUpdate: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!existingCommandMenuItem.isActive) {
|
||||
return {
|
||||
commandMenuItemsToCreate: [],
|
||||
commandMenuItemsToUpdate: [
|
||||
{ ...existingCommandMenuItem, isActive: true, updatedAt: now },
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (isBeingDisabled) {
|
||||
const commandMenuItemToDelete =
|
||||
const commandMenuItemToDeactivate =
|
||||
this.findNavigationCommandMenuItemForObject({
|
||||
objectUniversalIdentifier:
|
||||
existingFlatObjectMetadata.universalIdentifier,
|
||||
flatCommandMenuItemMaps,
|
||||
});
|
||||
|
||||
if (isDefined(commandMenuItemToDelete)) {
|
||||
if (
|
||||
isDefined(commandMenuItemToDeactivate) &&
|
||||
commandMenuItemToDeactivate.isActive
|
||||
) {
|
||||
return {
|
||||
commandMenuItemsToCreate: [],
|
||||
commandMenuItemsToDelete: [commandMenuItemToDelete],
|
||||
commandMenuItemsToUpdate: [
|
||||
{ ...commandMenuItemToDeactivate, isActive: false, updatedAt: now },
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { commandMenuItemsToCreate: [], commandMenuItemsToDelete: [] };
|
||||
return { commandMenuItemsToCreate: [], commandMenuItemsToUpdate: [] };
|
||||
}
|
||||
|
||||
public async findOneWithinWorkspace(
|
||||
|
||||
Reference in New Issue
Block a user