Migrate favorites to navigation menu items (1.17 upgrade) (#17477)

**What this PR does:**
- Migrates existing `Favorite` and `FavoriteFolder` entities to the new
`NavigationMenuItem` structure
- Preserves user-level vs workspace-level ownership
- Preserves folder structure, positions, and relationships
- Handles both view-based favorites (linked to views) and record-based
favorites (linked to records)
- Soft-deletes original favorites and folders after successful migration
- Enables the `IS_NAVIGATION_MENU_ITEM_ENABLED` feature flag
post-migration
- Skips migration if the feature flag is already enabled
- Idempotent: checks for existing navigation menu items to prevent
duplicates

**Migration flow:**
1. Migrate favorite folders first (creates folder mapping)
2. Migrate favorites
3. Soft-delete migrated favorites and folders
4. Enable feature flag

**What's next:**
- After all workspaces are migrated and the navigation menu item feature
is fully rolled out, we can:
- Remove the old `Favorite` and `FavoriteFolder` entities and related
code
- Remove the feature flag check and make navigation menu items the
default
  - Clean up any deprecated favorites-related code paths in the frontend

---------

Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
This commit is contained in:
Abdul Rahman
2026-02-06 19:12:20 +05:30
committed by GitHub
parent 7074d9ce1b
commit f6beb06364
6 changed files with 800 additions and 84 deletions
@@ -21,11 +21,17 @@ export const useNavigationMenuItemsByFolder = () => {
const coreViews = useRecoilValue(coreViewsState);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const { navigationMenuItems } = usePrefetchedNavigationMenuItemsData();
const { navigationMenuItems, workspaceNavigationMenuItems } =
usePrefetchedNavigationMenuItemsData();
const views = coreViews.map(convertCoreViewToView);
const { folders, itemsByFolderId } = navigationMenuItems.reduce<{
const allNavigationMenuItems = [
...navigationMenuItems,
...workspaceNavigationMenuItems,
];
const { folders, itemsByFolderId } = allNavigationMenuItems.reduce<{
folders: Array<{ id: string; name: string }>;
itemsByFolderId: Map<string, NavigationMenuItem[]>;
}>(