mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-29 15:25:45 +03:00
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:
parent
e1eead56c6
commit
de228be5ca
@ -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}
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user