fix: hide objects with no addable views in sidebar view picker (#18993)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Abdul Rahman
2026-03-26 18:43:49 +05:30
committed by GitHub
parent 160a80cbcb
commit 36c7c99e34
6 changed files with 24 additions and 34 deletions
@@ -17,7 +17,6 @@ import { useGetStandardObjectIcon } from '@/object-metadata/hooks/useGetStandard
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { viewsSelector } from '@/views/states/selectors/viewsSelector';
import { ViewKey } from '@/views/types/ViewKey';
export const NavigationMenuItemIcon = ({
navigationMenuItem,
@@ -43,11 +42,6 @@ export const NavigationMenuItemIcon = ({
const view = isDefined(navigationMenuItem.viewId)
? views.find((view) => view.id === navigationMenuItem.viewId)
: undefined;
const isViewWithOverlay =
navigationMenuItem.type === NavigationMenuItemType.VIEW &&
isDefined(view) &&
view.key !== ViewKey.INDEX;
const objectMetadataItem = objectMetadataItems.find(
(item) => item.nameSingular === objectNameSingular,
);
@@ -57,7 +51,10 @@ export const NavigationMenuItemIcon = ({
: StandardIcon;
const canShowViewOverlay =
isViewWithOverlay && isDefined(objectIconForView) && isDefined(view?.icon);
navigationMenuItem.type === NavigationMenuItemType.VIEW &&
isDefined(view) &&
isDefined(objectIconForView) &&
isDefined(view?.icon);
if (canShowViewOverlay) {
return (
@@ -17,7 +17,6 @@ import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/compo
import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { viewsSelector } from '@/views/states/selectors/viewsSelector';
import { ViewKey } from '@/views/types/ViewKey';
type NavigationMenuItemFolderSubItemProps = {
navigationMenuItem: NavigationMenuItem;
@@ -64,11 +63,6 @@ export const NavigationMenuItemFolderSubItem = ({
views,
);
const view = isDefined(navigationMenuItem.viewId)
? views.find((viewItem) => viewItem.id === navigationMenuItem.viewId)
: undefined;
const isIndexView = view?.key === ViewKey.INDEX;
const objectMetadataItem =
navigationMenuItem.type === NavigationMenuItemType.OBJECT ||
navigationMenuItem.type === NavigationMenuItemType.VIEW ||
@@ -98,7 +92,7 @@ export const NavigationMenuItemFolderSubItem = ({
return (
<NavigationDrawerSubItem
secondaryLabel={
isIndexView
navigationMenuItem.type !== NavigationMenuItemType.VIEW
? undefined
: getObjectNavigationMenuItemSecondaryLabel({
objectMetadataItems,
@@ -12,7 +12,6 @@ import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/Enriche
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { viewsSelector } from '@/views/states/selectors/viewsSelector';
import { ViewKey } from '@/views/types/ViewKey';
import { useLocation } from 'react-router-dom';
import {
AppPath,
@@ -102,10 +101,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({
const view = isDefined(navigationMenuItem?.viewId)
? views.find((view) => view.id === navigationMenuItem!.viewId)
: undefined;
const viewKey = view?.key ?? null;
const isViewWithCustomName =
isView && viewKey !== ViewKey.INDEX && isDefined(view);
const isViewWithResolvedView = isView && isDefined(view);
const itemLabel = isDefined(navigationMenuItem)
? getNavigationMenuItemLabel(navigationMenuItem, objectMetadataItems, views)
@@ -113,7 +109,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({
const label = isRecord
? itemLabel
: isViewWithCustomName
: isViewWithResolvedView
? itemLabel
: objectMetadataItem.labelPlural;
@@ -138,7 +134,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({
placeholder={itemLabel}
/>
)
: isViewWithCustomName && isDefined(view?.icon)
: isViewWithResolvedView && isDefined(view?.icon)
? () => (
<ObjectIconWithViewOverlay
ObjectIcon={getIcon(objectMetadataItem.icon)}
@@ -151,7 +147,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({
const iconThemeColor = !isRecord ? objectNavItemColor : undefined;
const secondaryLabel =
isRecord || isViewWithCustomName
isRecord || isViewWithResolvedView
? objectMetadataItem.labelSingular
: undefined;
@@ -1,16 +1,15 @@
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/edit/hooks/useDraftNavigationMenuItems';
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/edit/hooks/useNavigationMenuObjectMetadataFromDraft';
import { SidePanelNewSidebarItemViewObjectPickerSubView } from '@/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemViewObjectPickerSubView';
import { getAvailableObjectMetadataForNewSidebarItem } from '@/navigation-menu-item/edit/side-panel/utils/getAvailableObjectMetadataForNewSidebarItem';
import { isViewDisplayableInNavigationMenu } from '@/navigation-menu-item/edit/side-panel/utils/isViewDisplayableInNavigationMenu';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
import { SidePanelNewSidebarItemViewObjectPickerSubView } from '@/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemViewObjectPickerSubView';
import { getAvailableObjectMetadataForNewSidebarItem } from '@/navigation-menu-item/edit/side-panel/utils/getAvailableObjectMetadataForNewSidebarItem';
import { selectedObjectMetadataIdForViewFlowState } from '@/side-panel/states/selectedObjectMetadataIdForViewFlowState';
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
import { ViewKey } from '@/views/types/ViewKey';
import { ViewType } from '@/views/types/ViewType';
import { useState } from 'react';
export const SidePanelNewSidebarItemViewObjectPickerSubPage = () => {
@@ -24,14 +23,15 @@ export const SidePanelNewSidebarItemViewObjectPickerSubPage = () => {
const { objectMetadataItems } = useObjectMetadataItems();
const { activeNonSystemObjectMetadataItems } =
useFilteredObjectMetadataItems();
const { views, objectMetadataIdsWithIndexView } =
const { views, objectMetadataIdsWithIndexView, viewIdsInWorkspace } =
useNavigationMenuObjectMetadataFromDraft(currentDraft);
const objectMetadataIdsWithDisplayableViews = new Set(
views
.filter(
(view) =>
view.key !== ViewKey.INDEX && view.type !== ViewType.FIELDS_WIDGET,
isViewDisplayableInNavigationMenu(view) &&
!viewIdsInWorkspace.has(view.id),
)
.map((view) => view.objectMetadataId),
);
@@ -4,6 +4,7 @@ import { useAddViewToNavigationMenuDraft } from '@/navigation-menu-item/edit/vie
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/edit/hooks/useDraftNavigationMenuItems';
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/edit/hooks/useNavigationMenuObjectMetadataFromDraft';
import { useOpenNavigationMenuItemInSidePanel } from '@/navigation-menu-item/edit/hooks/useOpenNavigationMenuItemInSidePanel';
import { isViewDisplayableInNavigationMenu } from '@/navigation-menu-item/edit/side-panel/utils/isViewDisplayableInNavigationMenu';
import { pendingInsertionNavigationMenuItemState } from '@/navigation-menu-item/common/states/pendingInsertionNavigationMenuItemState';
import { getObjectColorWithFallback } from '@/object-metadata/utils/getObjectColorWithFallback';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
@@ -16,13 +17,10 @@ import { useSidePanelFilteredPickerItems } from '@/side-panel/hooks/useSidePanel
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { type View } from '@/views/types/View';
import { ViewKey } from '@/views/types/ViewKey';
import { ViewType } from '@/views/types/ViewType';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { ViewVisibility } from '~/generated-metadata/graphql';
type SidePanelNewSidebarItemViewPickerSubViewProps = {
selectedObjectMetadataIdForView: string;
@@ -49,9 +47,7 @@ export const SidePanelNewSidebarItemViewPickerSubView = ({
.filter(
(view) =>
view.objectMetadataId === selectedObjectMetadataIdForView &&
view.key !== ViewKey.INDEX &&
view.type !== ViewType.FIELDS_WIDGET &&
view.visibility === ViewVisibility.WORKSPACE,
isViewDisplayableInNavigationMenu(view),
)
.sort((a, b) => a.position - b.position);
@@ -0,0 +1,7 @@
import { type View } from '@/views/types/View';
import { ViewType } from '@/views/types/ViewType';
import { ViewVisibility } from '~/generated-metadata/graphql';
export const isViewDisplayableInNavigationMenu = (view: View): boolean =>
view.type !== ViewType.FIELDS_WIDGET &&
view.visibility === ViewVisibility.WORKSPACE;