diff --git a/src/components/item/FolderContent.tsx b/src/components/item/FolderContent.tsx
index d0fa2a453..975814933 100644
--- a/src/components/item/FolderContent.tsx
+++ b/src/components/item/FolderContent.tsx
@@ -29,7 +29,10 @@ import {
SelectionContextProvider,
useSelectionContext,
} from '../main/list/SelectionContext';
-import { useDragSelection } from '../main/list/useDragSelection';
+import {
+ DragContainerStack,
+ useDragSelection,
+} from '../main/list/useDragSelection';
import { DesktopMap } from '../map/DesktopMap';
import NoItemFilters from '../pages/NoItemFilters';
import { OutletType } from '../pages/item/type';
@@ -49,6 +52,8 @@ type Props = {
canWrite?: boolean;
};
+const CONTAINER_ID = 'items-container-id';
+
const Content = ({
item,
searchText,
@@ -60,7 +65,7 @@ const Content = ({
const { itemTypes } = useFilterItemsContext();
const { selectedIds, clearSelection, toggleSelection } =
useSelectionContext();
- const DragSelection = useDragSelection();
+ const DragSelection = useDragSelection({ containerId: CONTAINER_ID });
if (mode === ItemLayoutMode.Map) {
return (
@@ -73,24 +78,26 @@ const Content = ({
if (items?.length) {
return (
<>
-
- {Boolean(canWrite && !searchText && !itemTypes?.length) && (
-
-
-
- )}
+
+
+ {Boolean(canWrite && !searchText && !itemTypes?.length) && (
+
+
+
+ )}
+
{DragSelection}
>
);
diff --git a/src/components/main/list/ItemsTable.tsx b/src/components/main/list/ItemsTable.tsx
index a00ea3749..a27cbbb04 100644
--- a/src/components/main/list/ItemsTable.tsx
+++ b/src/components/main/list/ItemsTable.tsx
@@ -105,11 +105,16 @@ const ItemsTable = ({
return;
}
+ // silent error, happens when you want to cancel the operation
+ if (movedItem.id === targetItem.id) {
+ console.error('cannot move target into itself');
+ return;
+ }
+
// cannot move item into itself, or target cannot be part of selection if moving selection
if (
- movedItem.id === targetItem.id ||
- (selectedIds.includes(movedItem?.id) &&
- selectedIds.includes(targetItem.id))
+ selectedIds.includes(movedItem?.id) &&
+ selectedIds.includes(targetItem.id)
) {
toast.error(translateMessage(FAILURE_MESSAGES.INVALID_MOVE_TARGET));
return;
diff --git a/src/components/main/list/SelectionContext.tsx b/src/components/main/list/SelectionContext.tsx
index 4101847a5..7f0da2947 100644
--- a/src/components/main/list/SelectionContext.tsx
+++ b/src/components/main/list/SelectionContext.tsx
@@ -7,6 +7,8 @@ import {
useState,
} from 'react';
+import { Stack } from '@mui/material';
+
type SelectionContextValue = {
selectedIds: string[];
toggleSelection: (id: string) => void;
@@ -74,7 +76,9 @@ export const SelectionContextProvider = ({
return (
- {children}
+
+ {children}
+
);
};
diff --git a/src/components/main/list/useDragSelection.tsx b/src/components/main/list/useDragSelection.tsx
index dea70fbc7..f7b7ee989 100644
--- a/src/components/main/list/useDragSelection.tsx
+++ b/src/components/main/list/useDragSelection.tsx
@@ -1,4 +1,6 @@
-import { useState } from 'react';
+import { ReactNode, useState } from 'react';
+
+import { Stack } from '@mui/material';
import { PRIMARY_COLOR } from '@graasp/ui';
@@ -12,9 +14,35 @@ import { ITEM_CARD_CLASS } from '@/config/selectors';
import { useSelectionContext } from './SelectionContext';
+export const DragContainerStack = ({
+ gap,
+ id,
+ children,
+}: {
+ gap?: number;
+ id: string;
+ children: ReactNode;
+}): JSX.Element => (
+
+ {children}
+
+);
+
export const useDragSelection = ({
elementClass = ITEM_CARD_CLASS,
-} = {}): JSX.Element => {
+ containerId,
+}: {
+ containerId: string;
+ elementClass?: string;
+}): JSX.Element => {
const { addToSelection, clearSelection } = useSelectionContext();
const [boundingBox, setBoundingBox] = useState {
- // does not trigger drag selection if mousedown on card
if (e instanceof HTMLElement || e instanceof SVGElement) {
+ // does not trigger if click is outside of container
+ if (!e.closest(`#${containerId}`)) {
+ return false;
+ }
+
+ // does not trigger drag selection if mousedown on card
return !e?.closest(`.${elementClass}`);
}
return true;
diff --git a/src/components/pages/PageWrapper.tsx b/src/components/pages/PageWrapper.tsx
index 39d0e1bb4..fb3eee150 100644
--- a/src/components/pages/PageWrapper.tsx
+++ b/src/components/pages/PageWrapper.tsx
@@ -19,14 +19,25 @@ const PageWrapper = ({
{title}
-
-
-
- {title}
-
- {options}
+
+
+
+
+ {title}
+
+ {options}
+
+ {children}
- {children}
>
);
diff --git a/src/components/pages/RecycledItemsScreen.tsx b/src/components/pages/RecycledItemsScreen.tsx
index a212266d4..0e219fbaa 100644
--- a/src/components/pages/RecycledItemsScreen.tsx
+++ b/src/components/pages/RecycledItemsScreen.tsx
@@ -21,7 +21,10 @@ import {
SelectionContextProvider,
useSelectionContext,
} from '../main/list/SelectionContext';
-import { useDragSelection } from '../main/list/useDragSelection';
+import {
+ DragContainerStack,
+ useDragSelection,
+} from '../main/list/useDragSelection';
import ItemCard from '../table/ItemCard';
import SortingSelect from '../table/SortingSelect';
import { SortingOptions } from '../table/types';
@@ -29,6 +32,8 @@ import { useSorting, useTranslatedSortingOptions } from '../table/useSorting';
import PageWrapper from './PageWrapper';
import RecycleBinToolbar from './recycleBin/RecycleBinSelectionToolbar';
+const CONTAINER_ID = 'recycle-items-container';
+
const RecycledItemsScreenContent = ({
searchText,
}: {
@@ -52,14 +57,14 @@ const RecycledItemsScreenContent = ({
?.sort(sortFn);
const { selectedIds, toggleSelection } = useSelectionContext();
- const DragSelection = useDragSelection();
+ const DragSelection = useDragSelection({ containerId: CONTAINER_ID });
// render this when there is data from the query
if (recycledItems?.length) {
const hasSelection = selectedIds.length && filteredData?.length;
return (
<>
-
+
)}
- {
- // render the filtered data and when it is empty display that nothing matches the search
- filteredData?.length ? (
- filteredData.map((item) => (
- toggleSelection(item.id)}
- isSelected={selectedIds.includes(item.id)}
- showThumbnail={false}
- allowNavigation={false}
- footer={
-
-
-
-
- }
- />
- ))
- ) : (
-
- {translateBuilder(BUILDER.TRASH_NO_ITEM_SEARCH, {
- search: searchText,
- })}
-
- )
- }
+
+ {
+ // render the filtered data and when it is empty display that nothing matches the search
+ filteredData?.length ? (
+ filteredData.map((item) => (
+ toggleSelection(item.id)}
+ isSelected={selectedIds.includes(item.id)}
+ showThumbnail={false}
+ allowNavigation={false}
+ footer={
+
+
+
+
+ }
+ />
+ ))
+ ) : (
+
+ {translateBuilder(BUILDER.TRASH_NO_ITEM_SEARCH, {
+ search: searchText,
+ })}
+
+ )
+ }
+
{DragSelection}
>
diff --git a/src/components/pages/home/HomeScreen.tsx b/src/components/pages/home/HomeScreen.tsx
index 64fd7b315..4c858b336 100644
--- a/src/components/pages/home/HomeScreen.tsx
+++ b/src/components/pages/home/HomeScreen.tsx
@@ -17,7 +17,10 @@ import {
SelectionContextProvider,
useSelectionContext,
} from '@/components/main/list/SelectionContext';
-import { useDragSelection } from '@/components/main/list/useDragSelection';
+import {
+ DragContainerStack,
+ useDragSelection,
+} from '@/components/main/list/useDragSelection';
import { ITEM_PAGE_SIZE } from '@/config/constants';
import { ShowOnlyMeChangeType } from '@/config/types';
import { ItemLayoutMode, Ordering } from '@/enums';
@@ -46,6 +49,8 @@ import NoItemFilters from '../NoItemFilters';
import PageWrapper from '../PageWrapper';
import HomeSelectionToolbar from './HomeSelectionToolbar';
+const CONTAINER_ID = 'home-items-container';
+
const HomeScreenContent = ({ searchText }: { searchText: string }) => {
const { t: translateBuilder } = useBuilderTranslation();
const { t: translateEnums } = useEnumsTranslation();
@@ -75,7 +80,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
{ pageSize: ITEM_PAGE_SIZE },
);
- const DragSelection = useDragSelection();
+ const DragSelection = useDragSelection({ containerId: CONTAINER_ID });
const onShowOnlyMeChange: ShowOnlyMeChangeType = (checked) => {
setShowOnlyMe(checked);
@@ -105,7 +110,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
? data.pages.map(({ data: d }) => d.length).reduce((a, b) => a + b, 0)
: 0;
content = (
- <>
+
{
)}
- >
+
);
} else if (itemTypes.length || searchText) {
content = ;
@@ -182,7 +187,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
)}
-
+
{content}
{data && isFetching && (