From 7c252ff23378850209dbfee0166d3dcd4051fc45 Mon Sep 17 00:00:00 2001 From: Lakshay Manchanda Date: Mon, 18 May 2026 08:25:51 -0700 Subject: [PATCH] Fix 19026 deactivated relation unassignable (#19296) PR to fix the bug #19026 This PR will ensure that if an object has some relation deactivated, the relation will not be visible in the side panel tab and will not be assignable in the deactivated relation. ## Notes deactivated in People image ## Notes not visible in the side panel of people image --------- Co-authored-by: Thomas Trompette --- .../components/PageLayoutTabsRenderer.tsx | 50 +++++++++++++++++-- .../WidgetTypeToRelationFieldName.ts | 12 +++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 packages/twenty-front/src/modules/page-layout/constants/WidgetTypeToRelationFieldName.ts diff --git a/packages/twenty-front/src/modules/page-layout/components/PageLayoutTabsRenderer.tsx b/packages/twenty-front/src/modules/page-layout/components/PageLayoutTabsRenderer.tsx index f32d3dea3d..ea84859c64 100644 --- a/packages/twenty-front/src/modules/page-layout/components/PageLayoutTabsRenderer.tsx +++ b/packages/twenty-front/src/modules/page-layout/components/PageLayoutTabsRenderer.tsx @@ -1,10 +1,12 @@ import { metadataStoreState } from '@/metadata-store/states/metadataStoreState'; import { type FlatObjectMetadataItem } from '@/metadata-store/types/FlatObjectMetadataItem'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { PageLayoutLeftPanel } from '@/page-layout/components/PageLayoutLeftPanel'; import { PageLayoutTabList } from '@/page-layout/components/PageLayoutTabList'; import { PageLayoutTabListEffect } from '@/page-layout/components/PageLayoutTabListEffect'; import { DEFAULT_RECORD_PAGE_LAYOUT_ID } from '@/page-layout/constants/DefaultRecordPageLayoutId'; import { PAGE_LAYOUT_LEFT_PANEL_CONTAINER_WIDTH } from '@/page-layout/constants/PageLayoutLeftPanelContainerWidth'; +import { WIDGET_TYPE_TO_RELATION_FIELD_NAME } from '@/page-layout/constants/WidgetTypeToRelationFieldName'; import { useCurrentPageLayoutOrThrow } from '@/page-layout/hooks/useCurrentPageLayoutOrThrow'; import { useIsPageLayoutInEditMode } from '@/page-layout/hooks/useIsPageLayoutInEditMode'; import { usePageLayoutAddTabStrategy } from '@/page-layout/hooks/usePageLayoutAddTabStrategy'; @@ -17,13 +19,17 @@ import { getTabsWithVisibleWidgets } from '@/page-layout/utils/getTabsWithVisibl import { shouldEnableTabEditingFeatures } from '@/page-layout/utils/shouldEnableTabEditingFeatures'; import { sortTabsByPosition } from '@/page-layout/utils/sortTabsByPosition'; import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext'; +import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord'; import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue'; import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue'; import { styled } from '@linaria/react'; +import { useMemo } from 'react'; +import { FieldMetadataType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { useIsMobile } from 'twenty-ui/utilities'; + const StyledContainer = styled.div<{ hasPinnedTab: boolean }>` display: grid; grid-template-columns: ${({ hasPinnedTab }) => @@ -69,6 +75,28 @@ export const PageLayoutTabsRenderer = () => { currentPageLayout.id, ); + const targetRecord = useTargetRecord(); + + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular: targetRecord.targetObjectNameSingular, + }); + + const inactiveRelationFieldNames = useMemo(() => { + if (!isDefined(objectMetadataItem)) { + return new Set(); + } + return new Set( + objectMetadataItem.fields + .filter( + (field) => + !field.isActive && + (field.type === FieldMetadataType.RELATION || + field.type === FieldMetadataType.MORPH_RELATION), + ) + .map((field) => field.name), + ); + }, [objectMetadataItem]); + const isMobile = useIsMobile(); const metadataStore = useAtomFamilyStateValue( @@ -114,6 +142,22 @@ export const PageLayoutTabsRenderer = () => { const sortedTabs = sortTabsByPosition(tabsToRenderInTabList); + const sortedActiveTabs = useMemo( + () => + sortedTabs.filter((tab) => { + const widgetTypes = tab.widgets.map((widget) => widget.type); + return !widgetTypes.some((widgetType) => { + const relationFieldName = + WIDGET_TYPE_TO_RELATION_FIELD_NAME[widgetType]; + return ( + isDefined(relationFieldName) && + inactiveRelationFieldNames.has(relationFieldName) + ); + }); + }), + [sortedTabs, inactiveRelationFieldNames], + ); + const activeTabExistsInCurrentPageLayout = currentPageLayout.tabs.some( (tab) => tab.id === activeTabId, ); @@ -126,16 +170,16 @@ export const PageLayoutTabsRenderer = () => { - {(sortedTabs.length > 1 || isPageLayoutInEditMode) && ( + {(sortedActiveTabs.length > 1 || isPageLayoutInEditMode) && ( +> = { + [WidgetType.TASKS]: 'taskTargets', + [WidgetType.NOTES]: 'noteTargets', + [WidgetType.FILES]: 'attachments', + [WidgetType.TIMELINE]: 'timelineActivities', + [WidgetType.EMAILS]: 'messageParticipants', + [WidgetType.CALENDAR]: 'calendarEventParticipants', +};