mirror of
https://github.com/lingble/twenty.git
synced 2025-10-29 20:02:29 +00:00
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:
@@ -37,8 +37,8 @@ export const DeleteRecordsActionEffect = ({
|
|||||||
objectNameSingular: objectMetadataItem.nameSingular,
|
objectNameSingular: objectMetadataItem.nameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
const favorites = useFavorites();
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
const deleteFavorite = useDeleteFavorite();
|
const { deleteFavorite } = useDeleteFavorite();
|
||||||
|
|
||||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||||
contextStoreNumberOfSelectedRecordsComponentState,
|
contextStoreNumberOfSelectedRecordsComponentState,
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ export const ManageFavoritesActionEffect = ({
|
|||||||
contextStoreTargetedRecordsRuleComponentState,
|
contextStoreTargetedRecordsRuleComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const favorites = useFavorites();
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
|
|
||||||
const createFavorite = useCreateFavorite();
|
const { createFavorite } = useCreateFavorite();
|
||||||
|
|
||||||
const deleteFavorite = useDeleteFavorite();
|
const { deleteFavorite } = useDeleteFavorite();
|
||||||
|
|
||||||
const selectedRecordId =
|
const selectedRecordId =
|
||||||
contextStoreTargetedRecordsRule.mode === 'selection'
|
contextStoreTargetedRecordsRule.mode === 'selection'
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ export const CurrentWorkspaceMemberFavorites = ({
|
|||||||
const selectedFavoriteIndex = folder.favorites.findIndex((favorite) =>
|
const selectedFavoriteIndex = folder.favorites.findIndex((favorite) =>
|
||||||
isLocationMatchingFavorite(currentPath, currentViewPath, favorite),
|
isLocationMatchingFavorite(currentPath, currentViewPath, favorite),
|
||||||
);
|
);
|
||||||
const handleReorderFavorite = useReorderFavorite();
|
const { handleReorderFavorite } = useReorderFavorite();
|
||||||
|
|
||||||
const deleteFavorite = useDeleteFavorite();
|
const { deleteFavorite } = useDeleteFavorite();
|
||||||
|
|
||||||
const favoriteFolderContentLength = folder.favorites.length;
|
const favoriteFolderContentLength = folder.favorites.length;
|
||||||
|
|
||||||
@@ -154,6 +154,7 @@ export const CurrentWorkspaceMemberFavorites = ({
|
|||||||
key={favorite.id}
|
key={favorite.id}
|
||||||
draggableId={favorite.id}
|
draggableId={favorite.id}
|
||||||
index={index}
|
index={index}
|
||||||
|
isInsideScrollableContainer
|
||||||
itemComponent={
|
itemComponent={
|
||||||
<NavigationDrawerSubItem
|
<NavigationDrawerSubItem
|
||||||
key={favorite.id}
|
key={favorite.id}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { useRecoilState, useRecoilValue } from 'recoil';
|
|||||||
import {
|
import {
|
||||||
IconFolderPlus,
|
IconFolderPlus,
|
||||||
IconHeartOff,
|
IconHeartOff,
|
||||||
isDefined,
|
|
||||||
LightIconButton,
|
LightIconButton,
|
||||||
|
isDefined,
|
||||||
} from 'twenty-ui';
|
} from 'twenty-ui';
|
||||||
|
|
||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
@@ -32,9 +32,9 @@ export const CurrentWorkspaceMemberFavoritesFolders = () => {
|
|||||||
const currentViewPath = useLocation().pathname + useLocation().search;
|
const currentViewPath = useLocation().pathname + useLocation().search;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
const favorites = useFavorites();
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
const deleteFavorite = useDeleteFavorite();
|
const { deleteFavorite } = useDeleteFavorite();
|
||||||
const handleReorderFavorite = useReorderFavorite();
|
const { handleReorderFavorite } = useReorderFavorite();
|
||||||
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
|
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
|
||||||
useRecoilState(isFavoriteFolderCreatingState);
|
useRecoilState(isFavoriteFolderCreatingState);
|
||||||
|
|
||||||
@@ -50,24 +50,25 @@ export const CurrentWorkspaceMemberFavoritesFolders = () => {
|
|||||||
const toggleNewFolder = () => {
|
const toggleNewFolder = () => {
|
||||||
setIsFavoriteFolderCreating((current) => !current);
|
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)) {
|
if (loading && isDefined(currentWorkspaceMember)) {
|
||||||
return <FavoritesSkeletonLoader />;
|
return <FavoritesSkeletonLoader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentWorkspaceMemberFavorites = favorites.filter(
|
const orphanFavorites = favorites.filter(
|
||||||
(favorite) => favorite.workspaceMemberId === currentWorkspaceMember?.id,
|
|
||||||
);
|
|
||||||
|
|
||||||
const orphanFavorites = currentWorkspaceMemberFavorites.filter(
|
|
||||||
(favorite) => !favorite.favoriteFolderId,
|
(favorite) => !favorite.favoriteFolderId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (!shouldDisplayFavorites) {
|
||||||
(!currentWorkspaceMemberFavorites ||
|
|
||||||
currentWorkspaceMemberFavorites.length === 0) &&
|
|
||||||
!isFavoriteFolderCreating
|
|
||||||
) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +105,7 @@ export const CurrentWorkspaceMemberFavoritesFolders = () => {
|
|||||||
key={favorite.id}
|
key={favorite.id}
|
||||||
draggableId={favorite.id}
|
draggableId={favorite.id}
|
||||||
index={index}
|
index={index}
|
||||||
|
isInsideScrollableContainer={true}
|
||||||
itemComponent={
|
itemComponent={
|
||||||
<NavigationDrawerItem
|
<NavigationDrawerItem
|
||||||
key={favorite.id}
|
key={favorite.id}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export const FavoriteFolderNavigationDrawerItemDropdown = ({
|
|||||||
dropdownHotkeyScope={{
|
dropdownHotkeyScope={{
|
||||||
scope: FavoriteFolderHotkeyScope.FavoriteFolderRightIconDropdown,
|
scope: FavoriteFolderHotkeyScope.FavoriteFolderRightIconDropdown,
|
||||||
}}
|
}}
|
||||||
|
usePortal
|
||||||
data-select-disable
|
data-select-disable
|
||||||
clickableComponent={
|
clickableComponent={
|
||||||
<LightIconButton Icon={IconDotsVertical} accent="tertiary" />
|
<LightIconButton Icon={IconDotsVertical} accent="tertiary" />
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ export const FavoriteFolders = ({
|
|||||||
}: FavoriteFoldersProps) => {
|
}: FavoriteFoldersProps) => {
|
||||||
const [newFolderName, setNewFolderName] = useState('');
|
const [newFolderName, setNewFolderName] = useState('');
|
||||||
|
|
||||||
const favoritesByFolder = useFavoritesByFolder();
|
const { favoritesByFolder } = useFavoritesByFolder();
|
||||||
const createFavoriteFolder = useCreateFavoriteFolder();
|
const { createNewFavoriteFolder } = useCreateFavoriteFolder();
|
||||||
|
|
||||||
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
|
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
|
||||||
useRecoilState(isFavoriteFolderCreatingState);
|
useRecoilState(isFavoriteFolderCreatingState);
|
||||||
@@ -33,12 +33,12 @@ export const FavoriteFolders = ({
|
|||||||
|
|
||||||
setIsFavoriteFolderCreating(false);
|
setIsFavoriteFolderCreating(false);
|
||||||
setNewFolderName('');
|
setNewFolderName('');
|
||||||
await createFavoriteFolder(value);
|
await createNewFavoriteFolder(value);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClickOutside = async (
|
const handleClickOutside = async (
|
||||||
event: MouseEvent | TouchEvent,
|
_event: MouseEvent | TouchEvent,
|
||||||
value: string,
|
value: string,
|
||||||
) => {
|
) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@@ -48,7 +48,7 @@ export const FavoriteFolders = ({
|
|||||||
|
|
||||||
setIsFavoriteFolderCreating(false);
|
setIsFavoriteFolderCreating(false);
|
||||||
setNewFolderName('');
|
setNewFolderName('');
|
||||||
await createFavoriteFolder(value);
|
await createNewFavoriteFolder(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancelFavoriteFolderCreation = () => {
|
const handleCancelFavoriteFolderCreation = () => {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import { PageFavoriteButton } from '@/favorites/components/PageFavoriteButton';
|
||||||
import { FavoriteFolderPicker } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPicker';
|
import { FavoriteFolderPicker } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPicker';
|
||||||
import { FavoriteFolderPickerEffect } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPickerEffect';
|
import { FavoriteFolderPickerEffect } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPickerEffect';
|
||||||
import { FavoriteFolderPickerScope } from '@/favorites/favorite-folder-picker/scopes/FavoriteFolderPickerScope';
|
import { FavoriteFolderPickerComponentInstanceContext } from '@/favorites/favorite-folder-picker/scopes/FavoriteFolderPickerScope';
|
||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||||
import { PageFavoriteButton } from '@/ui/layout/page/components/PageFavoriteButton';
|
|
||||||
|
|
||||||
type PageFavoriteFoldersDropdownProps = {
|
type PageFavoriteFoldersDropdownProps = {
|
||||||
dropdownId: string;
|
dropdownId: string;
|
||||||
@@ -23,7 +23,9 @@ export const PageFavoriteFoldersDropdown = ({
|
|||||||
const { closeDropdown } = useDropdown(dropdownId);
|
const { closeDropdown } = useDropdown(dropdownId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FavoriteFolderPickerScope favoriteFoldersScopeId={dropdownId}>
|
<FavoriteFolderPickerComponentInstanceContext
|
||||||
|
favoriteFoldersScopeId={dropdownId}
|
||||||
|
>
|
||||||
<DropdownScope dropdownScopeId={dropdownId}>
|
<DropdownScope dropdownScopeId={dropdownId}>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
dropdownId={dropdownId}
|
dropdownId={dropdownId}
|
||||||
@@ -44,6 +46,6 @@ export const PageFavoriteFoldersDropdown = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</DropdownScope>
|
</DropdownScope>
|
||||||
</FavoriteFolderPickerScope>
|
</FavoriteFolderPickerComponentInstanceContext>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -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;
|
|
||||||
@@ -36,7 +36,7 @@ export const FavoriteFolderPicker = ({
|
|||||||
FavoriteFolderPickerInstanceContext,
|
FavoriteFolderPickerInstanceContext,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { getFoldersByIds, toggleFolderSelection } = useFavoriteFolderPicker({
|
const { favoriteFolders, toggleFolderSelection } = useFavoriteFolderPicker({
|
||||||
record,
|
record,
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
});
|
});
|
||||||
@@ -45,8 +45,7 @@ export const FavoriteFolderPicker = ({
|
|||||||
favoriteFolderSearchFilterComponentState,
|
favoriteFolderSearchFilterComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const folders = getFoldersByIds();
|
const filteredFolders = favoriteFolders.filter((folder) =>
|
||||||
const filteredFolders = folders.filter((folder) =>
|
|
||||||
folder.name
|
folder.name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(favoriteFoldersSearchFilter.toLowerCase()),
|
.includes(favoriteFoldersSearchFilter.toLowerCase()),
|
||||||
@@ -94,7 +93,7 @@ export const FavoriteFolderPicker = ({
|
|||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuItemsContainer hasMaxHeight>
|
||||||
<FavoriteFolderPickerList
|
<FavoriteFolderPickerList
|
||||||
folders={folders}
|
folders={favoriteFolders}
|
||||||
toggleFolderSelection={toggleFolderSelection}
|
toggleFolderSelection={toggleFolderSelection}
|
||||||
/>
|
/>
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const FavoriteFolderPickerEffect = ({
|
|||||||
|
|
||||||
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
|
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
|
||||||
|
|
||||||
const favorites = useFavorites();
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
const setCheckedState = useSetRecoilComponentStateV2(
|
const setCheckedState = useSetRecoilComponentStateV2(
|
||||||
favoriteFolderPickerCheckedComponentState,
|
favoriteFolderPickerCheckedComponentState,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ const StyledFooter = styled.div`
|
|||||||
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledIconPlus = styled(IconPlus)`
|
|
||||||
padding-left: ${({ theme }) => theme.spacing(1)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const FavoriteFolderPickerFooter = () => {
|
export const FavoriteFolderPickerFooter = () => {
|
||||||
const [, setIsFavoriteFolderCreating] = useRecoilState(
|
const [, setIsFavoriteFolderCreating] = useRecoilState(
|
||||||
isFavoriteFolderCreatingState,
|
isFavoriteFolderCreatingState,
|
||||||
@@ -35,7 +31,7 @@ export const FavoriteFolderPickerFooter = () => {
|
|||||||
closeDropdown();
|
closeDropdown();
|
||||||
}}
|
}}
|
||||||
text="Add folder"
|
text="Add folder"
|
||||||
LeftIcon={() => <StyledIconPlus size={theme.icon.size.md} />}
|
LeftIcon={() => <IconPlus size={theme.icon.size.md} />}
|
||||||
/>
|
/>
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
</StyledFooter>
|
</StyledFooter>
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
|
|||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { MenuItem } from 'twenty-ui';
|
import { MenuItem, MenuItemMultiSelect } from 'twenty-ui';
|
||||||
import { FavoriteFolderMenuItemMultiSelect } from './FavoriteFolderMenuItemMultiSelect';
|
|
||||||
|
|
||||||
const StyledItemsContainer = styled.div`
|
const StyledItemsContainer = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -30,6 +29,7 @@ export const FavoriteFolderPickerList = ({
|
|||||||
const [favoriteFoldersSearchFilter] = useRecoilComponentStateV2(
|
const [favoriteFoldersSearchFilter] = useRecoilComponentStateV2(
|
||||||
favoriteFolderSearchFilterComponentState,
|
favoriteFolderSearchFilterComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [favoriteFolderPickerChecked] = useRecoilComponentStateV2(
|
const [favoriteFolderPickerChecked] = useRecoilComponentStateV2(
|
||||||
favoriteFolderPickerCheckedComponentState,
|
favoriteFolderPickerCheckedComponentState,
|
||||||
);
|
);
|
||||||
@@ -47,7 +47,7 @@ export const FavoriteFolderPickerList = ({
|
|||||||
return (
|
return (
|
||||||
<StyledItemsContainer>
|
<StyledItemsContainer>
|
||||||
{showNoFolderOption && (
|
{showNoFolderOption && (
|
||||||
<FavoriteFolderMenuItemMultiSelect
|
<MenuItemMultiSelect
|
||||||
key={`menu-${NO_FOLDER_ID}`}
|
key={`menu-${NO_FOLDER_ID}`}
|
||||||
onSelectChange={() => toggleFolderSelection(NO_FOLDER_ID)}
|
onSelectChange={() => toggleFolderSelection(NO_FOLDER_ID)}
|
||||||
selected={favoriteFolderPickerChecked.includes(NO_FOLDER_ID)}
|
selected={favoriteFolderPickerChecked.includes(NO_FOLDER_ID)}
|
||||||
@@ -60,7 +60,7 @@ export const FavoriteFolderPickerList = ({
|
|||||||
)}
|
)}
|
||||||
{filteredFolders.length > 0
|
{filteredFolders.length > 0
|
||||||
? filteredFolders.map((folder) => (
|
? filteredFolders.map((folder) => (
|
||||||
<FavoriteFolderMenuItemMultiSelect
|
<MenuItemMultiSelect
|
||||||
key={`menu-${folder.id}`}
|
key={`menu-${folder.id}`}
|
||||||
onSelectChange={() => toggleFolderSelection(folder.id)}
|
onSelectChange={() => toggleFolderSelection(folder.id)}
|
||||||
selected={favoriteFolderPickerChecked.includes(folder.id)}
|
selected={favoriteFolderPickerChecked.includes(folder.id)}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { favoriteFolderIdsPickerComponentState } from '@/favorites/favorite-folder-picker/states/favoriteFolderIdPickerComponentState';
|
|
||||||
import { favoriteFolderPickerCheckedComponentState } from '@/favorites/favorite-folder-picker/states/favoriteFolderPickerCheckedComponentState';
|
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 { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
|
||||||
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
|
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
|
||||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||||
@@ -8,7 +7,7 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
|
|||||||
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
|
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
|
||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
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 { useRecoilCallback } from 'recoil';
|
||||||
import { isDefined } from 'twenty-ui';
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
@@ -17,46 +16,26 @@ type useFavoriteFolderPickerProps = {
|
|||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FolderOperations = {
|
type useFavoriteFolderPickerReturnType = {
|
||||||
getFoldersByIds: () => FavoriteFolder[];
|
favoriteFolders: FavoriteFolder[];
|
||||||
toggleFolderSelection: (folderId: string) => Promise<void>;
|
toggleFolderSelection: (folderId: string) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFavoriteFolderPicker = ({
|
export const useFavoriteFolderPicker = ({
|
||||||
record,
|
record,
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
}: useFavoriteFolderPickerProps): FolderOperations => {
|
}: useFavoriteFolderPickerProps): useFavoriteFolderPickerReturnType => {
|
||||||
const [favoriteFolderIdsPicker] = useRecoilComponentStateV2(
|
|
||||||
favoriteFolderIdsPickerComponentState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const favoriteFoldersMultiSelectCheckedState =
|
const favoriteFoldersMultiSelectCheckedState =
|
||||||
useRecoilComponentCallbackStateV2(
|
useRecoilComponentCallbackStateV2(
|
||||||
favoriteFolderPickerCheckedComponentState,
|
favoriteFolderPickerCheckedComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const favoriteFolderPickerFamilyState = useRecoilComponentCallbackStateV2(
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
favoriteFolderPickerComponentFamilyState,
|
const { createFavorite } = useCreateFavorite();
|
||||||
);
|
const { deleteFavorite } = useDeleteFavorite();
|
||||||
|
|
||||||
const favorites = useFavorites();
|
const favoriteFolders = useRecoilComponentValueV2(
|
||||||
const createFavorite = useCreateFavorite();
|
favoriteFoldersComponentSelector,
|
||||||
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 toggleFolderSelection = useRecoilCallback(
|
const toggleFolderSelection = useRecoilCallback(
|
||||||
@@ -123,7 +102,7 @@ export const useFavoriteFolderPicker = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getFoldersByIds,
|
favoriteFolders,
|
||||||
toggleFolderSelection,
|
toggleFolderSelection,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { FavoriteFolderPickerInstanceContext } from '@/favorites/favorite-folder-picker/states/context/FavoriteFolderPickerInstanceContext';
|
import { FavoriteFolderPickerInstanceContext } from '@/favorites/favorite-folder-picker/states/context/FavoriteFolderPickerInstanceContext';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
type FavoriteFolderPickerScopeProps = {
|
type FavoriteFolderPickerComponentInstanceContextProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
favoriteFoldersScopeId: string;
|
favoriteFoldersScopeId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FavoriteFolderPickerScope = ({
|
export const FavoriteFolderPickerComponentInstanceContext = ({
|
||||||
children,
|
children,
|
||||||
favoriteFoldersScopeId,
|
favoriteFoldersScopeId,
|
||||||
}: FavoriteFolderPickerScopeProps) => {
|
}: FavoriteFolderPickerComponentInstanceContextProps) => {
|
||||||
return (
|
return (
|
||||||
<FavoriteFolderPickerInstanceContext.Provider
|
<FavoriteFolderPickerInstanceContext.Provider
|
||||||
value={{ instanceId: favoriteFoldersScopeId }}
|
value={{ instanceId: favoriteFoldersScopeId }}
|
||||||
|
|||||||
@@ -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,
|
|
||||||
});
|
|
||||||
@@ -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));
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -44,7 +44,10 @@ describe('useCreateFavorite', () => {
|
|||||||
{ wrapper: Wrapper },
|
{ wrapper: Wrapper },
|
||||||
);
|
);
|
||||||
|
|
||||||
result.current(favoriteTargetObjectRecord, CoreObjectNameSingular.Person);
|
result.current.createFavorite(
|
||||||
|
favoriteTargetObjectRecord,
|
||||||
|
CoreObjectNameSingular.Person,
|
||||||
|
);
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(mocks[0].result).toHaveBeenCalled();
|
expect(mocks[0].result).toHaveBeenCalled();
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ describe('useDeleteFavorite', () => {
|
|||||||
{ wrapper: Wrapper },
|
{ wrapper: Wrapper },
|
||||||
);
|
);
|
||||||
|
|
||||||
result.current(favoriteId);
|
result.current.deleteFavorite(favoriteId);
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(mocks[1].result).toHaveBeenCalled();
|
expect(mocks[1].result).toHaveBeenCalled();
|
||||||
|
|||||||
@@ -38,6 +38,6 @@ describe('useFavorites', () => {
|
|||||||
{ wrapper: Wrapper },
|
{ wrapper: Wrapper },
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.current).toEqual(sortedFavorites);
|
expect(result.current.sortedFavorites).toEqual(sortedFavorites);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -54,7 +54,10 @@ describe('useReorderFavorite', () => {
|
|||||||
announce: () => {},
|
announce: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
result.current(dragAndDropResult, responderProvided);
|
result.current.handleReorderFavorite(
|
||||||
|
dragAndDropResult,
|
||||||
|
responderProvided,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
|
|||||||
@@ -34,5 +34,5 @@ export const useCreateFavorite = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return createFavorite;
|
return { createFavorite };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,5 +28,5 @@ export const useCreateFavoriteFolder = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return createNewFavoriteFolder;
|
return { createNewFavoriteFolder };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ export const useDeleteFavorite = () => {
|
|||||||
deleteOneRecord(favoriteId);
|
deleteOneRecord(favoriteId);
|
||||||
};
|
};
|
||||||
|
|
||||||
return deleteFavorite;
|
return { deleteFavorite };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
|
import { useReadFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useReadFindManyRecordsQueryInCache';
|
||||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
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 = () => {
|
export const useDeleteFavoriteFolder = () => {
|
||||||
const { deleteOneRecord } = useDeleteOneRecord({
|
const { deleteOneRecord } = useDeleteOneRecord({
|
||||||
objectNameSingular: CoreObjectNameSingular.FavoriteFolder,
|
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> => {
|
const deleteFavoriteFolder = async (folderId: string): Promise<void> => {
|
||||||
await deleteOneRecord(folderId);
|
await deleteOneRecord(folderId);
|
||||||
|
|
||||||
const updatedFavorites = [
|
const allFavorites = readFindManyRecordsQueryInCache<Favorite>({
|
||||||
...favorites.filter((favorite) => favorite.favoriteFolderId !== folderId),
|
queryVariables: {},
|
||||||
...workspaceFavorites,
|
recordGqlFields: PREFETCH_CONFIG[
|
||||||
];
|
PrefetchKey.AllFavorites
|
||||||
|
].operationSignatureFactory({ objectMetadataItem }).fields,
|
||||||
|
});
|
||||||
|
|
||||||
upsertFavorites(updatedFavorites);
|
const updatedFavorites = allFavorites.filter(
|
||||||
|
(favorite) => favorite.favoriteFolderId !== folderId,
|
||||||
|
);
|
||||||
|
|
||||||
|
upsertRecordsInCache(updatedFavorites);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -52,5 +52,5 @@ export const useFavorites = () => {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return sortedFavorites;
|
return { sortedFavorites };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,62 +1,30 @@
|
|||||||
import { sortFavorites } from '@/favorites/utils/sortFavorites';
|
import { sortFavorites } from '@/favorites/utils/sortFavorites';
|
||||||
import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular';
|
import { useFavoritesMetadata } from './useFavoritesMetadata';
|
||||||
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 { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
|
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
|
||||||
import { usePrefetchedFavoritesFoldersData } from './usePrefetchedFavoritesFoldersData';
|
import { usePrefetchedFavoritesFoldersData } from './usePrefetchedFavoritesFoldersData';
|
||||||
|
|
||||||
export const useFavoritesByFolder = () => {
|
export const useFavoritesByFolder = () => {
|
||||||
const { favorites } = usePrefetchedFavoritesData();
|
const { favorites } = usePrefetchedFavoritesData();
|
||||||
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
|
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
|
||||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
const {
|
||||||
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,
|
|
||||||
views,
|
views,
|
||||||
objectMetadataItems,
|
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 };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -12,7 +12,7 @@ export const useReorderFavorite = () => {
|
|||||||
objectNameSingular: CoreObjectNameSingular.Favorite,
|
objectNameSingular: CoreObjectNameSingular.Favorite,
|
||||||
});
|
});
|
||||||
|
|
||||||
const reorderFavorite: OnDragEndResponder = (result) => {
|
const handleReorderFavorite: OnDragEndResponder = (result) => {
|
||||||
if (!result.destination) return;
|
if (!result.destination) return;
|
||||||
|
|
||||||
const draggedFavoriteId = result.draggableId;
|
const draggedFavoriteId = result.draggableId;
|
||||||
@@ -37,5 +37,5 @@ export const useReorderFavorite = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return reorderFavorite;
|
return { handleReorderFavorite };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,50 +1,28 @@
|
|||||||
import { sortFavorites } from '@/favorites/utils/sortFavorites';
|
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 { useMemo } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useFavoritesMetadata } from './useFavoritesMetadata';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
|
||||||
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
|
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
|
||||||
|
|
||||||
export const useSortedFavorites = () => {
|
export const useSortedFavorites = () => {
|
||||||
const { favorites, workspaceFavorites } = usePrefetchedFavoritesData();
|
const { favorites, workspaceFavorites } = usePrefetchedFavoritesData();
|
||||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
const {
|
||||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
views,
|
||||||
const { objectMetadataItem: favoriteObjectMetadataItem } =
|
objectMetadataItems,
|
||||||
useObjectMetadataItem({
|
getObjectRecordIdentifierByNameSingular,
|
||||||
objectNameSingular: CoreObjectNameSingular.Favorite,
|
favoriteRelationFields,
|
||||||
});
|
} = useFavoritesMetadata();
|
||||||
|
|
||||||
const getObjectRecordIdentifierByNameSingular =
|
|
||||||
useGetObjectRecordIdentifierByNameSingular();
|
|
||||||
|
|
||||||
const favoriteRelationFieldMetadataItems = useMemo(
|
|
||||||
() =>
|
|
||||||
favoriteObjectMetadataItem.fields.filter(
|
|
||||||
(fieldMetadataItem) =>
|
|
||||||
fieldMetadataItem.type === FieldMetadataType.Relation &&
|
|
||||||
fieldMetadataItem.name !== 'workspaceMember' &&
|
|
||||||
fieldMetadataItem.name !== 'favoriteFolder',
|
|
||||||
),
|
|
||||||
[favoriteObjectMetadataItem.fields],
|
|
||||||
);
|
|
||||||
|
|
||||||
const favoritesSorted = useMemo(() => {
|
const favoritesSorted = useMemo(() => {
|
||||||
return sortFavorites(
|
return sortFavorites(
|
||||||
favorites,
|
favorites,
|
||||||
favoriteRelationFieldMetadataItems,
|
favoriteRelationFields,
|
||||||
getObjectRecordIdentifierByNameSingular,
|
getObjectRecordIdentifierByNameSingular,
|
||||||
true,
|
true,
|
||||||
views,
|
views,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
favoriteRelationFieldMetadataItems,
|
favoriteRelationFields,
|
||||||
favorites,
|
favorites,
|
||||||
getObjectRecordIdentifierByNameSingular,
|
getObjectRecordIdentifierByNameSingular,
|
||||||
views,
|
views,
|
||||||
@@ -54,14 +32,14 @@ export const useSortedFavorites = () => {
|
|||||||
const workspaceFavoritesSorted = useMemo(() => {
|
const workspaceFavoritesSorted = useMemo(() => {
|
||||||
return sortFavorites(
|
return sortFavorites(
|
||||||
workspaceFavorites.filter((favorite) => favorite.viewId),
|
workspaceFavorites.filter((favorite) => favorite.viewId),
|
||||||
favoriteRelationFieldMetadataItems,
|
favoriteRelationFields,
|
||||||
getObjectRecordIdentifierByNameSingular,
|
getObjectRecordIdentifierByNameSingular,
|
||||||
false,
|
false,
|
||||||
views,
|
views,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
favoriteRelationFieldMetadataItems,
|
favoriteRelationFields,
|
||||||
getObjectRecordIdentifierByNameSingular,
|
getObjectRecordIdentifierByNameSingular,
|
||||||
workspaceFavorites,
|
workspaceFavorites,
|
||||||
views,
|
views,
|
||||||
|
|||||||
@@ -52,5 +52,5 @@ export const useWorkspaceFavorites = () => {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return sortedWorkspaceFavorites;
|
return { sortedWorkspaceFavorites };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,23 +6,20 @@ import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
|||||||
import { CurrentWorkspaceMemberFavoritesFolders } from '@/favorites/components/CurrentWorkspaceMemberFavoritesFolders';
|
import { CurrentWorkspaceMemberFavoritesFolders } from '@/favorites/components/CurrentWorkspaceMemberFavoritesFolders';
|
||||||
import { WorkspaceFavorites } from '@/favorites/components/WorkspaceFavorites';
|
import { WorkspaceFavorites } from '@/favorites/components/WorkspaceFavorites';
|
||||||
import { NavigationDrawerOpenedSection } from '@/object-metadata/components/NavigationDrawerOpenedSection';
|
import { NavigationDrawerOpenedSection } from '@/object-metadata/components/NavigationDrawerOpenedSection';
|
||||||
import { NavigationDrawerSectionForObjectMetadataItemsWrapper } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper';
|
import { RemoteNavigationDrawerSection } from '@/object-metadata/components/RemoteNavigationDrawerSection';
|
||||||
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
||||||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
||||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||||
import { navigationDrawerExpandedMemorizedState } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedState';
|
import { navigationDrawerExpandedMemorizedState } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedState';
|
||||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
|
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const StyledMainSection = styled(NavigationDrawerSection)`
|
const StyledMainSection = styled(NavigationDrawerSection)`
|
||||||
min-height: fit-content;
|
min-height: fit-content;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
`;
|
|
||||||
export const MainNavigationDrawerItems = () => {
|
export const MainNavigationDrawerItems = () => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const { toggleCommandMenu } = useCommandMenu();
|
const { toggleCommandMenu } = useCommandMenu();
|
||||||
@@ -59,15 +56,16 @@ export const MainNavigationDrawerItems = () => {
|
|||||||
/>
|
/>
|
||||||
</StyledMainSection>
|
</StyledMainSection>
|
||||||
)}
|
)}
|
||||||
<StyledContainer>
|
<ScrollWrapper
|
||||||
|
contextProviderName="navigationDrawer"
|
||||||
|
enableXScroll={false}
|
||||||
|
scrollHide={true}
|
||||||
|
>
|
||||||
<NavigationDrawerOpenedSection />
|
<NavigationDrawerOpenedSection />
|
||||||
|
|
||||||
<CurrentWorkspaceMemberFavoritesFolders />
|
<CurrentWorkspaceMemberFavoritesFolders />
|
||||||
|
|
||||||
<WorkspaceFavorites />
|
<WorkspaceFavorites />
|
||||||
|
<RemoteNavigationDrawerSection />
|
||||||
<NavigationDrawerSectionForObjectMetadataItemsWrapper isRemote={true} />
|
</ScrollWrapper>
|
||||||
</StyledContainer>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { View } from '@/views/types/View';
|
|||||||
export const useFilteredObjectMetadataItemsForWorkspaceFavorites = () => {
|
export const useFilteredObjectMetadataItemsForWorkspaceFavorites = () => {
|
||||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||||
|
|
||||||
const workspaceFavorites = useWorkspaceFavorites();
|
const { sortedWorkspaceFavorites: workspaceFavorites } =
|
||||||
|
useWorkspaceFavorites();
|
||||||
|
|
||||||
const workspaceFavoriteIds = new Set(
|
const workspaceFavoriteIds = new Set(
|
||||||
workspaceFavorites.map((favorite) => favorite.recordId),
|
workspaceFavorites.map((favorite) => favorite.recordId),
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { NavigationDrawerAnimatedCollapseWrapper } from '@/ui/navigation/navigat
|
|||||||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
||||||
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
|
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
|
||||||
import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection';
|
import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection';
|
||||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
@@ -78,19 +77,15 @@ export const NavigationDrawerSectionForObjectMetadataItems = ({
|
|||||||
onClick={() => toggleNavigationSection()}
|
onClick={() => toggleNavigationSection()}
|
||||||
/>
|
/>
|
||||||
</NavigationDrawerAnimatedCollapseWrapper>
|
</NavigationDrawerAnimatedCollapseWrapper>
|
||||||
<ScrollWrapper contextProviderName="navigationDrawer">
|
<StyledObjectsMetaDataItemsWrapper>
|
||||||
<StyledObjectsMetaDataItemsWrapper>
|
{isNavigationSectionOpen &&
|
||||||
{isNavigationSectionOpen &&
|
objectMetadataItemsForNavigationItems.map((objectMetadataItem) => (
|
||||||
objectMetadataItemsForNavigationItems.map(
|
<NavigationDrawerItemForObjectMetadataItem
|
||||||
(objectMetadataItem) => (
|
key={`navigation-drawer-item-${objectMetadataItem.id}`}
|
||||||
<NavigationDrawerItemForObjectMetadataItem
|
objectMetadataItem={objectMetadataItem}
|
||||||
key={`navigation-drawer-item-${objectMetadataItem.id}`}
|
/>
|
||||||
objectMetadataItem={objectMetadataItem}
|
))}
|
||||||
/>
|
</StyledObjectsMetaDataItemsWrapper>
|
||||||
),
|
|
||||||
)}
|
|
||||||
</StyledObjectsMetaDataItemsWrapper>
|
|
||||||
</ScrollWrapper>
|
|
||||||
</NavigationDrawerSection>
|
</NavigationDrawerSection>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,16 +7,12 @@ import { NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader } from '@/o
|
|||||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||||
|
|
||||||
export const NavigationDrawerSectionForObjectMetadataItemsWrapper = ({
|
export const RemoteNavigationDrawerSection = () => {
|
||||||
isRemote,
|
|
||||||
}: {
|
|
||||||
isRemote: boolean;
|
|
||||||
}) => {
|
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
|
|
||||||
const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
|
const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
|
||||||
const filteredActiveObjectMetadataItems = activeObjectMetadataItems.filter(
|
const filteredActiveObjectMetadataItems = activeObjectMetadataItems.filter(
|
||||||
(item) => (isRemote ? item.isRemote : !item.isRemote),
|
(item) => item.isRemote,
|
||||||
);
|
);
|
||||||
const loading = useIsPrefetchLoading();
|
const loading = useIsPrefetchLoading();
|
||||||
|
|
||||||
@@ -26,9 +22,9 @@ export const NavigationDrawerSectionForObjectMetadataItemsWrapper = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationDrawerSectionForObjectMetadataItems
|
<NavigationDrawerSectionForObjectMetadataItems
|
||||||
sectionTitle={isRemote ? 'Remote' : 'Workspace'}
|
sectionTitle={'Remote'}
|
||||||
objectMetadataItems={filteredActiveObjectMetadataItems}
|
objectMetadataItems={filteredActiveObjectMetadataItems}
|
||||||
isRemote={isRemote}
|
isRemote={true}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import { Meta, StoryObj } from '@storybook/react';
|
|
||||||
|
|
||||||
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
|
|
||||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
|
||||||
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
|
||||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
|
||||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
|
||||||
|
|
||||||
import { NavigationDrawerSectionForObjectMetadataItemsWrapper } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsWrapper';
|
|
||||||
import { within } from '@storybook/test';
|
|
||||||
import { PrefetchLoadedDecorator } from '~/testing/decorators/PrefetchLoadedDecorator';
|
|
||||||
|
|
||||||
const meta: Meta<typeof NavigationDrawerSectionForObjectMetadataItemsWrapper> =
|
|
||||||
{
|
|
||||||
title:
|
|
||||||
'Modules/ObjectMetadata/NavigationDrawerSectionForObjectMetadataItemsWrapper',
|
|
||||||
component: NavigationDrawerSectionForObjectMetadataItemsWrapper,
|
|
||||||
decorators: [
|
|
||||||
IconsProviderDecorator,
|
|
||||||
ObjectMetadataItemsDecorator,
|
|
||||||
ComponentWithRouterDecorator,
|
|
||||||
ComponentWithRecoilScopeDecorator,
|
|
||||||
SnackBarDecorator,
|
|
||||||
PrefetchLoadedDecorator,
|
|
||||||
],
|
|
||||||
parameters: {
|
|
||||||
msw: graphqlMocks,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
type Story = StoryObj<
|
|
||||||
typeof NavigationDrawerSectionForObjectMetadataItemsWrapper
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const Default: Story = {
|
|
||||||
play: async ({ canvasElement }) => {
|
|
||||||
const canvas = within(canvasElement);
|
|
||||||
await canvas.findByText('People', undefined, { timeout: 10000 });
|
|
||||||
await canvas.findByText('Companies');
|
|
||||||
await canvas.findByText('Opportunities');
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { PageFavoriteFoldersDropdown } from '@/favorites/components/PageFavoriteFolderDropdown';
|
||||||
import { FAVORITE_FOLDER_PICKER_DROPDOWN_ID } from '@/favorites/favorite-folder-picker/constants/FavoriteFolderPickerDropdownId';
|
import { FAVORITE_FOLDER_PICKER_DROPDOWN_ID } from '@/favorites/favorite-folder-picker/constants/FavoriteFolderPickerDropdownId';
|
||||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||||
@@ -8,7 +9,6 @@ import { recordIndexViewTypeState } from '@/object-record/record-index/states/re
|
|||||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||||
import { PageAddButton } from '@/ui/layout/page/components/PageAddButton';
|
import { PageAddButton } from '@/ui/layout/page/components/PageAddButton';
|
||||||
import { PageFavoriteFoldersDropdown } from '@/ui/layout/page/components/PageFavoriteFolderDropdown';
|
|
||||||
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
||||||
import { PageHotkeysEffect } from '@/ui/layout/page/components/PageHotkeysEffect';
|
import { PageHotkeysEffect } from '@/ui/layout/page/components/PageHotkeysEffect';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
@@ -39,7 +39,7 @@ export const RecordIndexPageHeader = () => {
|
|||||||
|
|
||||||
const view = views.find((view) => view.id === currentViewId);
|
const view = views.find((view) => view.id === currentViewId);
|
||||||
|
|
||||||
const favorites = useFavorites();
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
|
|
||||||
const isFavorite = favorites.some(
|
const isFavorite = favorites.some(
|
||||||
(favorite) =>
|
(favorite) =>
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ export const useRecordShowPage = (
|
|||||||
const { objectMetadataItems } = useObjectMetadataItems();
|
const { objectMetadataItems } = useObjectMetadataItems();
|
||||||
const { labelIdentifierFieldMetadataItem } =
|
const { labelIdentifierFieldMetadataItem } =
|
||||||
useLabelIdentifierFieldMetadataItem({ objectNameSingular });
|
useLabelIdentifierFieldMetadataItem({ objectNameSingular });
|
||||||
const favorites = useFavorites();
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
const createFavorite = useCreateFavorite();
|
const { createFavorite } = useCreateFavorite();
|
||||||
const deleteFavorite = useDeleteFavorite();
|
const { deleteFavorite } = useDeleteFavorite();
|
||||||
const setEntityFields = useSetRecoilState(
|
const setEntityFields = useSetRecoilState(
|
||||||
recordStoreFamilyState(objectRecordId),
|
recordStoreFamilyState(objectRecordId),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useEffect } from 'react';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
|
// TODO: Remove this component once we merge it with PrefetchRunQueriesEffect (once we remove feature flag)
|
||||||
export const PrefetchFavoriteFoldersRunQueriesEffect = () => {
|
export const PrefetchFavoriteFoldersRunQueriesEffect = () => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
|
|
||||||
@@ -19,7 +20,6 @@ export const PrefetchFavoriteFoldersRunQueriesEffect = () => {
|
|||||||
|
|
||||||
const { objectMetadataItems } = useObjectMetadataItems();
|
const { objectMetadataItems } = useObjectMetadataItems();
|
||||||
|
|
||||||
// Only include favorite folders operation
|
|
||||||
const operationSignatures = Object.values(PREFETCH_CONFIG)
|
const operationSignatures = Object.values(PREFETCH_CONFIG)
|
||||||
.filter(({ objectNameSingular }) => objectNameSingular === 'favoriteFolder')
|
.filter(({ objectNameSingular }) => objectNameSingular === 'favoriteFolder')
|
||||||
.map(({ objectNameSingular, operationSignatureFactory }) => {
|
.map(({ objectNameSingular, operationSignatureFactory }) => {
|
||||||
|
|||||||
@@ -9,14 +9,10 @@ import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
|
|||||||
import { usePrefetchRunQuery } from '@/prefetch/hooks/internal/usePrefetchRunQuery';
|
import { usePrefetchRunQuery } from '@/prefetch/hooks/internal/usePrefetchRunQuery';
|
||||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||||
import { View } from '@/views/types/View';
|
import { View } from '@/views/types/View';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
export const PrefetchRunQueriesEffect = () => {
|
export const PrefetchRunQueriesEffect = () => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
const isFavoriteFolderEnabled = useIsFeatureEnabled(
|
|
||||||
'IS_FAVORITE_FOLDER_ENABLED',
|
|
||||||
);
|
|
||||||
|
|
||||||
const { upsertRecordsInCache: upsertViewsInCache } =
|
const { upsertRecordsInCache: upsertViewsInCache } =
|
||||||
usePrefetchRunQuery<View>({
|
usePrefetchRunQuery<View>({
|
||||||
@@ -33,7 +29,7 @@ export const PrefetchRunQueriesEffect = () => {
|
|||||||
const operationSignatures = Object.values(PREFETCH_CONFIG)
|
const operationSignatures = Object.values(PREFETCH_CONFIG)
|
||||||
.filter(
|
.filter(
|
||||||
({ objectNameSingular }) =>
|
({ objectNameSingular }) =>
|
||||||
// Exclude favorite folders as they're handled separately
|
// TODO: Remove this filter once we merge PrefetchFavortiteFoldersRunQueriesEffect with this component
|
||||||
objectNameSingular !== 'favoriteFolder',
|
objectNameSingular !== 'favoriteFolder',
|
||||||
)
|
)
|
||||||
.map(({ objectNameSingular, operationSignatureFactory }) => {
|
.map(({ objectNameSingular, operationSignatureFactory }) => {
|
||||||
@@ -57,12 +53,7 @@ export const PrefetchRunQueriesEffect = () => {
|
|||||||
if (isDefined(result.favorites)) {
|
if (isDefined(result.favorites)) {
|
||||||
upsertFavoritesInCache(result.favorites as Favorite[]);
|
upsertFavoritesInCache(result.favorites as Favorite[]);
|
||||||
}
|
}
|
||||||
}, [
|
}, [result, upsertViewsInCache, upsertFavoritesInCache]);
|
||||||
result,
|
|
||||||
upsertViewsInCache,
|
|
||||||
upsertFavoritesInCache,
|
|
||||||
isFavoriteFolderEnabled,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
|
|
||||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
export const useIsFavoriteFoldersPrefetchLoading = () => {
|
|
||||||
const areFavoritesFolderPrefetched = useRecoilValue(
|
|
||||||
prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
|
|
||||||
);
|
|
||||||
|
|
||||||
return !areFavoritesFolderPrefetched;
|
|
||||||
};
|
|
||||||
@@ -2,13 +2,14 @@ import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedF
|
|||||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useIsFavoriteFoldersPrefetchLoading } from './useIsFavoriteFoldersPrefetchLoading';
|
|
||||||
|
|
||||||
export const useIsPrefetchLoading = () => {
|
export const useIsPrefetchLoading = () => {
|
||||||
const isFavoriteFolderEnabled = useIsFeatureEnabled(
|
const isFavoriteFolderEnabled = useIsFeatureEnabled(
|
||||||
'IS_FAVORITE_FOLDER_ENABLED',
|
'IS_FAVORITE_FOLDER_ENABLED',
|
||||||
);
|
);
|
||||||
const isFavoriteFoldersLoading = useIsFavoriteFoldersPrefetchLoading();
|
const isFavoriteFoldersPrefetched = useRecoilValue(
|
||||||
|
prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
|
||||||
|
);
|
||||||
|
|
||||||
const areViewsPrefetched = useRecoilValue(
|
const areViewsPrefetched = useRecoilValue(
|
||||||
prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
|
prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
|
||||||
@@ -20,6 +21,6 @@ export const useIsPrefetchLoading = () => {
|
|||||||
return (
|
return (
|
||||||
!areViewsPrefetched ||
|
!areViewsPrefetched ||
|
||||||
!areFavoritesPrefetched ||
|
!areFavoritesPrefetched ||
|
||||||
(isFavoriteFolderEnabled && isFavoriteFoldersLoading)
|
(isFavoriteFolderEnabled && !isFavoriteFoldersPrefetched)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import {
|
import {
|
||||||
DragDropContext,
|
DragDropContext,
|
||||||
Droppable,
|
Droppable,
|
||||||
OnDragEndResponder,
|
OnDragEndResponder,
|
||||||
} from '@hello-pangea/dnd';
|
} from '@hello-pangea/dnd';
|
||||||
|
import { useState } from 'react';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
type DraggableListProps = {
|
type DraggableListProps = {
|
||||||
draggableItems: React.ReactNode;
|
draggableItems: React.ReactNode;
|
||||||
|
|||||||
@@ -23,12 +23,17 @@ const StyledScrollWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledInnerContainer = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
`;
|
||||||
|
|
||||||
export type ScrollWrapperProps = {
|
export type ScrollWrapperProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
enableXScroll?: boolean;
|
enableXScroll?: boolean;
|
||||||
enableYScroll?: boolean;
|
enableYScroll?: boolean;
|
||||||
contextProviderName: ContextProviderName;
|
contextProviderName: ContextProviderName;
|
||||||
|
scrollHide?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ScrollWrapper = ({
|
export const ScrollWrapper = ({
|
||||||
@@ -37,6 +42,7 @@ export const ScrollWrapper = ({
|
|||||||
enableXScroll = true,
|
enableXScroll = true,
|
||||||
enableYScroll = true,
|
enableYScroll = true,
|
||||||
contextProviderName,
|
contextProviderName,
|
||||||
|
scrollHide = false,
|
||||||
}: ScrollWrapperProps) => {
|
}: ScrollWrapperProps) => {
|
||||||
const scrollableRef = useRef<HTMLDivElement>(null);
|
const scrollableRef = useRef<HTMLDivElement>(null);
|
||||||
const Context = getContextByProviderName(contextProviderName);
|
const Context = getContextByProviderName(contextProviderName);
|
||||||
@@ -55,7 +61,10 @@ export const ScrollWrapper = ({
|
|||||||
|
|
||||||
const [initialize, instance] = useOverlayScrollbars({
|
const [initialize, instance] = useOverlayScrollbars({
|
||||||
options: {
|
options: {
|
||||||
scrollbars: { autoHide: 'scroll' },
|
scrollbars: {
|
||||||
|
autoHide: scrollHide ? 'scroll' : 'never',
|
||||||
|
visibility: scrollHide ? 'hidden' : 'visible',
|
||||||
|
},
|
||||||
overflow: {
|
overflow: {
|
||||||
x: enableXScroll ? undefined : 'hidden',
|
x: enableXScroll ? undefined : 'hidden',
|
||||||
y: enableYScroll ? undefined : 'hidden',
|
y: enableYScroll ? undefined : 'hidden',
|
||||||
@@ -84,7 +93,7 @@ export const ScrollWrapper = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StyledScrollWrapper ref={scrollableRef} className={className}>
|
<StyledScrollWrapper ref={scrollableRef} className={className}>
|
||||||
{children}
|
<StyledInnerContainer>{children}</StyledInnerContainer>
|
||||||
</StyledScrollWrapper>
|
</StyledScrollWrapper>
|
||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { PageFavoriteButton } from '@/favorites/components/PageFavoriteButton';
|
||||||
|
import { PageFavoriteFoldersDropdown } from '@/favorites/components/PageFavoriteFolderDropdown';
|
||||||
import { FAVORITE_FOLDER_PICKER_DROPDOWN_ID } from '@/favorites/favorite-folder-picker/constants/FavoriteFolderPickerDropdownId';
|
import { FAVORITE_FOLDER_PICKER_DROPDOWN_ID } from '@/favorites/favorite-folder-picker/constants/FavoriteFolderPickerDropdownId';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { PageFavoriteButton } from '@/ui/layout/page/components/PageFavoriteButton';
|
|
||||||
import { PageFavoriteFoldersDropdown } from '@/ui/layout/page/components/PageFavoriteFolderDropdown';
|
|
||||||
import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton';
|
import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton';
|
||||||
import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton';
|
import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
|
|||||||
Reference in New Issue
Block a user