Enhance navigation menu item matching logic
- Updated `isLocationMatchingNavigationMenuItem` to include additional parameters for better matching of object record show paths. - Introduced logging for debugging navigation matches, capturing relevant data for analysis. - Added tests to ensure correct behavior for object navigation items on record show pages, distinguishing between view-only and object pins. - Refactored related components to utilize the updated matching logic. This improves the accuracy of navigation item states and enhances debugging capabilities.
This commit is contained in:
+32
@@ -39,4 +39,36 @@ describe('isLocationMatchingNavigationMenuItem', () => {
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should match object or view nav item when on a record show page for that object', () => {
|
||||
expect(
|
||||
isLocationMatchingNavigationMenuItem(
|
||||
'/object/company/rec-1',
|
||||
'/object/company/rec-1',
|
||||
NavigationMenuItemType.OBJECT,
|
||||
'/objects/companies?viewId=idx',
|
||||
'company',
|
||||
),
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
isLocationMatchingNavigationMenuItem(
|
||||
'/object/person/rec-1',
|
||||
'/object/person/rec-1',
|
||||
NavigationMenuItemType.VIEW,
|
||||
'/objects/people?viewId=v1',
|
||||
'person',
|
||||
),
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
isLocationMatchingNavigationMenuItem(
|
||||
'/object/person/rec-1',
|
||||
'/object/person/rec-1',
|
||||
NavigationMenuItemType.OBJECT,
|
||||
'/objects/companies?viewId=idx',
|
||||
'company',
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
+25
-2
@@ -1,15 +1,38 @@
|
||||
import { NavigationMenuItemType } from 'twenty-shared/types';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { AppPath, NavigationMenuItemType } from 'twenty-shared/types';
|
||||
import { getAppPath } from 'twenty-shared/utils';
|
||||
|
||||
export const isLocationMatchingNavigationMenuItem = (
|
||||
currentPath: string,
|
||||
currentViewPath: string,
|
||||
navigationMenuItemType: NavigationMenuItemType,
|
||||
computedLink: string,
|
||||
objectNameSingularForRecordShowMatch: string | null = null,
|
||||
) => {
|
||||
const isViewBasedItem =
|
||||
navigationMenuItemType === NavigationMenuItemType.VIEW ||
|
||||
navigationMenuItemType === NavigationMenuItemType.OBJECT;
|
||||
return isViewBasedItem
|
||||
|
||||
const matchesListDestination = isViewBasedItem
|
||||
? computedLink === currentViewPath
|
||||
: computedLink === currentPath;
|
||||
|
||||
if (matchesListDestination) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
isViewBasedItem &&
|
||||
isNonEmptyString(objectNameSingularForRecordShowMatch)
|
||||
) {
|
||||
const recordShowBase = getAppPath(AppPath.RecordShowPage, {
|
||||
objectNameSingular: objectNameSingularForRecordShowMatch,
|
||||
objectRecordId: '',
|
||||
});
|
||||
|
||||
return currentPath.startsWith(`${recordShowBase}/`);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
+8
@@ -6,6 +6,7 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { type NavigationMenuItem } from '~/generated-metadata/graphql';
|
||||
|
||||
import { openNavigationMenuItemFolderIdsState } from '@/navigation-menu-item/common/states/openNavigationMenuItemFolderIdsState';
|
||||
import { getObjectMetadataForNavigationMenuItem } from '@/navigation-menu-item/display/object/utils/getObjectMetadataForNavigationMenuItem';
|
||||
import { getNavigationMenuItemComputedLink } from '@/navigation-menu-item/display/utils/getNavigationMenuItemComputedLink';
|
||||
import { isLocationMatchingNavigationMenuItem } from '@/navigation-menu-item/common/utils/isLocationMatchingNavigationMenuItem';
|
||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
||||
@@ -85,11 +86,18 @@ export const useNavigationMenuItemFolderOpenState = ({
|
||||
objectMetadataItems,
|
||||
views,
|
||||
);
|
||||
const objectMetadataItem = getObjectMetadataForNavigationMenuItem(
|
||||
item,
|
||||
objectMetadataItems,
|
||||
views,
|
||||
);
|
||||
|
||||
return isLocationMatchingNavigationMenuItem(
|
||||
currentPath,
|
||||
currentViewPath,
|
||||
item.type,
|
||||
computedLink,
|
||||
objectMetadataItem?.nameSingular ?? null,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
+11
-5
@@ -3,6 +3,7 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { Fragment, type ReactNode, useContext } from 'react';
|
||||
|
||||
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
|
||||
import { isLocationMatchingNavigationMenuItem } from '@/navigation-menu-item/common/utils/isLocationMatchingNavigationMenuItem';
|
||||
import { recordIdentifierToObjectRecordIdentifier } from '@/navigation-menu-item/common/utils/recordIdentifierToObjectRecordIdentifier';
|
||||
import { getNavigationMenuItemComputedLink } from '@/navigation-menu-item/display/utils/getNavigationMenuItemComputedLink';
|
||||
import { getNavigationMenuItemLabel } from '@/navigation-menu-item/display/utils/getNavigationMenuItemLabel';
|
||||
@@ -91,17 +92,22 @@ export const NavigationDrawerItemForObjectMetadataItem = ({
|
||||
const computedLink = hasCustomLink ? navigationPath : '';
|
||||
|
||||
const isActive = hasCustomLink
|
||||
? (isView || isObject ? currentPathWithSearch : currentPath) ===
|
||||
computedLink
|
||||
? isLocationMatchingNavigationMenuItem(
|
||||
currentPath,
|
||||
currentPathWithSearch,
|
||||
navigationMenuItem!.type,
|
||||
computedLink,
|
||||
isObject || isView ? objectMetadataItem.nameSingular : null,
|
||||
)
|
||||
: currentPath ===
|
||||
getAppPath(AppPath.RecordIndexPage, {
|
||||
objectNamePlural: objectMetadataItem.namePlural,
|
||||
}) ||
|
||||
currentPath.includes(
|
||||
getAppPath(AppPath.RecordShowPage, {
|
||||
currentPath.startsWith(
|
||||
`${getAppPath(AppPath.RecordShowPage, {
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
objectRecordId: '',
|
||||
}) + '/',
|
||||
})}/`,
|
||||
);
|
||||
|
||||
const handleClick = isLayoutCustomizationModeEnabled
|
||||
|
||||
Reference in New Issue
Block a user