From b1c821b0e30879f3db66d7c40224676d3f7e7f35 Mon Sep 17 00:00:00 2001 From: Abdul Rahman <81605929+abdulrahmancodes@users.noreply.github.com> Date: Fri, 9 Jan 2026 22:01:22 +0530 Subject: [PATCH] Implement hide empty groups for grouped table view (#16494) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Félix Malfait Co-authored-by: Félix Malfait --- .../components/RecordBoardColumn.tsx | 15 +++------------ .../RecordBoardColumnHeaderWrapper.tsx | 15 +++------------ .../hooks/useShouldHideRecordGroup.ts | 17 +++++++++++++++++ .../components/RecordTableRecordGroupRows.tsx | 7 +++++++ .../RecordTableRecordGroupSection.tsx | 7 +++++++ 5 files changed, 37 insertions(+), 24 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/record-group/hooks/useShouldHideRecordGroup.ts diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumn.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumn.tsx index 1bd5ef4343..94457e3403 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumn.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumn.tsx @@ -3,13 +3,11 @@ import { Droppable } from '@hello-pangea/dnd'; import { RecordBoardColumnCardsContainer } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer'; import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; -import { emptyRecordGroupByIdComponentFamilyState } from '@/object-record/record-group/states/emptyRecordGroupByIdComponentFamilyState'; +import { useShouldHideRecordGroup } from '@/object-record/record-group/hooks/useShouldHideRecordGroup'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState'; -import { recordIndexShouldHideEmptyRecordGroupsComponentState } from '@/object-record/record-index/states/recordIndexShouldHideEmptyRecordGroupsComponentState'; import { DragAndDropLibraryLegacyReRenderBreaker } from '@/ui/drag-and-drop/components/DragAndDropReRenderBreaker'; import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue'; -import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; @@ -44,16 +42,9 @@ export const RecordBoardColumn = ({ recordBoardColumnId, ); - const shouldHideEmptyRecordGroups = useRecoilComponentValue( - recordIndexShouldHideEmptyRecordGroupsComponentState, - ); + const shouldHide = useShouldHideRecordGroup(recordBoardColumnId); - const isRecordGroupEmpty = useRecoilComponentFamilyValue( - emptyRecordGroupByIdComponentFamilyState, - recordBoardColumnId, - ); - - if (shouldHideEmptyRecordGroups && isRecordGroupEmpty) { + if (shouldHide) { return null; } diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderWrapper.tsx index 8893b30247..230f45f80c 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderWrapper.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderWrapper.tsx @@ -1,11 +1,9 @@ import { RecordBoardColumnHeader } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeader'; import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext'; -import { emptyRecordGroupByIdComponentFamilyState } from '@/object-record/record-group/states/emptyRecordGroupByIdComponentFamilyState'; +import { useShouldHideRecordGroup } from '@/object-record/record-group/hooks/useShouldHideRecordGroup'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState'; -import { recordIndexShouldHideEmptyRecordGroupsComponentState } from '@/object-record/record-index/states/recordIndexShouldHideEmptyRecordGroupsComponentState'; import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue'; -import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; @@ -27,16 +25,9 @@ export const RecordBoardColumnHeaderWrapper = ({ columnId, ); - const shouldHideEmptyRecordGroups = useRecoilComponentValue( - recordIndexShouldHideEmptyRecordGroupsComponentState, - ); + const shouldHide = useShouldHideRecordGroup(columnId); - const isRecordGroupEmpty = useRecoilComponentFamilyValue( - emptyRecordGroupByIdComponentFamilyState, - columnId, - ); - - if (shouldHideEmptyRecordGroups && isRecordGroupEmpty) { + if (shouldHide) { return null; } diff --git a/packages/twenty-front/src/modules/object-record/record-group/hooks/useShouldHideRecordGroup.ts b/packages/twenty-front/src/modules/object-record/record-group/hooks/useShouldHideRecordGroup.ts new file mode 100644 index 0000000000..65114c5a97 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-group/hooks/useShouldHideRecordGroup.ts @@ -0,0 +1,17 @@ +import { emptyRecordGroupByIdComponentFamilyState } from '@/object-record/record-group/states/emptyRecordGroupByIdComponentFamilyState'; +import { recordIndexShouldHideEmptyRecordGroupsComponentState } from '@/object-record/record-index/states/recordIndexShouldHideEmptyRecordGroupsComponentState'; +import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue'; +import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; + +export const useShouldHideRecordGroup = (recordGroupId: string): boolean => { + const shouldHideEmptyRecordGroups = useRecoilComponentValue( + recordIndexShouldHideEmptyRecordGroupsComponentState, + ); + + const isRecordGroupEmpty = useRecoilComponentFamilyValue( + emptyRecordGroupByIdComponentFamilyState, + recordGroupId, + ); + + return shouldHideEmptyRecordGroups && isRecordGroupEmpty; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupRows.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupRows.tsx index e2c69cca61..d09c93259d 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupRows.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupRows.tsx @@ -1,4 +1,5 @@ import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId'; +import { useShouldHideRecordGroup } from '@/object-record/record-group/hooks/useShouldHideRecordGroup'; import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState'; import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector'; import { RecordTableBodyDroppablePlaceholder } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppablePlaceholder'; @@ -15,6 +16,8 @@ import { isDefined } from 'twenty-shared/utils'; export const RecordTableRecordGroupRows = () => { const currentRecordGroupId = useCurrentRecordGroupId(); + const shouldHide = useShouldHideRecordGroup(currentRecordGroupId); + const allRecordIds = useRecoilComponentValue( recordIndexAllRecordIdsComponentSelector, ); @@ -34,6 +37,10 @@ export const RecordTableRecordGroupRows = () => { [allRecordIds], ); + if (shouldHide) { + return null; + } + if (!isRecordGroupTableSectionToggled) { return null; } diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx index 23fb3d57a8..2ec08785a8 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection.tsx @@ -5,6 +5,7 @@ import { useCallback } from 'react'; import { RecordBoardColumnHeaderAggregateDropdown } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdown'; import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector'; import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId'; +import { useShouldHideRecordGroup } from '@/object-record/record-group/hooks/useShouldHideRecordGroup'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; @@ -117,6 +118,8 @@ export const RecordTableRecordGroupSection = () => { const currentRecordGroupId = useCurrentRecordGroupId(); + const shouldHide = useShouldHideRecordGroup(currentRecordGroupId); + const { objectMetadataItem } = useRecordTableContextOrThrow(); const recordGroup = useRecoilValue( @@ -178,6 +181,10 @@ export const RecordTableRecordGroupSection = () => { sumOfWidthOfVisibleRecordFieldsAfterLabelIdentifierField + sumOfBorderWidthForFields; + if (shouldHide) { + return null; + } + if (!isDefined(recordGroup)) { return null; }