fix: library multiselect not accounting for published state (#5132)

This commit is contained in:
David Luzar 2022-05-07 19:13:10 +02:00 committed by GitHub
parent 9e8e047aae
commit 65c32b3319
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 61 deletions

View File

@ -25,7 +25,6 @@ import "./LibraryMenu.scss";
import LibraryMenuItems from "./LibraryMenuItems"; import LibraryMenuItems from "./LibraryMenuItems";
import { EVENT } from "../constants"; import { EVENT } from "../constants";
import { KEYS } from "../keys"; import { KEYS } from "../keys";
import { arrayToMap } from "../utils";
import { trackEvent } from "../analytics"; import { trackEvent } from "../analytics";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { jotaiScope } from "../jotai"; import { jotaiScope } from "../jotai";
@ -225,10 +224,6 @@ export const LibraryMenu = ({
[setShowPublishLibraryDialog, setPublishLibSuccess, selectedItems, library], [setShowPublishLibraryDialog, setPublishLibSuccess, selectedItems, library],
); );
const [lastSelectedItem, setLastSelectedItem] = useState<
LibraryItem["id"] | null
>(null);
if ( if (
libraryItemsData.status === "loading" && libraryItemsData.status === "loading" &&
!libraryItemsData.isInitialized !libraryItemsData.isInitialized
@ -284,47 +279,7 @@ export const LibraryMenu = ({
files={files} files={files}
id={id} id={id}
selectedItems={selectedItems} selectedItems={selectedItems}
onToggle={(id, event) => { onSelectItems={(ids) => setSelectedItems(ids)}
const shouldSelect = !selectedItems.includes(id);
if (shouldSelect) {
if (event.shiftKey && lastSelectedItem) {
const rangeStart = libraryItemsData.libraryItems.findIndex(
(item) => item.id === lastSelectedItem,
);
const rangeEnd = libraryItemsData.libraryItems.findIndex(
(item) => item.id === id,
);
if (rangeStart === -1 || rangeEnd === -1) {
setSelectedItems([...selectedItems, id]);
return;
}
const selectedItemsMap = arrayToMap(selectedItems);
const nextSelectedIds = libraryItemsData.libraryItems.reduce(
(acc: LibraryItem["id"][], item, idx) => {
if (
(idx >= rangeStart && idx <= rangeEnd) ||
selectedItemsMap.has(item.id)
) {
acc.push(item.id);
}
return acc;
},
[],
);
setSelectedItems(nextSelectedIds);
} else {
setSelectedItems([...selectedItems, id]);
}
setLastSelectedItem(id);
} else {
setLastSelectedItem(null);
setSelectedItems(selectedItems.filter((_id) => _id !== id));
}
}}
onPublish={() => setShowPublishLibraryDialog(true)} onPublish={() => setShowPublishLibraryDialog(true)}
resetLibrary={resetLibrary} resetLibrary={resetLibrary}
/> />

View File

@ -1,5 +1,5 @@
import { chunk } from "lodash"; import { chunk } from "lodash";
import { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import { importLibraryFromJSON, saveLibraryAsJSON } from "../data/json"; import { importLibraryFromJSON, saveLibraryAsJSON } from "../data/json";
import Library from "../data/library"; import Library from "../data/library";
import { ExcalidrawElement, NonDeleted } from "../element/types"; import { ExcalidrawElement, NonDeleted } from "../element/types";
@ -11,7 +11,7 @@ import {
LibraryItem, LibraryItem,
LibraryItems, LibraryItems,
} from "../types"; } from "../types";
import { muteFSAbortError } from "../utils"; import { arrayToMap, muteFSAbortError } from "../utils";
import { useDeviceType } from "./App"; import { useDeviceType } from "./App";
import ConfirmDialog from "./ConfirmDialog"; import ConfirmDialog from "./ConfirmDialog";
import { exportToFileIcon, load, publishIcon, trash } from "./icons"; import { exportToFileIcon, load, publishIcon, trash } from "./icons";
@ -38,7 +38,7 @@ const LibraryMenuItems = ({
files, files,
id, id,
selectedItems, selectedItems,
onToggle, onSelectItems,
onPublish, onPublish,
resetLibrary, resetLibrary,
}: { }: {
@ -55,7 +55,7 @@ const LibraryMenuItems = ({
library: Library; library: Library;
id: string; id: string;
selectedItems: LibraryItem["id"][]; selectedItems: LibraryItem["id"][];
onToggle: (id: LibraryItem["id"], event: React.MouseEvent) => void; onSelectItems: (id: LibraryItem["id"][]) => void;
onPublish: () => void; onPublish: () => void;
resetLibrary: () => void; resetLibrary: () => void;
}) => { }) => {
@ -192,6 +192,55 @@ const LibraryMenuItems = ({
(id) => libraryItems.find((item) => item.id === id)?.status === "published", (id) => libraryItems.find((item) => item.id === id)?.status === "published",
); );
const [lastSelectedItem, setLastSelectedItem] = useState<
LibraryItem["id"] | null
>(null);
const onItemSelectToggle = (
id: LibraryItem["id"],
event: React.MouseEvent,
) => {
const shouldSelect = !selectedItems.includes(id);
const orderedItems = [...unpublishedItems, ...publishedItems];
if (shouldSelect) {
if (event.shiftKey && lastSelectedItem) {
const rangeStart = orderedItems.findIndex(
(item) => item.id === lastSelectedItem,
);
const rangeEnd = orderedItems.findIndex((item) => item.id === id);
if (rangeStart === -1 || rangeEnd === -1) {
onSelectItems([...selectedItems, id]);
return;
}
const selectedItemsMap = arrayToMap(selectedItems);
const nextSelectedIds = orderedItems.reduce(
(acc: LibraryItem["id"][], item, idx) => {
if (
(idx >= rangeStart && idx <= rangeEnd) ||
selectedItemsMap.has(item.id)
) {
acc.push(item.id);
}
return acc;
},
[],
);
onSelectItems(nextSelectedIds);
} else {
onSelectItems([...selectedItems, id]);
}
setLastSelectedItem(id);
} else {
setLastSelectedItem(null);
onSelectItems(selectedItems.filter((_id) => _id !== id));
}
};
const createLibraryItemCompo = (params: { const createLibraryItemCompo = (params: {
item: item:
| LibraryItem | LibraryItem
@ -212,9 +261,7 @@ const LibraryMenuItems = ({
onClick={params.onClick || (() => {})} onClick={params.onClick || (() => {})}
id={params.item?.id || null} id={params.item?.id || null}
selected={!!params.item?.id && selectedItems.includes(params.item.id)} selected={!!params.item?.id && selectedItems.includes(params.item.id)}
onToggle={(id, event) => { onToggle={onItemSelectToggle}
onToggle(id, event);
}}
/> />
</Stack.Col> </Stack.Col>
); );
@ -272,16 +319,12 @@ const LibraryMenuItems = ({
}); });
}; };
const unpublishedItems = libraryItems.filter(
(item) => item.status !== "published",
);
const publishedItems = libraryItems.filter( const publishedItems = libraryItems.filter(
(item) => item.status === "published", (item) => item.status === "published",
); );
const unpublishedItems = [
// append pending library item
...(pendingElements.length
? [{ id: null, elements: pendingElements }]
: []),
...libraryItems.filter((item) => item.status !== "published"),
];
return ( return (
<div className="library-menu-items-container"> <div className="library-menu-items-container">
@ -310,7 +353,13 @@ const LibraryMenuItems = ({
> >
<> <>
<div className="separator">{t("labels.personalLib")}</div> <div className="separator">{t("labels.personalLib")}</div>
{renderLibrarySection(unpublishedItems)} {renderLibrarySection([
// append pending library item
...(pendingElements.length
? [{ id: null, elements: pendingElements }]
: []),
...unpublishedItems,
])}
</> </>
<> <>