AAU I want to re-order my views with drag & drop (#5002)

### Description
I want to re-order my views with drag & drop

### Refs
#4782 

### Demo
https://jam.dev/c/699ece8a-0467-494a-b9a3-faf666ee9c93

Fixes #4782

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>
Co-authored-by: FellipeMTX <fellipefacdir@gmail.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
gitstart-twenty 2024-05-15 18:57:17 +03:00 committed by GitHub
parent e1eead56c6
commit de228be5ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 17 deletions

View File

@ -17,6 +17,7 @@ export type MenuItemDraggableProps = {
text: string;
isDragDisabled?: boolean;
className?: string;
isIconDisplayedOnHoverOnly?: boolean;
};
export const MenuItemDraggable = ({
LeftIcon,
@ -27,6 +28,7 @@ export const MenuItemDraggable = ({
text,
isDragDisabled = false,
className,
isIconDisplayedOnHoverOnly = true,
}: MenuItemDraggableProps) => {
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
@ -36,6 +38,7 @@ export const MenuItemDraggable = ({
accent={accent}
className={className}
isMenuOpen={!!isTooltipOpen}
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
>
<MenuItemLeftContent
LeftIcon={LeftIcon}

View File

@ -1,17 +1,22 @@
import { MouseEvent } from 'react';
import { MouseEvent, useCallback } from 'react';
import styled from '@emotion/styled';
import { DropResult } from '@hello-pangea/dnd';
import { useSetRecoilState } from 'recoil';
import { IconLock, IconPencil, IconPlus, useIcons } from 'twenty-ui';
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItemDraggable';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useHandleViews } from '@/views/hooks/useHandleViews';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
import { moveArrayItem } from '~/utils/array/moveArrayItem';
import { isDefined } from '~/utils/isDefined';
const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
@ -33,6 +38,8 @@ export const ViewPickerListContent = () => {
const { closeDropdown } = useDropdown(VIEW_PICKER_DROPDOWN_ID);
const { updateView } = useHandleViews();
const handleViewSelect = (viewId: string) => {
selectView(viewId);
closeDropdown();
@ -56,29 +63,73 @@ export const ViewPickerListContent = () => {
const { getIcon } = useIcons();
const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX');
const viewsOnCurrentObjectWithoutIndex = viewsOnCurrentObject.filter(
(view) => view.key !== 'INDEX',
);
const handleDragEnd = useCallback(
(result: DropResult) => {
if (!result.destination) return;
moveArrayItem(viewsOnCurrentObject, {
fromIndex: result.source.index,
toIndex: result.destination.index,
}).forEach((view, index) => {
if (view.position !== index) {
updateView({ ...view, position: index });
}
});
},
[updateView, viewsOnCurrentObject],
);
return (
<>
<DropdownMenuItemsContainer>
{viewsOnCurrentObject.map((view) => (
<DraggableList
onDragEnd={handleDragEnd}
draggableItems={viewsOnCurrentObjectWithoutIndex.map(
(view, index) => (
<DraggableItem
key={view.id}
draggableId={view.id}
index={index}
isDragDisabled={viewsOnCurrentObjectWithoutIndex.length === 1}
itemComponent={
<MenuItemDraggable
key={view.id}
iconButtons={[
{
Icon: IconPencil,
onClick: (event: MouseEvent<HTMLButtonElement>) =>
handleEditViewButtonClick(event, view.id),
},
].filter(isDefined)}
isIconDisplayedOnHoverOnly
onClick={() => handleViewSelect(view.id)}
LeftIcon={getIcon(view.icon)}
text={view.name}
/>
}
/>
),
)}
/>
{indexView && (
<MenuItem
key={view.id}
key={indexView.id}
iconButtons={[
view.key !== 'INDEX'
? {
Icon: IconPencil,
onClick: (event: MouseEvent<HTMLButtonElement>) =>
handleEditViewButtonClick(event, view.id),
}
: {
Icon: IconLock,
},
{
Icon: IconLock,
},
].filter(isDefined)}
isIconDisplayedOnHoverOnly={view.key !== 'INDEX'}
onClick={() => handleViewSelect(view.id)}
LeftIcon={getIcon(view.icon)}
text={view.name}
isIconDisplayedOnHoverOnly={false}
onClick={() => handleViewSelect(indexView.id)}
LeftIcon={getIcon(indexView.icon)}
text={indexView.name}
/>
))}
)}
</DropdownMenuItemsContainer>
<DropdownMenuSeparator />
<StyledBoldDropdownMenuItemsContainer>