-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
closes - #5755 --------- Co-authored-by: martmull <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> Co-authored-by: Charles Bochet <[email protected]>
- Loading branch information
1 parent
5115022
commit 0125d58
Showing
100 changed files
with
23,995 additions
and
21,450 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
300 changes: 185 additions & 115 deletions
300
packages/twenty-front/src/modules/favorites/components/CurrentWorkspaceMemberFavorites.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,127 +1,197 @@ | ||
import styled from '@emotion/styled'; | ||
import { useRecoilValue } from 'recoil'; | ||
import { Avatar, isDefined } from 'twenty-ui'; | ||
|
||
import { FavoritesSkeletonLoader } from '@/favorites/components/FavoritesSkeletonLoader'; | ||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; | ||
import { FavoriteFolderNavigationDrawerItemDropdown } from '@/favorites/components/FavoriteFolderNavigationDrawerItemDropdown'; | ||
import { FavoriteIcon } from '@/favorites/components/FavoriteIcon'; | ||
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite'; | ||
import { useDeleteFavoriteFolder } from '@/favorites/hooks/useDeleteFavoriteFolder'; | ||
import { useRenameFavoriteFolder } from '@/favorites/hooks/useRenameFavoriteFolder'; | ||
import { useReorderFavorite } from '@/favorites/hooks/useReorderFavorite'; | ||
import { activeFavoriteFolderIdState } from '@/favorites/states/activeFavoriteFolderIdState'; | ||
import { isLocationMatchingFavorite } from '@/favorites/utils/isLocationMatchingFavorite'; | ||
import { ProcessedFavorite } from '@/favorites/utils/sortFavorites'; | ||
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem'; | ||
import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList'; | ||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; | ||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; | ||
import { NavigationDrawerInput } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerInput'; | ||
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; | ||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; | ||
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; | ||
import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; | ||
|
||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; | ||
import { NavigationDrawerAnimatedCollapseWrapper } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerAnimatedCollapseWrapper'; | ||
import { NavigationDrawerItemsCollapsedContainer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsedContainer'; | ||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; | ||
import { useFavorites } from '../hooks/useFavorites'; | ||
|
||
const StyledContainer = styled(NavigationDrawerSection)` | ||
width: 100%; | ||
`; | ||
|
||
const StyledAvatar = styled(Avatar)` | ||
:hover { | ||
cursor: grab; | ||
} | ||
`; | ||
|
||
const StyledNavigationDrawerItem = styled(NavigationDrawerItem)` | ||
:active { | ||
cursor: grabbing; | ||
.fav-avatar:hover { | ||
cursor: grabbing; | ||
} | ||
} | ||
`; | ||
|
||
export const CurrentWorkspaceMemberFavorites = () => { | ||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); | ||
|
||
const { favorites, handleReorderFavorite } = useFavorites(); | ||
const loading = useIsPrefetchLoading(); | ||
const { toggleNavigationSection, isNavigationSectionOpenState } = | ||
useNavigationSection('Favorites'); | ||
const isNavigationSectionOpen = useRecoilValue(isNavigationSectionOpenState); | ||
|
||
if (loading && isDefined(currentWorkspaceMember)) { | ||
return <FavoritesSkeletonLoader />; | ||
} | ||
import { NavigationDrawerItemsCollapsableContainer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer'; | ||
import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; | ||
import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment'; | ||
import { useState } from 'react'; | ||
import { useLocation } from 'react-router-dom'; | ||
import { useRecoilState } from 'recoil'; | ||
import { IconFolder, IconHeartOff, LightIconButton } from 'twenty-ui'; | ||
|
||
type CurrentWorkspaceMemberFavoritesProps = { | ||
folder: { | ||
folderId: string; | ||
folderName: string; | ||
favorites: ProcessedFavorite[]; | ||
}; | ||
isGroup: boolean; | ||
}; | ||
|
||
const currentWorkspaceMemberFavorites = favorites.filter( | ||
(favorite) => favorite.workspaceMemberId === currentWorkspaceMember?.id, | ||
export const CurrentWorkspaceMemberFavorites = ({ | ||
folder, | ||
isGroup, | ||
}: CurrentWorkspaceMemberFavoritesProps) => { | ||
const currentPath = useLocation().pathname; | ||
const currentViewPath = useLocation().pathname + useLocation().search; | ||
|
||
const [isFavoriteFolderRenaming, setIsFavoriteFolderRenaming] = | ||
useState(false); | ||
const [favoriteFolderName, setFavoriteFolderName] = useState( | ||
folder.folderName, | ||
); | ||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||
const [activeFavoriteFolderId, setActiveFavoriteFolderId] = useRecoilState( | ||
activeFavoriteFolderIdState, | ||
); | ||
const isOpen = activeFavoriteFolderId === folder.folderId; | ||
|
||
const handleToggle = () => { | ||
setActiveFavoriteFolderId(isOpen ? null : folder.folderId); | ||
}; | ||
|
||
const { renameFavoriteFolder } = useRenameFavoriteFolder(); | ||
const { deleteFavoriteFolder } = useDeleteFavoriteFolder(); | ||
const { | ||
closeDropdown: closeFavoriteFolderEditDropdown, | ||
isDropdownOpen: isFavoriteFolderEditDropdownOpen, | ||
} = useDropdown(`favorite-folder-edit-${folder.folderId}`); | ||
const selectedFavoriteIndex = folder.favorites.findIndex((favorite) => | ||
isLocationMatchingFavorite(currentPath, currentViewPath, favorite), | ||
); | ||
const handleReorderFavorite = useReorderFavorite(); | ||
|
||
const deleteFavorite = useDeleteFavorite(); | ||
|
||
const favoriteFolderContentLength = folder.favorites.length; | ||
|
||
const handleSubmitRename = async (value: string) => { | ||
if (value === '') return; | ||
await renameFavoriteFolder(folder.folderId, value); | ||
setIsFavoriteFolderRenaming(false); | ||
return true; | ||
}; | ||
|
||
const handleCancelRename = () => { | ||
setFavoriteFolderName(folder.folderName); | ||
setIsFavoriteFolderRenaming(false); | ||
}; | ||
|
||
const handleClickOutside = async ( | ||
event: MouseEvent | TouchEvent, | ||
value: string, | ||
) => { | ||
if (!value) { | ||
setIsFavoriteFolderRenaming(false); | ||
return; | ||
} | ||
|
||
if ( | ||
!currentWorkspaceMemberFavorites || | ||
currentWorkspaceMemberFavorites.length === 0 | ||
) | ||
return <></>; | ||
|
||
const isGroup = currentWorkspaceMemberFavorites.length > 1; | ||
|
||
const draggableListContent = ( | ||
<DraggableList | ||
onDragEnd={handleReorderFavorite} | ||
draggableItems={ | ||
<> | ||
{currentWorkspaceMemberFavorites.map((favorite, index) => { | ||
const { | ||
id, | ||
labelIdentifier, | ||
avatarUrl, | ||
avatarType, | ||
link, | ||
recordId, | ||
} = favorite; | ||
|
||
return ( | ||
<DraggableItem | ||
key={id} | ||
draggableId={id} | ||
index={index} | ||
itemComponent={ | ||
<StyledNavigationDrawerItem | ||
key={id} | ||
label={labelIdentifier} | ||
Icon={() => ( | ||
<StyledAvatar | ||
placeholderColorSeed={recordId} | ||
avatarUrl={avatarUrl} | ||
type={avatarType} | ||
placeholder={labelIdentifier} | ||
className="fav-avatar" | ||
/> | ||
)} | ||
to={link} | ||
/> | ||
} | ||
/> | ||
); | ||
})} | ||
</> | ||
} | ||
await renameFavoriteFolder(folder.folderId, value); | ||
setIsFavoriteFolderRenaming(false); | ||
}; | ||
|
||
const handleFavoriteFolderDelete = async () => { | ||
if (folder.favorites.length > 0) { | ||
setIsDeleteModalOpen(true); | ||
closeFavoriteFolderEditDropdown(); | ||
} else { | ||
await deleteFavoriteFolder(folder.folderId); | ||
closeFavoriteFolderEditDropdown(); | ||
} | ||
}; | ||
|
||
const handleConfirmDelete = async () => { | ||
await deleteFavoriteFolder(folder.folderId); | ||
setIsDeleteModalOpen(false); | ||
}; | ||
|
||
const rightOptions = ( | ||
<FavoriteFolderNavigationDrawerItemDropdown | ||
folderId={folder.folderId} | ||
onRename={() => setIsFavoriteFolderRenaming(true)} | ||
onDelete={handleFavoriteFolderDelete} | ||
closeDropdown={closeFavoriteFolderEditDropdown} | ||
/> | ||
); | ||
|
||
return ( | ||
<StyledContainer> | ||
<NavigationDrawerAnimatedCollapseWrapper> | ||
<NavigationDrawerSectionTitle | ||
label="Favorites" | ||
onClick={() => toggleNavigationSection()} | ||
/> | ||
</NavigationDrawerAnimatedCollapseWrapper> | ||
|
||
{isNavigationSectionOpen && ( | ||
<ScrollWrapper contextProviderName="navigationDrawer"> | ||
<NavigationDrawerItemsCollapsedContainer isGroup={isGroup}> | ||
{draggableListContent} | ||
</NavigationDrawerItemsCollapsedContainer> | ||
</ScrollWrapper> | ||
)} | ||
</StyledContainer> | ||
<> | ||
<NavigationDrawerItemsCollapsableContainer | ||
key={folder.folderId} | ||
isGroup={isGroup} | ||
> | ||
{isFavoriteFolderRenaming ? ( | ||
<NavigationDrawerInput | ||
Icon={IconFolder} | ||
value={favoriteFolderName} | ||
onChange={setFavoriteFolderName} | ||
onSubmit={handleSubmitRename} | ||
onCancel={handleCancelRename} | ||
onClickOutside={handleClickOutside} | ||
hotkeyScope="favorites-folder-input" | ||
/> | ||
) : ( | ||
<NavigationDrawerItem | ||
key={folder.folderId} | ||
label={folder.folderName} | ||
Icon={IconFolder} | ||
onClick={handleToggle} | ||
rightOptions={rightOptions} | ||
className="navigation-drawer-item" | ||
active={isFavoriteFolderEditDropdownOpen} | ||
/> | ||
)} | ||
|
||
{isOpen && ( | ||
<DraggableList | ||
onDragEnd={handleReorderFavorite} | ||
draggableItems={ | ||
<> | ||
{folder.favorites.map((favorite, index) => ( | ||
<DraggableItem | ||
key={favorite.id} | ||
draggableId={favorite.id} | ||
index={index} | ||
itemComponent={ | ||
<NavigationDrawerSubItem | ||
key={favorite.id} | ||
label={favorite.labelIdentifier} | ||
Icon={() => <FavoriteIcon favorite={favorite} />} | ||
to={favorite.link} | ||
active={index === selectedFavoriteIndex} | ||
subItemState={getNavigationSubItemLeftAdornment({ | ||
index, | ||
arrayLength: favoriteFolderContentLength, | ||
selectedIndex: selectedFavoriteIndex, | ||
})} | ||
rightOptions={ | ||
<LightIconButton | ||
Icon={IconHeartOff} | ||
onClick={() => deleteFavorite(favorite.id)} | ||
accent="tertiary" | ||
/> | ||
} | ||
isDraggable | ||
/> | ||
} | ||
/> | ||
))} | ||
</> | ||
} | ||
/> | ||
)} | ||
</NavigationDrawerItemsCollapsableContainer> | ||
|
||
<ConfirmationModal | ||
isOpen={isDeleteModalOpen} | ||
setIsOpen={setIsDeleteModalOpen} | ||
title={`Remove ${folder.favorites.length} ${folder.favorites.length > 1 ? 'favorites' : 'favorite'}?`} | ||
subtitle={`This action will delete this favorite folder ${folder.favorites.length > 1 ? `and all ${folder.favorites.length} favorites` : 'and the favorite'} inside. Do you want to continue?`} | ||
onConfirmClick={handleConfirmDelete} | ||
deleteButtonText="Delete Folder" | ||
/> | ||
</> | ||
); | ||
}; |
Oops, something went wrong.