Navbar drag drop using dnd kit (#18288)
This commit is contained in:
+58
-31
@@ -1,66 +1,78 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import type { NavigationMenuItem } from '~/generated-metadata/graphql';
|
||||
|
||||
import { navigationMenuItemsDraftState } from '@/navigation-menu-item/states/navigationMenuItemsDraftState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { getPositionBetween } from '@/navigation-menu-item/utils/getPositionBetween';
|
||||
import { isNavigationMenuItemFolder } from '@/navigation-menu-item/utils/isNavigationMenuItemFolder';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
|
||||
const swapPositionsInDraft = (
|
||||
draft: NavigationMenuItem[],
|
||||
itemA: NavigationMenuItem,
|
||||
itemB: NavigationMenuItem,
|
||||
): NavigationMenuItem[] =>
|
||||
draft.map((item) => {
|
||||
if (item.id === itemA.id) {
|
||||
return { ...item, position: itemB.position };
|
||||
}
|
||||
if (item.id === itemB.id) {
|
||||
return { ...item, position: itemA.position };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
import { useWorkspaceSectionItems } from './useWorkspaceSectionItems';
|
||||
|
||||
export const useNavigationMenuItemMoveRemove = () => {
|
||||
const setNavigationMenuItemsDraft = useSetAtomState(
|
||||
navigationMenuItemsDraftState,
|
||||
);
|
||||
const items = useWorkspaceSectionItems();
|
||||
const visibleItemIds = new Set(items.map((item) => item.id));
|
||||
|
||||
const moveUp = (navigationMenuItemId: string) => {
|
||||
setNavigationMenuItemsDraft((draft) => {
|
||||
if (!draft) return draft;
|
||||
if (!draft) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const currentItem = draft.find(
|
||||
(item) => item.id === navigationMenuItemId,
|
||||
);
|
||||
if (!currentItem) return draft;
|
||||
if (!currentItem) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const folderId = currentItem.folderId ?? null;
|
||||
const siblings = draft
|
||||
.filter((item) => (item.folderId ?? null) === folderId)
|
||||
.filter(
|
||||
(item) =>
|
||||
(item.folderId ?? null) === folderId && visibleItemIds.has(item.id),
|
||||
)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
|
||||
const currentIndex = siblings.findIndex(
|
||||
(item) => item.id === navigationMenuItemId,
|
||||
);
|
||||
if (currentIndex <= 0) return draft;
|
||||
if (currentIndex <= 0) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const itemAbove = siblings[currentIndex - 1];
|
||||
return swapPositionsInDraft(draft, currentItem, itemAbove);
|
||||
const prev = siblings[currentIndex - 1];
|
||||
const prevPrev = siblings[currentIndex - 2];
|
||||
const newPosition = getPositionBetween(prevPrev?.position, prev.position);
|
||||
|
||||
return draft.map((item) =>
|
||||
item.id === navigationMenuItemId
|
||||
? { ...item, position: newPosition }
|
||||
: item,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const moveDown = (navigationMenuItemId: string) => {
|
||||
setNavigationMenuItemsDraft((draft) => {
|
||||
if (!draft) return draft;
|
||||
if (!draft) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const currentItem = draft.find(
|
||||
(item) => item.id === navigationMenuItemId,
|
||||
);
|
||||
if (!currentItem) return draft;
|
||||
if (!currentItem) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const folderId = currentItem.folderId ?? null;
|
||||
const siblings = draft
|
||||
.filter((item) => (item.folderId ?? null) === folderId)
|
||||
.filter(
|
||||
(item) =>
|
||||
(item.folderId ?? null) === folderId && visibleItemIds.has(item.id),
|
||||
)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
|
||||
const currentIndex = siblings.findIndex(
|
||||
@@ -70,19 +82,30 @@ export const useNavigationMenuItemMoveRemove = () => {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const itemBelow = siblings[currentIndex + 1];
|
||||
return swapPositionsInDraft(draft, currentItem, itemBelow);
|
||||
const next = siblings[currentIndex + 1];
|
||||
const nextNext = siblings[currentIndex + 2];
|
||||
const newPosition = getPositionBetween(next.position, nextNext?.position);
|
||||
|
||||
return draft.map((item) =>
|
||||
item.id === navigationMenuItemId
|
||||
? { ...item, position: newPosition }
|
||||
: item,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const remove = (navigationMenuItemId: string) => {
|
||||
setNavigationMenuItemsDraft((draft) => {
|
||||
if (!draft) return draft;
|
||||
if (!draft) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const itemToRemove = draft.find(
|
||||
(item) => item.id === navigationMenuItemId,
|
||||
);
|
||||
if (!itemToRemove) return draft;
|
||||
if (!itemToRemove) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const isFolder = isNavigationMenuItemFolder(itemToRemove);
|
||||
|
||||
@@ -103,10 +126,14 @@ export const useNavigationMenuItemMoveRemove = () => {
|
||||
targetFolderId: string | null,
|
||||
) => {
|
||||
setNavigationMenuItemsDraft((draft) => {
|
||||
if (!draft) return draft;
|
||||
if (!draft) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const itemToMove = draft.find((item) => item.id === navigationMenuItemId);
|
||||
if (!itemToMove) return draft;
|
||||
if (!itemToMove) {
|
||||
return draft;
|
||||
}
|
||||
|
||||
const isFolder = isNavigationMenuItemFolder(itemToMove);
|
||||
if (isFolder && targetFolderId === navigationMenuItemId) {
|
||||
|
||||
Reference in New Issue
Block a user