Skip to content

Commit

Permalink
feat: allow drag move many items
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Jul 22, 2024
1 parent bf1f7ab commit 43fe5ef
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 26 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@graasp/chatbox": "3.1.0",
"@graasp/map": "1.16.0",
"@graasp/query-client": "3.16.0",
"@graasp/sdk": "4.19.0",
"@graasp/sdk": "4.20.0",
"@graasp/translations": "1.32.0",
"@graasp/ui": "github:graasp/graasp-ui#card-selection",
"@mui/icons-material": "5.16.4",
Expand Down
4 changes: 3 additions & 1 deletion src/components/item/FolderContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ type Props = {
const Content = ({ item, searchText, items, sortBy }: Props) => {
const { mode } = useLayoutContext();
const { itemTypes } = useFilterItemsContext();
const { selectedIds, toggleSelection } = useSelectionContext();
const { selectedIds, clearSelection, toggleSelection } =
useSelectionContext();

const enableEditing = item.permission
? PermissionLevelCompare.lte(PermissionLevel.Write, item.permission)
Expand All @@ -73,6 +74,7 @@ const Content = ({ item, searchText, items, sortBy }: Props) => {
id={buildItemsTableId(item.id)}
items={items ?? []}
onCardClick={(id) => toggleSelection(id)}
onMove={clearSelection}
/>
{Boolean(enableEditing && !searchText && !itemTypes?.length) && (
<Stack alignItems="center" mb={2}>
Expand Down
60 changes: 45 additions & 15 deletions src/components/main/list/ItemsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';

import { ItemType, PackedItem } from '@graasp/sdk';
import { COMMON } from '@graasp/translations';
import { COMMON, FAILURE_MESSAGES } from '@graasp/translations';
import { Button, DraggingWrapper } from '@graasp/ui';

import {
useBuilderTranslation,
useCommonTranslation,
useEnumsTranslation,
useMessagesTranslation,
} from '@/config/i18n';
import { BUILDER } from '@/langs/constants';

Expand All @@ -33,6 +34,7 @@ export type ItemsTableProps = {
enableMoveInBetween?: boolean;
onCardClick?: (el: string) => void;
selectedIds?: string[];
onMove?: () => void;
};

const ItemsTable = ({
Expand All @@ -43,10 +45,12 @@ const ItemsTable = ({
enableMoveInBetween = true,
selectedIds,
onCardClick,
onMove,
}: ItemsTableProps): JSX.Element => {
const [open, setOpen] = useState(false);
const { t: translateCommon } = useCommonTranslation();
const { t: translateBuilder } = useBuilderTranslation();
const { t: translateMessage } = useMessagesTranslation();
const { t: translateEnums } = useEnumsTranslation();

const { itemId } = useParams();
Expand All @@ -59,7 +63,7 @@ const ItemsTable = ({
const { mutate: moveItems } = mutations.useMoveItems();
const { mutateAsync: uploadItems } = mutations.useUploadFiles();
const [moveData, setMoveData] = useState<{
movedItem: PackedItem;
movedItems: PackedItem[];
to: PackedItem;
}>();

Expand All @@ -71,7 +75,10 @@ const ItemsTable = ({
items: rows,
});

const onDropInRow = (movedItem: PackedItem | any, targetItem: PackedItem) => {
const onDropInRow = (
movedItem: PackedItem | { files: File[] },
targetItem: PackedItem,
) => {
// prevent drop in non-folder item
if (targetItem.type !== ItemType.FOLDER) {
toast.error(
Expand All @@ -83,7 +90,7 @@ const ItemsTable = ({
}

// upload files in item
if (movedItem.files) {
if ('files' in movedItem) {
uploadItems({
files: movedItem.files,
id: targetItem.id,
Expand All @@ -95,21 +102,39 @@ const ItemsTable = ({
.catch((e) => {
close(e);
});
} else if (movedItem.id !== targetItem.id) {
setOpen(true);
setMoveData({ movedItem, to: targetItem });
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))
) {
toast.error(translateMessage(FAILURE_MESSAGES.INVALID_MOVE_TARGET));
return;
}

let movedItems: PackedItem[] = [];
// use selected ids on drag move if moved item is part of selected ids
if (selectedIds?.includes(movedItem?.id)) {
movedItems = rows.filter(({ id }) => selectedIds.includes(id));
} else if (movedItem) {
movedItems = [movedItem];
}
setMoveData({ movedItems, to: targetItem });
setOpen(true);
};

// warning: this won't work anymore with pagination!
const onDropBetweenRow = (
{ files, id }: PackedItem | any,
el: PackedItem | { files: File[] },
previousItem?: PackedItem,
) => {
// upload files at row
if (files) {
if ('files' in el) {
uploadItems({
files,
files: el.files,
id: parentItem?.id,
previousItemId: previousItem?.id,
onUploadProgress: update,
Expand All @@ -124,6 +149,7 @@ const ItemsTable = ({
console.error('cannot move in root');
toast.error(BUILDER.ERROR_MESSAGE);
} else {
const { id } = el;
setMovingId(id);
reorder({
id,
Expand All @@ -137,9 +163,10 @@ const ItemsTable = ({

const handleMoveItems = () => {
if (moveData) {
moveItems({ items: [moveData.movedItem], to: moveData.to.id });
moveItems({ items: moveData.movedItems, to: moveData.to.id });
setMoveData(undefined);
handleClose();
onMove?.();
}
};

Expand Down Expand Up @@ -181,17 +208,20 @@ const ItemsTable = ({
t={translateBuilder}
i18nKey={BUILDER.MOVE_CONFIRM_TITLE}
values={{
name: moveData.movedItem.name,
count: moveData.movedItems.length,
targetName: moveData.to.name,
}}
components={{ 1: <strong /> }}
/>
</DialogTitle>

<DialogContent>
{translateBuilder(BUILDER.MOVE_WARNING, {
name: moveData.movedItem.name,
})}
{translateBuilder(BUILDER.MOVE_WARNING)}
<ul>
{moveData.movedItems.map(({ name, id }) => (
<li key={id}>{name}</li>
))}
</ul>
</DialogContent>
</>
) : (
Expand Down
6 changes: 4 additions & 2 deletions src/components/pages/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
const { itemTypes } = useFilterItemsContext();
const [showOnlyMe, setShowOnlyMe] = useState(false);

const { selectedIds, toggleSelection } = useSelectionContext();
const { selectedIds, toggleSelection, clearSelection } =
useSelectionContext();
const { mode } = useLayoutContext();
const { sortBy, setSortBy, ordering, setOrdering } =
useSorting<SortingOptions>({
Expand Down Expand Up @@ -81,7 +82,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
);
}

if (data && data.pages.length) {
if (data?.pages?.length) {
// default show upload zone
let content = (
<Box mt={2}>
Expand All @@ -101,6 +102,7 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
enableMoveInBetween={false}
onCardClick={toggleSelection}
selectedIds={selectedIds}
onMove={clearSelection}
/>
{!isFetching && data.pages[0].totalCount > totalFetchedItems && (
<Stack textAlign="center" alignItems="center">
Expand Down
5 changes: 3 additions & 2 deletions src/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -463,9 +463,10 @@
"BOOKMARKS_NO_ITEM": "No bookmarked item",
"BOOKMARKS_NO_ITEM_SEARCH": "No bookmarked item for {{search}}",
"UPLOAD_BETWEEN_FILES": "Upload your file(s) here",
"MOVE_WARNING": "This operation might give access to {{name}} to more persons than previously. Do you want to proceed?",
"MOVE_WARNING": "This operation might give access to more persons than previously to the items below. Do you want to proceed?",
"MOVE_IN_NON_FOLDER_ERROR_MESSAGE": "Cannot add items in {{type}}",
"MOVE_CONFIRM_TITLE": "Confirm moving <1>{{name}}</1> inside <1>{{targetName}}</1>",
"MOVE_CONFIRM_TITLE_one": "Confirm moving one item inside <1>{{targetName}}</1>?",
"MOVE_CONFIRM_TITLE": "Confirm moving <1>{{count}}</1> items inside <1>{{targetName}}</1>?",
"ITEM_SEARCH_NOTHING_FOUND": "No item found with these parameters",
"ITEM_SEARCH_NOTHING_FOUND_QUERY_TITLE": "search",
"ITEM_SEARCH_NOTHING_FOUND_TYPES_TITLE": "types",
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1734,9 +1734,9 @@ __metadata:
languageName: node
linkType: hard

"@graasp/sdk@npm:4.19.0":
version: 4.19.0
resolution: "@graasp/sdk@npm:4.19.0"
"@graasp/sdk@npm:4.20.0":
version: 4.20.0
resolution: "@graasp/sdk@npm:4.20.0"
dependencies:
"@faker-js/faker": "npm:8.4.1"
filesize: "npm:10.1.4"
Expand All @@ -1745,7 +1745,7 @@ __metadata:
peerDependencies:
date-fns: ^3
uuid: ^9 || ^10.0.0
checksum: 10/d2fb382f5669ab1b8e265612208d6766672be8b6fa833fe1af8e4f17d2c3f7f384e4bf3f5fd004ec76c8c1ab1ad382c37730477e90ec1ae85b3079ca6a8e68aa
checksum: 10/81e336d68094bcd234b4983217ce9f05d41501032fac00810bf927b8289ef933e18cdfb0e1b0275df6af5a7683b54a8ebf509134aa95b4c7ecfce4a5f313752d
languageName: node
linkType: hard

Expand Down Expand Up @@ -7959,7 +7959,7 @@ __metadata:
"@graasp/chatbox": "npm:3.1.0"
"@graasp/map": "npm:1.16.0"
"@graasp/query-client": "npm:3.16.0"
"@graasp/sdk": "npm:4.19.0"
"@graasp/sdk": "npm:4.20.0"
"@graasp/translations": "npm:1.32.0"
"@graasp/ui": "github:graasp/graasp-ui#card-selection"
"@mui/icons-material": "npm:5.16.4"
Expand Down

0 comments on commit 43fe5ef

Please sign in to comment.