favorite folders followup (#8570)

Something changed, which affected the Favorite folder picker checkbox
styles -- fixed it!
Cleaned up code in `CurrentWorkspaceMemberFavoritesFolders` - removed
redundant filtering since favorites are already filtered in
`usePrefetchedFavoritesData`.
Regarding issue #8569 - I am not sure what to do in this case. Since
Folders data is gated by a feature flag, we can't use it in
`CurrentWorkspaceMemberFavoritesFolders` to ensure the favorite section
renders with empty folders. Currently, the section only appears when at
least one favorite exists - may be leave this section open at all times
or fix this bug after removal of the feature flag?

---------

Co-authored-by: Nitin Koche <nitinkoche@Nitins-MacBook-Pro.local>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
nitin
2024-11-19 23:25:25 +05:30
committed by GitHub
parent 2773974459
commit 4f2019edae
45 changed files with 253 additions and 315 deletions

View File

@ -61,9 +61,9 @@ export const CurrentWorkspaceMemberFavorites = ({
const selectedFavoriteIndex = folder.favorites.findIndex((favorite) =>
isLocationMatchingFavorite(currentPath, currentViewPath, favorite),
);
const handleReorderFavorite = useReorderFavorite();
const { handleReorderFavorite } = useReorderFavorite();
const deleteFavorite = useDeleteFavorite();
const { deleteFavorite } = useDeleteFavorite();
const favoriteFolderContentLength = folder.favorites.length;
@ -154,6 +154,7 @@ export const CurrentWorkspaceMemberFavorites = ({
key={favorite.id}
draggableId={favorite.id}
index={index}
isInsideScrollableContainer
itemComponent={
<NavigationDrawerSubItem
key={favorite.id}

View File

@ -4,8 +4,8 @@ import { useRecoilState, useRecoilValue } from 'recoil';
import {
IconFolderPlus,
IconHeartOff,
isDefined,
LightIconButton,
isDefined,
} from 'twenty-ui';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
@ -32,9 +32,9 @@ export const CurrentWorkspaceMemberFavoritesFolders = () => {
const currentViewPath = useLocation().pathname + useLocation().search;
const theme = useTheme();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const favorites = useFavorites();
const deleteFavorite = useDeleteFavorite();
const handleReorderFavorite = useReorderFavorite();
const { sortedFavorites: favorites } = useFavorites();
const { deleteFavorite } = useDeleteFavorite();
const { handleReorderFavorite } = useReorderFavorite();
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
useRecoilState(isFavoriteFolderCreatingState);
@ -50,24 +50,25 @@ export const CurrentWorkspaceMemberFavoritesFolders = () => {
const toggleNewFolder = () => {
setIsFavoriteFolderCreating((current) => !current);
};
const shouldDisplayFavoritesWithFeatureFlagEnabled = true;
//todo: remove this logic once feature flag gating is removed
const shouldDisplayFavoritesWithoutFeatureFlagEnabled =
favorites.length > 0 || isFavoriteFolderCreating;
const shouldDisplayFavorites = isFavoriteFolderEnabled
? shouldDisplayFavoritesWithFeatureFlagEnabled
: shouldDisplayFavoritesWithoutFeatureFlagEnabled;
if (loading && isDefined(currentWorkspaceMember)) {
return <FavoritesSkeletonLoader />;
}
const currentWorkspaceMemberFavorites = favorites.filter(
(favorite) => favorite.workspaceMemberId === currentWorkspaceMember?.id,
);
const orphanFavorites = currentWorkspaceMemberFavorites.filter(
const orphanFavorites = favorites.filter(
(favorite) => !favorite.favoriteFolderId,
);
if (
(!currentWorkspaceMemberFavorites ||
currentWorkspaceMemberFavorites.length === 0) &&
!isFavoriteFolderCreating
) {
if (!shouldDisplayFavorites) {
return null;
}
@ -104,6 +105,7 @@ export const CurrentWorkspaceMemberFavoritesFolders = () => {
key={favorite.id}
draggableId={favorite.id}
index={index}
isInsideScrollableContainer={true}
itemComponent={
<NavigationDrawerItem
key={favorite.id}

View File

@ -38,6 +38,7 @@ export const FavoriteFolderNavigationDrawerItemDropdown = ({
dropdownHotkeyScope={{
scope: FavoriteFolderHotkeyScope.FavoriteFolderRightIconDropdown,
}}
usePortal
data-select-disable
clickableComponent={
<LightIconButton Icon={IconDotsVertical} accent="tertiary" />

View File

@ -18,8 +18,8 @@ export const FavoriteFolders = ({
}: FavoriteFoldersProps) => {
const [newFolderName, setNewFolderName] = useState('');
const favoritesByFolder = useFavoritesByFolder();
const createFavoriteFolder = useCreateFavoriteFolder();
const { favoritesByFolder } = useFavoritesByFolder();
const { createNewFavoriteFolder } = useCreateFavoriteFolder();
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
useRecoilState(isFavoriteFolderCreatingState);
@ -33,12 +33,12 @@ export const FavoriteFolders = ({
setIsFavoriteFolderCreating(false);
setNewFolderName('');
await createFavoriteFolder(value);
await createNewFavoriteFolder(value);
return true;
};
const handleClickOutside = async (
event: MouseEvent | TouchEvent,
_event: MouseEvent | TouchEvent,
value: string,
) => {
if (!value) {
@ -48,7 +48,7 @@ export const FavoriteFolders = ({
setIsFavoriteFolderCreating(false);
setNewFolderName('');
await createFavoriteFolder(value);
await createNewFavoriteFolder(value);
};
const handleCancelFavoriteFolderCreation = () => {

View File

@ -0,0 +1,20 @@
import { IconButton, IconHeart } from 'twenty-ui';
type PageFavoriteButtonProps = {
isFavorite: boolean;
onClick?: () => void;
};
export const PageFavoriteButton = ({
isFavorite,
onClick,
}: PageFavoriteButtonProps) => (
<IconButton
Icon={IconHeart}
size="medium"
variant="secondary"
data-testid="add-button"
accent={isFavorite ? 'danger' : 'default'}
onClick={onClick}
/>
);

View File

@ -0,0 +1,51 @@
import { PageFavoriteButton } from '@/favorites/components/PageFavoriteButton';
import { FavoriteFolderPicker } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPicker';
import { FavoriteFolderPickerEffect } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPickerEffect';
import { FavoriteFolderPickerComponentInstanceContext } from '@/favorites/favorite-folder-picker/scopes/FavoriteFolderPickerScope';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
type PageFavoriteFoldersDropdownProps = {
dropdownId: string;
isFavorite: boolean;
record?: ObjectRecord;
objectNameSingular: string;
};
export const PageFavoriteFoldersDropdown = ({
dropdownId,
isFavorite,
record,
objectNameSingular,
}: PageFavoriteFoldersDropdownProps) => {
const { closeDropdown } = useDropdown(dropdownId);
return (
<FavoriteFolderPickerComponentInstanceContext
favoriteFoldersScopeId={dropdownId}
>
<DropdownScope dropdownScopeId={dropdownId}>
<Dropdown
dropdownId={dropdownId}
dropdownPlacement="bottom-start"
clickableComponent={<PageFavoriteButton isFavorite={isFavorite} />}
dropdownComponents={
<>
<FavoriteFolderPickerEffect record={record} />
<FavoriteFolderPicker
onSubmit={closeDropdown}
record={record}
objectNameSingular={objectNameSingular}
/>
</>
}
dropdownHotkeyScope={{
scope: dropdownId,
}}
/>
</DropdownScope>
</FavoriteFolderPickerComponentInstanceContext>
);
};

View File

@ -1,10 +0,0 @@
import styled from '@emotion/styled';
import { MenuItemMultiSelect } from '@ui/navigation/menu-item/components/MenuItemMultiSelect';
const StyledNoGapMenuItem = styled(MenuItemMultiSelect)`
& > div {
gap: 0;
}
`;
export const FavoriteFolderMenuItemMultiSelect = StyledNoGapMenuItem;

View File

@ -36,7 +36,7 @@ export const FavoriteFolderPicker = ({
FavoriteFolderPickerInstanceContext,
);
const { getFoldersByIds, toggleFolderSelection } = useFavoriteFolderPicker({
const { favoriteFolders, toggleFolderSelection } = useFavoriteFolderPicker({
record,
objectNameSingular,
});
@ -45,8 +45,7 @@ export const FavoriteFolderPicker = ({
favoriteFolderSearchFilterComponentState,
);
const folders = getFoldersByIds();
const filteredFolders = folders.filter((folder) =>
const filteredFolders = favoriteFolders.filter((folder) =>
folder.name
.toLowerCase()
.includes(favoriteFoldersSearchFilter.toLowerCase()),
@ -94,7 +93,7 @@ export const FavoriteFolderPicker = ({
<DropdownMenuSeparator />
<DropdownMenuItemsContainer hasMaxHeight>
<FavoriteFolderPickerList
folders={folders}
folders={favoriteFolders}
toggleFolderSelection={toggleFolderSelection}
/>
</DropdownMenuItemsContainer>

View File

@ -30,7 +30,7 @@ export const FavoriteFolderPickerEffect = ({
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
const favorites = useFavorites();
const { sortedFavorites: favorites } = useFavorites();
const setCheckedState = useSetRecoilComponentStateV2(
favoriteFolderPickerCheckedComponentState,
);

View File

@ -14,10 +14,6 @@ const StyledFooter = styled.div`
border-top: 1px solid ${({ theme }) => theme.border.color.light};
`;
const StyledIconPlus = styled(IconPlus)`
padding-left: ${({ theme }) => theme.spacing(1)};
`;
export const FavoriteFolderPickerFooter = () => {
const [, setIsFavoriteFolderCreating] = useRecoilState(
isFavoriteFolderCreatingState,
@ -35,7 +31,7 @@ export const FavoriteFolderPickerFooter = () => {
closeDropdown();
}}
text="Add folder"
LeftIcon={() => <StyledIconPlus size={theme.icon.size.md} />}
LeftIcon={() => <IconPlus size={theme.icon.size.md} />}
/>
</DropdownMenuItemsContainer>
</StyledFooter>

View File

@ -4,8 +4,7 @@ import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import styled from '@emotion/styled';
import { MenuItem } from 'twenty-ui';
import { FavoriteFolderMenuItemMultiSelect } from './FavoriteFolderMenuItemMultiSelect';
import { MenuItem, MenuItemMultiSelect } from 'twenty-ui';
const StyledItemsContainer = styled.div`
width: 100%;
@ -30,6 +29,7 @@ export const FavoriteFolderPickerList = ({
const [favoriteFoldersSearchFilter] = useRecoilComponentStateV2(
favoriteFolderSearchFilterComponentState,
);
const [favoriteFolderPickerChecked] = useRecoilComponentStateV2(
favoriteFolderPickerCheckedComponentState,
);
@ -47,7 +47,7 @@ export const FavoriteFolderPickerList = ({
return (
<StyledItemsContainer>
{showNoFolderOption && (
<FavoriteFolderMenuItemMultiSelect
<MenuItemMultiSelect
key={`menu-${NO_FOLDER_ID}`}
onSelectChange={() => toggleFolderSelection(NO_FOLDER_ID)}
selected={favoriteFolderPickerChecked.includes(NO_FOLDER_ID)}
@ -60,7 +60,7 @@ export const FavoriteFolderPickerList = ({
)}
{filteredFolders.length > 0
? filteredFolders.map((folder) => (
<FavoriteFolderMenuItemMultiSelect
<MenuItemMultiSelect
key={`menu-${folder.id}`}
onSelectChange={() => toggleFolderSelection(folder.id)}
selected={favoriteFolderPickerChecked.includes(folder.id)}

View File

@ -1,6 +1,5 @@
import { favoriteFolderIdsPickerComponentState } from '@/favorites/favorite-folder-picker/states/favoriteFolderIdPickerComponentState';
import { favoriteFolderPickerCheckedComponentState } from '@/favorites/favorite-folder-picker/states/favoriteFolderPickerCheckedComponentState';
import { favoriteFolderPickerComponentFamilyState } from '@/favorites/favorite-folder-picker/states/favoriteFolderPickerComponentFamilyState';
import { favoriteFoldersComponentSelector } from '@/favorites/favorite-folder-picker/states/selectors/favoriteFoldersComponentSelector';
import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
@ -8,7 +7,7 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-ui';
@ -17,46 +16,26 @@ type useFavoriteFolderPickerProps = {
objectNameSingular: string;
};
type FolderOperations = {
getFoldersByIds: () => FavoriteFolder[];
type useFavoriteFolderPickerReturnType = {
favoriteFolders: FavoriteFolder[];
toggleFolderSelection: (folderId: string) => Promise<void>;
};
export const useFavoriteFolderPicker = ({
record,
objectNameSingular,
}: useFavoriteFolderPickerProps): FolderOperations => {
const [favoriteFolderIdsPicker] = useRecoilComponentStateV2(
favoriteFolderIdsPickerComponentState,
);
}: useFavoriteFolderPickerProps): useFavoriteFolderPickerReturnType => {
const favoriteFoldersMultiSelectCheckedState =
useRecoilComponentCallbackStateV2(
favoriteFolderPickerCheckedComponentState,
);
const favoriteFolderPickerFamilyState = useRecoilComponentCallbackStateV2(
favoriteFolderPickerComponentFamilyState,
);
const { sortedFavorites: favorites } = useFavorites();
const { createFavorite } = useCreateFavorite();
const { deleteFavorite } = useDeleteFavorite();
const favorites = useFavorites();
const createFavorite = useCreateFavorite();
const deleteFavorite = useDeleteFavorite();
const getFoldersByIds = useRecoilCallback(
({ snapshot }) =>
(): FavoriteFolder[] => {
return favoriteFolderIdsPicker
.map((folderId) => {
const folderValue = snapshot
.getLoadable(favoriteFolderPickerFamilyState(folderId))
.getValue();
return folderValue;
})
.filter((folder): folder is FavoriteFolder => isDefined(folder));
},
[favoriteFolderIdsPicker, favoriteFolderPickerFamilyState],
const favoriteFolders = useRecoilComponentValueV2(
favoriteFoldersComponentSelector,
);
const toggleFolderSelection = useRecoilCallback(
@ -123,7 +102,7 @@ export const useFavoriteFolderPicker = ({
);
return {
getFoldersByIds,
favoriteFolders,
toggleFolderSelection,
};
};

View File

@ -1,15 +1,15 @@
import { FavoriteFolderPickerInstanceContext } from '@/favorites/favorite-folder-picker/states/context/FavoriteFolderPickerInstanceContext';
import { ReactNode } from 'react';
type FavoriteFolderPickerScopeProps = {
type FavoriteFolderPickerComponentInstanceContextProps = {
children: ReactNode;
favoriteFoldersScopeId: string;
};
export const FavoriteFolderPickerScope = ({
export const FavoriteFolderPickerComponentInstanceContext = ({
children,
favoriteFoldersScopeId,
}: FavoriteFolderPickerScopeProps) => {
}: FavoriteFolderPickerComponentInstanceContextProps) => {
return (
<FavoriteFolderPickerInstanceContext.Provider
value={{ instanceId: favoriteFoldersScopeId }}

View File

@ -1,9 +0,0 @@
import { FavoriteFolderPickerInstanceContext } from '@/favorites/favorite-folder-picker/states/context/FavoriteFolderPickerInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const favoriteFolderLoadingComponentState =
createComponentStateV2<boolean>({
key: 'favoriteFoldersLoadingComponentState',
defaultValue: false,
componentInstanceContext: FavoriteFolderPickerInstanceContext,
});

View File

@ -0,0 +1,31 @@
import { FavoriteFolderPickerInstanceContext } from '@/favorites/favorite-folder-picker/states/context/FavoriteFolderPickerInstanceContext';
import { favoriteFolderIdsPickerComponentState } from '@/favorites/favorite-folder-picker/states/favoriteFolderIdPickerComponentState';
import { favoriteFolderPickerComponentFamilyState } from '@/favorites/favorite-folder-picker/states/favoriteFolderPickerComponentFamilyState';
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
import { isDefined } from 'twenty-ui';
export const favoriteFoldersComponentSelector = createComponentSelectorV2<
FavoriteFolder[]
>({
key: 'favoriteFoldersComponentSelector',
componentInstanceContext: FavoriteFolderPickerInstanceContext,
get:
({ instanceId }) =>
({ get }) => {
const folderIds = get(
favoriteFolderIdsPickerComponentState.atomFamily({ instanceId }),
);
return folderIds
.map((folderId: string) =>
get(
favoriteFolderPickerComponentFamilyState.atomFamily({
instanceId,
familyKey: folderId,
}),
),
)
.filter((folder): folder is FavoriteFolder => isDefined(folder));
},
});

View File

@ -44,7 +44,10 @@ describe('useCreateFavorite', () => {
{ wrapper: Wrapper },
);
result.current(favoriteTargetObjectRecord, CoreObjectNameSingular.Person);
result.current.createFavorite(
favoriteTargetObjectRecord,
CoreObjectNameSingular.Person,
);
await waitFor(() => {
expect(mocks[0].result).toHaveBeenCalled();

View File

@ -38,7 +38,7 @@ describe('useDeleteFavorite', () => {
{ wrapper: Wrapper },
);
result.current(favoriteId);
result.current.deleteFavorite(favoriteId);
await waitFor(() => {
expect(mocks[1].result).toHaveBeenCalled();

View File

@ -38,6 +38,6 @@ describe('useFavorites', () => {
{ wrapper: Wrapper },
);
expect(result.current).toEqual(sortedFavorites);
expect(result.current.sortedFavorites).toEqual(sortedFavorites);
});
});

View File

@ -54,7 +54,10 @@ describe('useReorderFavorite', () => {
announce: () => {},
};
result.current(dragAndDropResult, responderProvided);
result.current.handleReorderFavorite(
dragAndDropResult,
responderProvided,
);
});
await waitFor(() => {

View File

@ -34,5 +34,5 @@ export const useCreateFavorite = () => {
});
};
return createFavorite;
return { createFavorite };
};

View File

@ -28,5 +28,5 @@ export const useCreateFavoriteFolder = () => {
});
};
return createNewFavoriteFolder;
return { createNewFavoriteFolder };
};

View File

@ -10,5 +10,5 @@ export const useDeleteFavorite = () => {
deleteOneRecord(favoriteId);
};
return deleteFavorite;
return { deleteFavorite };
};

View File

@ -1,23 +1,46 @@
import { Favorite } from '@/favorites/types/Favorite';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useReadFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useReadFindManyRecordsQueryInCache';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
import { usePrefetchRunQuery } from '@/prefetch/hooks/internal/usePrefetchRunQuery';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
export const useDeleteFavoriteFolder = () => {
const { deleteOneRecord } = useDeleteOneRecord({
objectNameSingular: CoreObjectNameSingular.FavoriteFolder,
});
const { upsertFavorites, favorites, workspaceFavorites } =
usePrefetchedFavoritesData();
const { upsertRecordsInCache } = usePrefetchRunQuery<Favorite>({
prefetchKey: PrefetchKey.AllFavorites,
});
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular:
PREFETCH_CONFIG[PrefetchKey.AllFavorites].objectNameSingular,
});
const { readFindManyRecordsQueryInCache } =
useReadFindManyRecordsQueryInCache({
objectMetadataItem,
});
const deleteFavoriteFolder = async (folderId: string): Promise<void> => {
await deleteOneRecord(folderId);
const updatedFavorites = [
...favorites.filter((favorite) => favorite.favoriteFolderId !== folderId),
...workspaceFavorites,
];
const allFavorites = readFindManyRecordsQueryInCache<Favorite>({
queryVariables: {},
recordGqlFields: PREFETCH_CONFIG[
PrefetchKey.AllFavorites
].operationSignatureFactory({ objectMetadataItem }).fields,
});
upsertFavorites(updatedFavorites);
const updatedFavorites = allFavorites.filter(
(favorite) => favorite.favoriteFolderId !== folderId,
);
upsertRecordsInCache(updatedFavorites);
};
return {

View File

@ -52,5 +52,5 @@ export const useFavorites = () => {
],
);
return sortedFavorites;
return { sortedFavorites };
};

View File

@ -1,62 +1,30 @@
import { sortFavorites } from '@/favorites/utils/sortFavorites';
import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { View } from '@/views/types/View';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { useFavoritesMetadata } from './useFavoritesMetadata';
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
import { usePrefetchedFavoritesFoldersData } from './usePrefetchedFavoritesFoldersData';
export const useFavoritesByFolder = () => {
const { favorites } = usePrefetchedFavoritesData();
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const getObjectRecordIdentifierByNameSingular =
useGetObjectRecordIdentifierByNameSingular();
const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const favoriteRelationFields = useMemo(
() =>
favoriteObjectMetadataItem.fields.filter(
(fieldMetadataItem) =>
fieldMetadataItem.type === FieldMetadataType.Relation &&
fieldMetadataItem.name !== 'workspaceMember' &&
fieldMetadataItem.name !== 'favoriteFolder',
),
[favoriteObjectMetadataItem.fields],
);
const favoritesByFolder = useMemo(() => {
return favoriteFolders.map((folder) => ({
folderId: folder.id,
folderName: folder.name,
favorites: sortFavorites(
favorites.filter((favorite) => favorite.favoriteFolderId === folder.id),
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
true,
views,
objectMetadataItems,
),
}));
}, [
favoriteFolders,
favorites,
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
const {
views,
objectMetadataItems,
]);
getObjectRecordIdentifierByNameSingular,
favoriteRelationFields,
} = useFavoritesMetadata();
return favoritesByFolder;
const favoritesByFolder = favoriteFolders.map((folder) => ({
folderId: folder.id,
folderName: folder.name,
favorites: sortFavorites(
favorites.filter((favorite) => favorite.favoriteFolderId === folder.id),
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
true,
views,
objectMetadataItems,
),
}));
return { favoritesByFolder };
};

View File

@ -0,0 +1,35 @@
import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { View } from '@/views/types/View';
import { useRecoilValue } from 'recoil';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const useFavoritesMetadata = () => {
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const getObjectRecordIdentifierByNameSingular =
useGetObjectRecordIdentifierByNameSingular();
const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const favoriteRelationFields = favoriteObjectMetadataItem.fields.filter(
(fieldMetadataItem) =>
fieldMetadataItem.type === FieldMetadataType.Relation &&
fieldMetadataItem.name !== 'workspaceMember' &&
fieldMetadataItem.name !== 'favoriteFolder',
);
return {
views,
objectMetadataItems,
getObjectRecordIdentifierByNameSingular,
favoriteRelationFields,
};
};

View File

@ -12,7 +12,7 @@ export const useReorderFavorite = () => {
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const reorderFavorite: OnDragEndResponder = (result) => {
const handleReorderFavorite: OnDragEndResponder = (result) => {
if (!result.destination) return;
const draggedFavoriteId = result.draggableId;
@ -37,5 +37,5 @@ export const useReorderFavorite = () => {
});
};
return reorderFavorite;
return { handleReorderFavorite };
};

View File

@ -1,50 +1,28 @@
import { sortFavorites } from '@/favorites/utils/sortFavorites';
import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { View } from '@/views/types/View';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { useFavoritesMetadata } from './useFavoritesMetadata';
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
export const useSortedFavorites = () => {
const { favorites, workspaceFavorites } = usePrefetchedFavoritesData();
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.Favorite,
});
const getObjectRecordIdentifierByNameSingular =
useGetObjectRecordIdentifierByNameSingular();
const favoriteRelationFieldMetadataItems = useMemo(
() =>
favoriteObjectMetadataItem.fields.filter(
(fieldMetadataItem) =>
fieldMetadataItem.type === FieldMetadataType.Relation &&
fieldMetadataItem.name !== 'workspaceMember' &&
fieldMetadataItem.name !== 'favoriteFolder',
),
[favoriteObjectMetadataItem.fields],
);
const {
views,
objectMetadataItems,
getObjectRecordIdentifierByNameSingular,
favoriteRelationFields,
} = useFavoritesMetadata();
const favoritesSorted = useMemo(() => {
return sortFavorites(
favorites,
favoriteRelationFieldMetadataItems,
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
true,
views,
objectMetadataItems,
);
}, [
favoriteRelationFieldMetadataItems,
favoriteRelationFields,
favorites,
getObjectRecordIdentifierByNameSingular,
views,
@ -54,14 +32,14 @@ export const useSortedFavorites = () => {
const workspaceFavoritesSorted = useMemo(() => {
return sortFavorites(
workspaceFavorites.filter((favorite) => favorite.viewId),
favoriteRelationFieldMetadataItems,
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
false,
views,
objectMetadataItems,
);
}, [
favoriteRelationFieldMetadataItems,
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
workspaceFavorites,
views,

View File

@ -52,5 +52,5 @@ export const useWorkspaceFavorites = () => {
],
);
return sortedWorkspaceFavorites;
return { sortedWorkspaceFavorites };
};