diff options
Diffstat (limited to 'apps/web/components/dashboard/BulkBookmarksAction.tsx')
| -rw-r--r-- | apps/web/components/dashboard/BulkBookmarksAction.tsx | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/apps/web/components/dashboard/BulkBookmarksAction.tsx b/apps/web/components/dashboard/BulkBookmarksAction.tsx index 9e248c03..bad76ff9 100644 --- a/apps/web/components/dashboard/BulkBookmarksAction.tsx +++ b/apps/web/components/dashboard/BulkBookmarksAction.tsx @@ -16,6 +16,7 @@ import { Hash, Link, List, + ListMinus, Pencil, RotateCw, Trash2, @@ -27,6 +28,7 @@ import { useRecrawlBookmark, useUpdateBookmark, } from "@karakeep/shared-react/hooks/bookmarks"; +import { useRemoveBookmarkFromList } from "@karakeep/shared-react/hooks/lists"; import { limitConcurrency } from "@karakeep/shared/concurrency"; import { BookmarkTypes } from "@karakeep/shared/types/bookmarks"; @@ -38,7 +40,11 @@ const MAX_CONCURRENT_BULK_ACTIONS = 50; export default function BulkBookmarksAction() { const { t } = useTranslation(); - const { selectedBookmarks, isBulkEditEnabled } = useBulkActionsStore(); + const { + selectedBookmarks, + isBulkEditEnabled, + listContext: withinListContext, + } = useBulkActionsStore(); const setIsBulkEditEnabled = useBulkActionsStore( (state) => state.setIsBulkEditEnabled, ); @@ -50,6 +56,8 @@ export default function BulkBookmarksAction() { (state) => state.isEverythingSelected, ); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); + const [isRemoveFromListDialogOpen, setIsRemoveFromListDialogOpen] = + useState(false); const [manageListsModal, setManageListsModalOpen] = useState(false); const [bulkTagModal, setBulkTagModalOpen] = useState(false); const pathname = usePathname(); @@ -92,6 +100,13 @@ export default function BulkBookmarksAction() { onError, }); + const removeBookmarkFromListMutator = useRemoveBookmarkFromList({ + onSuccess: () => { + setIsBulkEditEnabled(false); + }, + onError, + }); + interface UpdateBookmarkProps { favourited?: boolean; archived?: boolean; @@ -184,6 +199,31 @@ export default function BulkBookmarksAction() { setIsDeleteDialogOpen(false); }; + const removeBookmarksFromList = async () => { + if (!withinListContext) return; + + const results = await Promise.allSettled( + limitConcurrency( + selectedBookmarks.map( + (item) => () => + removeBookmarkFromListMutator.mutateAsync({ + bookmarkId: item.id, + listId: withinListContext.id, + }), + ), + MAX_CONCURRENT_BULK_ACTIONS, + ), + ); + + const successes = results.filter((r) => r.status === "fulfilled").length; + if (successes > 0) { + toast({ + description: `${successes} bookmarks have been removed from the list!`, + }); + } + setIsRemoveFromListDialogOpen(false); + }; + const alreadyFavourited = selectedBookmarks.length && selectedBookmarks.every((item) => item.favourited === true); @@ -203,6 +243,18 @@ export default function BulkBookmarksAction() { hidden: !isBulkEditEnabled, }, { + name: t("actions.remove_from_list"), + icon: <ListMinus size={18} />, + action: () => setIsRemoveFromListDialogOpen(true), + isPending: removeBookmarkFromListMutator.isPending, + hidden: + !isBulkEditEnabled || + !withinListContext || + withinListContext.type !== "manual" || + (withinListContext.userRole !== "editor" && + withinListContext.userRole !== "owner"), + }, + { name: t("actions.add_to_list"), icon: <List size={18} />, action: () => setManageListsModalOpen(true), @@ -298,6 +350,27 @@ export default function BulkBookmarksAction() { </ActionButton> )} /> + <ActionConfirmingDialog + open={isRemoveFromListDialogOpen} + setOpen={setIsRemoveFromListDialogOpen} + title={"Remove Bookmarks from List"} + description={ + <p> + Are you sure you want to remove {selectedBookmarks.length} bookmarks + from this list? + </p> + } + actionButton={() => ( + <ActionButton + type="button" + variant="destructive" + loading={removeBookmarkFromListMutator.isPending} + onClick={() => removeBookmarksFromList()} + > + {t("actions.remove")} + </ActionButton> + )} + /> <BulkManageListsModal bookmarkIds={selectedBookmarks.map((b) => b.id)} open={manageListsModal} |
