diff --git a/src/components/Libraries/AddToLibraryModal.tsx b/src/components/Libraries/AddToLibraryModal.tsx index e3dd3fa59..21c3f95fe 100644 --- a/src/components/Libraries/AddToLibraryModal.tsx +++ b/src/components/Libraries/AddToLibraryModal.tsx @@ -25,14 +25,21 @@ import { import { FormProvider, useForm } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; -import { LibrarySelector } from './LibrarySelector'; import { useState } from 'react'; import { useStore } from '@/store'; import { parseAPIError } from '@/utils/common/parseAPIError'; import { LibraryIdentifier } from '@/api/biblib/types'; -import { useAddDocumentsByQuery, useAddLibrary, useEditLibraryDocuments } from '@/api/biblib/libraries'; +import { + useAddDocumentsByQuery, + useAddLibrary, + useEditLibraryDocuments, + useGetLibraries, +} from '@/api/biblib/libraries'; +import { ILibraryListTableSort, LibraryListTable } from './LibraryListTable'; +import { NumPerPageType } from '@/types'; +import { TableSkeleton } from './TableSkeleton'; export type SelectionType = 'all' | 'selected'; @@ -57,58 +64,40 @@ export const AddToLibraryModal = ({ const toast = useToast(); - const handleAddToLibrary = (id: LibraryIdentifier) => { - if (bibcodes?.length > 0 || selectedDocs?.length > 0) { - // add selected - editDocs( - { - id, - bibcode: bibcodes ?? selectedDocs, - action: 'add', - }, - { - onSettled(data, error) { - if (error) { - toast({ - status: 'error', - title: 'Error adding to library', - description: parseAPIError(error), - }); - } else { - toast({ - status: 'success', - title: `${data.number_added} papers added to library`, - }); - clearSelections(); - onClose(true); - } - }, - }, - ); - } else { - addDocsByQuery( - { - id, - params: { q: query.q }, - action: 'add', - }, - { - onSettled(data, error) { - if (data) { - toast({ status: 'success', title: `${data.number_added} papers added to library` }); - clearSelections(); - onClose(true); - } else if (error) { - toast({ - status: 'error', - title: 'Error adding to library', - description: parseAPIError(error), - }); - } - }, - }, - ); - } + const handleAddToLibrary = (ids: LibraryIdentifier[]) => { + const promises = + bibcodes?.length > 0 || selectedDocs?.length > 0 + ? ids.map((id) => + editDocs({ + id, + bibcode: bibcodes ?? selectedDocs, + action: 'add', + }), + ) + : ids.map((id) => + addDocsByQuery({ + id, + params: { q: query.q }, + action: 'add', + }), + ); + + Promise.all(promises).then( + () => { + toast({ + status: 'success', + title: `Paper(s) added to ${ids.length > 1 ? 'libraries' : 'library'} `, + }); + clearSelections(); + onClose(true); + }, + () => { + toast({ + status: 'error', + title: 'Error adding to library', + }); + }, + ); }; return ( @@ -121,13 +110,13 @@ export const AddToLibraryModal = ({ {bibcodes ? bibcodes.length : selectedDocs && selectedDocs.length !== 0 ? selectedDocs.length : 'all'}{' '} paper(s) {' '} - to Library + to: - Existing Library + Existing Libraries New Library @@ -159,24 +148,106 @@ const AddToExistingLibraryPane = ({ isLoading, }: { onClose: (added: boolean) => void; - onSubmit: (id: LibraryIdentifier) => void; + onSubmit: (ids: LibraryIdentifier[]) => void; isLoading: boolean; }) => { - const [library, setLibrary] = useState(null); + const [pageSize, setPageSize] = useState(10); + + const [pageIndex, setPageIndex] = useState(0); + + const [sort, setSort] = useState({ col: 'date_last_modified', dir: 'desc' }); + + const [selectedLibs, setSelectedLibs] = useState([]); + + const { data: librariesData, isLoading: isLoadingLibraries } = useGetLibraries( + { + start: pageIndex * pageSize, + rows: pageSize, + sort: sort.col, + order: sort.dir, + }, + { staleTime: 0, cacheTime: 0 }, + ); + + const libraries = librariesData?.libraries ?? []; + + const entries = librariesData?.count ?? 0; + + const handleSortChange = (sort: ILibraryListTableSort) => { + setSort(sort); + setPageIndex(0); + }; + + const handlePageIndexChange = (index: number) => { + setPageIndex(index); + }; + + const handlePageSizeChange = (size: NumPerPageType) => { + setPageSize(size); + setPageIndex(0); + }; + + const handleSelectLibrary = (id: LibraryIdentifier) => { + if (selectedLibs.includes(id)) { + // deselect + setSelectedLibs((prev) => prev.filter((l) => l !== id)); + } else { + // select + setSelectedLibs((prev) => [...prev, id]); + } + }; const handleOnSubmit = () => { - onSubmit(library); + onSubmit(selectedLibs); }; + const handleCancel = () => { - setLibrary(null); + setSelectedLibs([]); onClose(false); }; return ( <> - setLibrary(null)} /> + {isLoading || isLoadingLibraries ? ( + + ) : ( + <> + + {selectedLibs.length === 0 + ? 'No libraries selected' + : `${selectedLibs.length} ${selectedLibs.length > 1 ? 'libraries' : 'library'} selected`}{' '} + {selectedLibs.length > 0 && ( + + )} + + + + )} + -