aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/BulkBookmarksAction.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/components/dashboard/BulkBookmarksAction.tsx')
-rw-r--r--apps/web/components/dashboard/BulkBookmarksAction.tsx75
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}