Fix navigation drag drop indicator position (#18515)
Closes [#2295](https://github.com/twentyhq/core-team-issues/issues/2295) --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com> Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
+29
-10
@@ -1,4 +1,5 @@
|
||||
import { type OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useStore } from 'jotai';
|
||||
import { type NavigationMenuItem } from '~/generated-metadata/graphql';
|
||||
|
||||
import { NavigationMenuItemDroppableIds } from '@/navigation-menu-item/constants/NavigationMenuItemDroppableIds';
|
||||
@@ -11,21 +12,15 @@ import {
|
||||
matchesWorkspaceFolderId,
|
||||
validateAndExtractWorkspaceFolderId,
|
||||
} from '@/navigation-menu-item/utils/validateAndExtractWorkspaceFolderId';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { usePrefetchedNavigationMenuItemsData } from './usePrefetchedNavigationMenuItemsData';
|
||||
|
||||
export const useHandleWorkspaceNavigationMenuItemDragAndDrop = () => {
|
||||
const store = useStore();
|
||||
const { workspaceNavigationMenuItems } =
|
||||
usePrefetchedNavigationMenuItemsData();
|
||||
const isNavigationMenuInEditMode = useAtomStateValue(
|
||||
isNavigationMenuInEditModeState,
|
||||
);
|
||||
const navigationMenuItemsDraft = useAtomStateValue(
|
||||
navigationMenuItemsDraftState,
|
||||
);
|
||||
const setNavigationMenuItemsDraft = useSetAtomState(
|
||||
navigationMenuItemsDraftState,
|
||||
);
|
||||
@@ -47,7 +42,9 @@ export const useHandleWorkspaceNavigationMenuItemDragAndDrop = () => {
|
||||
};
|
||||
|
||||
const handleWorkspaceNavigationMenuItemDragAndDrop: OnDragEndResponder = (
|
||||
result,
|
||||
result: Parameters<OnDragEndResponder>[0] & {
|
||||
insertBeforeItemId?: string | null;
|
||||
},
|
||||
) => {
|
||||
const { destination, source, draggableId } = result;
|
||||
|
||||
@@ -70,6 +67,12 @@ export const useHandleWorkspaceNavigationMenuItemDragAndDrop = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const navigationMenuItemsDraft = store.get(
|
||||
navigationMenuItemsDraftState.atom,
|
||||
);
|
||||
const isNavigationMenuInEditMode = store.get(
|
||||
isNavigationMenuInEditModeState.atom,
|
||||
);
|
||||
if (!isNavigationMenuInEditMode || !navigationMenuItemsDraft) {
|
||||
return;
|
||||
}
|
||||
@@ -122,8 +125,24 @@ export const useHandleWorkspaceNavigationMenuItemDragAndDrop = () => {
|
||||
const listWithoutDragged = sourceList.filter(
|
||||
(item) => item.id !== draggableId,
|
||||
);
|
||||
const prevItem = listWithoutDragged[destination.index - 1];
|
||||
const nextItem = listWithoutDragged[destination.index];
|
||||
const sourceIndexInList = sourceList.findIndex(
|
||||
(item) => item.id === draggableId,
|
||||
);
|
||||
const insertBeforeIndex =
|
||||
result.insertBeforeItemId != null
|
||||
? sourceList.findIndex(
|
||||
(item) => item.id === result.insertBeforeItemId,
|
||||
)
|
||||
: -1;
|
||||
const destinationIndexInFullList =
|
||||
insertBeforeIndex >= 0 ? insertBeforeIndex : destination.index;
|
||||
const destIndexInListWithoutDragged =
|
||||
sourceIndexInList < destinationIndexInFullList &&
|
||||
destinationIndexInFullList <= listWithoutDragged.length
|
||||
? destinationIndexInFullList - 1
|
||||
: destinationIndexInFullList;
|
||||
const prevItem = listWithoutDragged[destIndexInListWithoutDragged - 1];
|
||||
const nextItem = listWithoutDragged[destIndexInListWithoutDragged];
|
||||
const newPosition = getPositionBetween(
|
||||
prevItem?.position,
|
||||
nextItem?.position,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { type DragDropProvider } from '@dnd-kit/react';
|
||||
import { isSortable } from '@dnd-kit/react/sortable';
|
||||
import type { ResponderProvided } from '@hello-pangea/dnd';
|
||||
import { type ComponentProps, useCallback, useState } from 'react';
|
||||
import { useStore } from 'jotai';
|
||||
import { type ComponentProps, useCallback, useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ADD_TO_NAV_SOURCE_DROPPABLE_ID } from '@/navigation-menu-item/constants/AddToNavSourceDroppableId';
|
||||
@@ -96,6 +96,7 @@ export const useWorkspaceDndKit = (): {
|
||||
id: string,
|
||||
source: DropDestination,
|
||||
destination: DropDestination,
|
||||
insertBeforeItemId?: string | null,
|
||||
) => {
|
||||
const draggedItem = getNavItemById(id);
|
||||
const destFolderId = validateAndExtractWorkspaceFolderId(
|
||||
@@ -118,7 +119,11 @@ export const useWorkspaceDndKit = (): {
|
||||
);
|
||||
const provided: ResponderProvided = { announce: () => {} };
|
||||
handleWorkspaceNavigationMenuItemDragAndDrop(
|
||||
{ ...result, ...DROP_RESULT_OPTIONS },
|
||||
{
|
||||
...result,
|
||||
...DROP_RESULT_OPTIONS,
|
||||
...(insertBeforeItemId != null && { insertBeforeItemId }),
|
||||
},
|
||||
provided,
|
||||
);
|
||||
};
|
||||
@@ -284,10 +289,14 @@ export const useWorkspaceDndKit = (): {
|
||||
isWorkspaceDroppableId(initialGroupStr) &&
|
||||
isWorkspaceDroppableId(destGroup);
|
||||
if (bothWorkspace) {
|
||||
const insertBeforeItemId = resolved.isTargetFolder
|
||||
? null
|
||||
: String(target?.id ?? '');
|
||||
applyWorkspaceReorderIfAllowed(
|
||||
draggableId,
|
||||
{ droppableId: initialGroupStr, index: initialIndex },
|
||||
resolved.destination,
|
||||
insertBeforeItemId || undefined,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
+38
-28
@@ -26,6 +26,8 @@ import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/us
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
import { styled } from '@linaria/react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const LazyWorkspaceSectionListDndKit = lazy(() =>
|
||||
import(
|
||||
@@ -33,6 +35,10 @@ const LazyWorkspaceSectionListDndKit = lazy(() =>
|
||||
).then((m) => ({ default: m.WorkspaceSectionListDndKit })),
|
||||
);
|
||||
|
||||
const StyledWorkspaceSectionContentGapOffset = styled.div`
|
||||
margin-top: calc(-1 * ${themeCssVariables.betweenSiblingsGap});
|
||||
`;
|
||||
|
||||
type NavigationDrawerSectionForWorkspaceItemsProps = {
|
||||
sectionTitle: string;
|
||||
items: FlatWorkspaceItem[];
|
||||
@@ -150,44 +156,48 @@ export const NavigationDrawerSectionForWorkspaceItems = ({
|
||||
isOpen={isNavigationSectionOpen}
|
||||
/>
|
||||
</NavigationDrawerAnimatedCollapseWrapper>
|
||||
<AnimatedExpandableContainer
|
||||
isExpanded={
|
||||
isNavigationSectionOpen || isAddToNavigationDropTargetVisible
|
||||
}
|
||||
dimension="height"
|
||||
mode="fit-content"
|
||||
containAnimation
|
||||
initial={false}
|
||||
>
|
||||
{isNavigationMenuInEditMode ? (
|
||||
<Suspense
|
||||
fallback={
|
||||
<WorkspaceSectionListEditModeFallback
|
||||
<StyledWorkspaceSectionContentGapOffset>
|
||||
<AnimatedExpandableContainer
|
||||
isExpanded={
|
||||
isNavigationSectionOpen || isAddToNavigationDropTargetVisible
|
||||
}
|
||||
dimension="height"
|
||||
mode="fit-content"
|
||||
containAnimation
|
||||
initial={false}
|
||||
>
|
||||
{isNavigationMenuInEditMode ? (
|
||||
<Suspense
|
||||
fallback={
|
||||
<WorkspaceSectionListEditModeFallback
|
||||
filteredItems={filteredItems}
|
||||
folderChildrenById={folderChildrenById}
|
||||
onActiveObjectMetadataItemClick={
|
||||
onActiveObjectMetadataItemClick
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LazyWorkspaceSectionListDndKit
|
||||
filteredItems={filteredItems}
|
||||
getEditModeProps={getEditModeProps}
|
||||
folderChildrenById={folderChildrenById}
|
||||
selectedNavigationMenuItemId={selectedNavigationMenuItemId}
|
||||
onNavigationMenuItemClick={onNavigationMenuItemClick}
|
||||
onActiveObjectMetadataItemClick={
|
||||
onActiveObjectMetadataItemClick
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LazyWorkspaceSectionListDndKit
|
||||
</Suspense>
|
||||
) : (
|
||||
<NavigationDrawerSectionForWorkspaceItemsListReadOnly
|
||||
filteredItems={filteredItems}
|
||||
getEditModeProps={getEditModeProps}
|
||||
folderChildrenById={folderChildrenById}
|
||||
selectedNavigationMenuItemId={selectedNavigationMenuItemId}
|
||||
onNavigationMenuItemClick={onNavigationMenuItemClick}
|
||||
onActiveObjectMetadataItemClick={onActiveObjectMetadataItemClick}
|
||||
/>
|
||||
</Suspense>
|
||||
) : (
|
||||
<NavigationDrawerSectionForWorkspaceItemsListReadOnly
|
||||
filteredItems={filteredItems}
|
||||
folderChildrenById={folderChildrenById}
|
||||
onActiveObjectMetadataItemClick={onActiveObjectMetadataItemClick}
|
||||
/>
|
||||
)}
|
||||
</AnimatedExpandableContainer>
|
||||
)}
|
||||
</AnimatedExpandableContainer>
|
||||
</StyledWorkspaceSectionContentGapOffset>
|
||||
</NavigationDrawerSection>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-1
@@ -3,7 +3,6 @@ import { WorkspaceDndKitSortableItem } from '@/navigation-menu-item/components/W
|
||||
import { NavigationMenuItemDroppableIds } from '@/navigation-menu-item/constants/NavigationMenuItemDroppableIds';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { NavigationDropTargetContext } from '@/navigation-menu-item/contexts/NavigationDropTargetContext';
|
||||
import { NavigationMenuItemDragContext } from '@/navigation-menu-item/contexts/NavigationMenuItemDragContext';
|
||||
import { useIsDropDisabledForSection } from '@/navigation-menu-item/hooks/useIsDropDisabledForSection';
|
||||
import { isNavigationMenuInEditModeState } from '@/navigation-menu-item/states/isNavigationMenuInEditModeState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
@@ -11,6 +10,7 @@ import { styled } from '@linaria/react';
|
||||
import { useContext } from 'react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
import { NavigationMenuItemDragContext } from '@/navigation-menu-item/contexts/NavigationMenuItemDragContext';
|
||||
import { NavigationDrawerSectionForWorkspaceItemContent } from '@/object-metadata/components/NavigationDrawerSectionForWorkspaceItemContent';
|
||||
import { WorkspaceOrphanDropTarget } from '@/object-metadata/components/WorkspaceOrphanDropTarget';
|
||||
import { WorkspaceSectionAddMenuItemButton } from '@/object-metadata/components/WorkspaceSectionAddMenuItemButton';
|
||||
@@ -20,6 +20,7 @@ const StyledList = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${themeCssVariables.betweenSiblingsGap};
|
||||
padding-top: ${themeCssVariables.betweenSiblingsGap};
|
||||
`;
|
||||
|
||||
const StyledListItemRow = styled.div`
|
||||
|
||||
+1
@@ -10,6 +10,7 @@ const StyledList = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${themeCssVariables.betweenSiblingsGap};
|
||||
padding-top: ${themeCssVariables.betweenSiblingsGap};
|
||||
`;
|
||||
|
||||
type NavigationDrawerSectionForWorkspaceItemsListReadOnlyProps = Pick<
|
||||
|
||||
Reference in New Issue
Block a user