feat: record board component state refactor (#8779)

Fix #8758 

This PR is migrating the recoil component state from v1 to v2 for board.
It also now share some states and logics between board and table,
further can be done later.
Lastly this PR fix an issue since the PR #8613 that was treating
no-value as a normal record-group.
This commit is contained in:
Jérémy M
2024-11-28 13:44:21 +01:00
committed by GitHub
parent e96ad9a1f2
commit 812ed6ed69
95 changed files with 1355 additions and 1316 deletions

View File

@ -10,46 +10,50 @@ import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObje
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useLocation } from 'react-router-dom';
import { useSetRecoilState } from 'recoil';
export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
const {
currentContentId,
viewType,
recordIndexId,
objectMetadataItem,
onContentChange,
closeDropdown,
} = useOptionsDropdown();
const { objectNamePlural } = useObjectNamePluralFromSingular({
objectNameSingular: objectMetadataItem.nameSingular,
});
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordGroupFieldMetadataComponentState,
);
const { hiddenRecordGroups, viewGroupFieldMetadataItem } = useRecordGroups({
const hiddenRecordGroupIds = useRecoilComponentValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const { objectNamePlural } = useObjectNamePluralFromSingular({
objectNameSingular: objectMetadataItem.nameSingular,
});
const { handleVisibilityChange: handleRecordGroupVisibilityChange } =
useRecordGroupVisibility({
viewBarId: recordIndexId,
viewType,
});
const viewGroupSettingsUrl = getSettingsPagePath(
SettingsPath.ObjectFieldEdit,
{
objectSlug: objectNamePlural,
fieldSlug: viewGroupFieldMetadataItem?.name ?? '',
fieldSlug: recordGroupFieldMetadata?.name ?? '',
},
);
@ -61,11 +65,11 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
useEffect(() => {
if (
currentContentId === 'hiddenRecordGroups' &&
hiddenRecordGroups.length === 0
hiddenRecordGroupIds.length === 0
) {
onContentChange('recordGroups');
}
}, [hiddenRecordGroups, currentContentId, onContentChange]);
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
return (
<>
@ -74,13 +78,13 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
StartIcon={IconChevronLeft}
onClick={() => onContentChange('recordGroups')}
>
Hidden {viewGroupFieldMetadataItem?.label}
Hidden {recordGroupFieldMetadata?.label}
</DropdownMenuHeader>
</DropdownMenuItemsContainer>
<RecordGroupsVisibilityDropdownSection
title={`Hidden ${viewGroupFieldMetadataItem?.label}`}
recordGroups={hiddenRecordGroups}
title={`Hidden ${recordGroupFieldMetadata?.label}`}
recordGroupIds={hiddenRecordGroupIds}
onVisibilityChange={handleRecordGroupVisibilityChange}
isDraggable={false}
showSubheader={false}

View File

@ -15,7 +15,7 @@ import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/h
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import {
displayedExportProgress,
useExportRecords,
@ -26,6 +26,7 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewType } from '@/views/types/ViewType';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
@ -44,6 +45,10 @@ export const ObjectOptionsDropdownMenuContent = () => {
objectNameSingular: objectMetadataItem.nameSingular,
});
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordGroupFieldMetadataComponentState,
);
useScopedHotkeys(
[Key.Escape],
() => {
@ -64,10 +69,6 @@ export const ObjectOptionsDropdownMenuContent = () => {
viewBarId: recordIndexId,
});
const { viewGroupFieldMetadataItem } = useRecordGroups({
objectNameSingular: objectMetadataItem.nameSingular,
});
const { openObjectRecordsSpreasheetImportDialog } =
useOpenObjectRecordsSpreadsheetImportDialog(
objectMetadataItem.nameSingular,
@ -113,7 +114,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
onClick={() => onContentChange('recordGroups')}
LeftIcon={IconLayoutList}
text="Group by"
contextualText={viewGroupFieldMetadataItem?.label}
contextualText={recordGroupFieldMetadata?.label}
hasSubMenu
/>
)}

View File

@ -12,7 +12,7 @@ import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObje
import { StyledInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { useSearchRecordGroupField } from '@/object-record/object-options-dropdown/hooks/useSearchRecordGroupField';
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
import { useHandleRecordGroupField } from '@/object-record/record-index/hooks/useHandleRecordGroupField';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
@ -20,6 +20,7 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useLocation } from 'react-router-dom';
import { useSetRecoilState } from 'recoil';
@ -38,9 +39,9 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
objectNameSingular: objectMetadataItem.nameSingular,
});
const { hiddenRecordGroups } = useRecordGroups({
objectNameSingular: objectMetadataItem.nameSingular,
});
const hiddenRecordGroupIds = useRecoilComponentValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const {
recordGroupFieldSearchInput,
@ -68,11 +69,11 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
useEffect(() => {
if (
currentContentId === 'hiddenRecordGroups' &&
hiddenRecordGroups.length === 0
hiddenRecordGroupIds.length === 0
) {
onContentChange('recordGroups');
}
}, [hiddenRecordGroups, currentContentId, onContentChange]);
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
return (
<>

View File

@ -8,24 +8,21 @@ import {
} from 'twenty-ui';
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
import { RecordGroupSort } from '@/object-record/record-group/types/RecordGroupSort';
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
export const ObjectOptionsDropdownRecordGroupSortContent = () => {
const {
currentContentId,
objectMetadataItem,
onContentChange,
closeDropdown,
} = useOptionsDropdown();
const { currentContentId, onContentChange, closeDropdown } =
useOptionsDropdown();
const { hiddenRecordGroups } = useRecordGroups({
objectNameSingular: objectMetadataItem.nameSingular,
});
const hiddenRecordGroupIds = useRecoilComponentValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const setRecordGroupSort = useSetRecoilComponentStateV2(
recordIndexRecordGroupSortComponentState,
@ -39,11 +36,11 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
useEffect(() => {
if (
currentContentId === 'hiddenRecordGroups' &&
hiddenRecordGroups.length === 0
hiddenRecordGroupIds.length === 0
) {
onContentChange('recordGroups');
}
}, [hiddenRecordGroups, currentContentId, onContentChange]);
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
return (
<>

View File

@ -13,8 +13,10 @@ import {
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
import { useRecordGroupReorder } from '@/object-record/record-group/hooks/useRecordGroupReorder';
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
import { recordIndexRecordGroupHideComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupHideComponentState';
import { recordIndexRecordGroupIsDraggableSortComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexRecordGroupIsDraggableSortComponentSelector';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
@ -26,22 +28,20 @@ import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
export const ObjectOptionsDropdownRecordGroupsContent = () => {
const isViewGroupEnabled = useIsFeatureEnabled('IS_VIEW_GROUPS_ENABLED');
const {
currentContentId,
viewType,
recordIndexId,
objectMetadataItem,
onContentChange,
resetContent,
} = useOptionsDropdown();
const { currentContentId, recordIndexId, onContentChange, resetContent } =
useOptionsDropdown();
const {
hiddenRecordGroups,
visibleRecordGroups,
viewGroupFieldMetadataItem,
} = useRecordGroups({
objectNameSingular: objectMetadataItem.nameSingular,
});
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordGroupFieldMetadataComponentState,
);
const visibleRecordGroupIds = useRecoilComponentValueV2(
visibleRecordGroupIdsComponentSelector,
);
const hiddenRecordGroupIds = useRecoilComponentValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const isDragableSortRecordGroup = useRecoilComponentValueV2(
recordIndexRecordGroupIsDraggableSortComponentSelector,
@ -56,23 +56,21 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
handleHideEmptyRecordGroupChange,
} = useRecordGroupVisibility({
viewBarId: recordIndexId,
viewType,
});
const { handleOrderChange: handleRecordGroupOrderChange } =
useRecordGroupReorder({
objectNameSingular: objectMetadataItem.nameSingular,
viewBarId: recordIndexId,
});
useEffect(() => {
if (
currentContentId === 'hiddenRecordGroups' &&
hiddenRecordGroups.length === 0
hiddenRecordGroupIds.length === 0
) {
onContentChange('recordGroups');
}
}, [hiddenRecordGroups, currentContentId, onContentChange]);
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
return (
<>
@ -86,9 +84,9 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
onClick={() => onContentChange('recordGroupFields')}
LeftIcon={IconLayoutList}
text={
!viewGroupFieldMetadataItem
!recordGroupFieldMetadata
? 'Group by'
: `Group by "${viewGroupFieldMetadataItem.label}"`
: `Group by "${recordGroupFieldMetadata.label}"`
}
hasSubMenu
/>
@ -108,12 +106,12 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
toggleSize="small"
/>
</DropdownMenuItemsContainer>
{visibleRecordGroups.length > 0 && (
{visibleRecordGroupIds.length > 0 && (
<>
<DropdownMenuSeparator />
<RecordGroupsVisibilityDropdownSection
title="Visible groups"
recordGroups={visibleRecordGroups}
recordGroupIds={visibleRecordGroupIds}
onDragEnd={handleRecordGroupOrderChange}
onVisibilityChange={handleRecordGroupVisibilityChange}
isDraggable={isDragableSortRecordGroup}
@ -121,14 +119,14 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
/>
</>
)}
{hiddenRecordGroups.length > 0 && (
{hiddenRecordGroupIds.length > 0 && (
<>
<DropdownMenuSeparator />
<DropdownMenuItemsContainer>
<MenuItemNavigate
onClick={() => onContentChange('hiddenRecordGroups')}
LeftIcon={IconEyeOff}
text={`Hidden ${viewGroupFieldMetadataItem?.label ?? ''}`}
text={`Hidden ${recordGroupFieldMetadata?.label ?? ''}`}
/>
</DropdownMenuItemsContainer>
</>

View File

@ -4,10 +4,11 @@ import { useRecoilState } from 'recoil';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { GraphQLView } from '@/views/types/GraphQLView';
@ -32,11 +33,12 @@ export const useObjectOptionsForBoard = ({
const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
const { updateCurrentView } = useUpdateCurrentView(viewBarId);
const { isCompactModeActiveState } = useRecordBoard(recordBoardId);
const [isCompactModeActive, setIsCompactModeActive] = useRecoilState(
isCompactModeActiveState,
);
const [isCompactModeActive, setIsCompactModeActive] =
useRecoilComponentStateV2(
isRecordBoardCompactModeActiveComponentState,
recordBoardId,
);
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,