Procházet zdrojové kódy

Merge pull request #7235 from weseek/feat/gw7912-display-bookmarked-page-under-bookmark-folder

feat: gw7912 display bookmarked page under bookmark folder
Ryoji Shimizu před 3 roky
rodič
revize
170a67644e

+ 47 - 1
packages/app/src/components/Bookmarks/BookmarkFolderItem.tsx

@@ -11,12 +11,16 @@ import CountBadge from '~/components/Common/CountBadge';
 import FolderIcon from '~/components/Icons/FolderIcon';
 import TriangleIcon from '~/components/Icons/TriangleIcon';
 import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
+import { IPageToDeleteWithMeta } from '~/interfaces/page';
+import { OnDeletedFunction } from '~/interfaces/ui';
 import { useSWRBookmarkInfo } from '~/stores/bookmark';
 import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
+import { usePageDeleteModal } from '~/stores/modal';
 import { useSWRxCurrentPage } from '~/stores/page';
 
 import BookmarkFolderItemControl from './BookmarkFolderItemControl';
 import BookmarkFolderNameInput from './BookmarkFolderNameInput';
+import BookmarkItem from './BookmarkItem';
 import DeleteBookmarkFolderModal from './DeleteBookmarkFolderModal';
 
 
@@ -29,7 +33,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
 
   const { t } = useTranslation();
   const {
-    name, _id: folderId, children, parent,
+    name, _id: folderId, children, parent, bookmarks,
   } = bookmarkFolder;
   const [currentChildren, setCurrentChildren] = useState<BookmarkFolderItems[]>();
   const [targetFolder, setTargetFolder] = useState<string | null>(folderId);
@@ -41,6 +45,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
   const [isDeleteFolderModalShown, setIsDeleteFolderModalShown] = useState<boolean>(false);
   const { data: currentPage } = useSWRxCurrentPage();
   const { mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
+  const { open: openDeleteModal } = usePageDeleteModal();
 
   const childCount = useMemo((): number => {
     if (currentChildren != null && currentChildren.length > children.length) {
@@ -133,6 +138,30 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
     setIsCreateAction(true);
   }, [hasChildren, isOpen]);
 
+  const onClickDeleteBookmarkHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
+    const pageDeletedHandler : OnDeletedFunction = (pathOrPathsToDelete, _isRecursively, isCompletely) => {
+      if (typeof pathOrPathsToDelete !== 'string') {
+        return;
+      }
+      const path = pathOrPathsToDelete;
+
+      if (isCompletely) {
+        toastSuccess(t('deleted_pages_completely', { path }));
+      }
+      else {
+        toastSuccess(t('deleted_pages', { path }));
+      }
+      mutateParentBookmarkFolder();
+      mutateBookmarkInfo();
+    };
+    openDeleteModal([pageToDelete], { onDeleted: pageDeletedHandler });
+  }, [mutateBookmarkInfo, mutateParentBookmarkFolder, openDeleteModal, t]);
+
+  const onUnbookmarkHandler = useCallback(() => {
+    mutateParentBookmarkFolder();
+    mutateBookmarkInfo();
+  }, [mutateBookmarkInfo, mutateParentBookmarkFolder]);
+
   const renderChildFolder = () => {
     return isOpen && currentChildren?.map((childFolder) => {
       return (
@@ -146,6 +175,20 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
     });
   };
 
+  const renderBookmarkItem = () => {
+    return isOpen && bookmarks?.map((bookmark) => {
+      return (
+        <BookmarkItem
+          bookmarkedPage={bookmark.page}
+          key={bookmark._id}
+          onUnbookmarked={onUnbookmarkHandler}
+          onRenamed={mutateParentBookmarkFolder}
+          onClickDeleteMenuItem={onClickDeleteBookmarkHandler}
+        />
+      );
+    });
+  };
+
   const onClickRenameHandler = useCallback(() => {
     setIsRenameAction(true);
   }, []);
@@ -233,6 +276,9 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
       {
         renderChildFolder()
       }
+      {
+        renderBookmarkItem()
+      }
       <DeleteBookmarkFolderModal
         bookmarkFolder={bookmarkFolder}
         isOpen={isDeleteFolderModalShown}

+ 13 - 7
packages/app/src/components/Bookmarks/BookmarkFolderMenu.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useCallback, useEffect, useState,
+  useCallback, useState,
 } from 'react';
 
 import { useTranslation } from 'next-i18next';
@@ -32,11 +32,13 @@ const BookmarkFolderMenu = (props: Props): JSX.Element => {
   const { data: currentPage } = useSWRxCurrentPage();
   const { mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
 
+
   const onClickNewBookmarkFolder = useCallback(() => {
     setIsCreateAction(true);
   }, []);
 
-  useEffect(() => {
+  const toggleHandler = useCallback(() => {
+    mutateBookmarkFolderData();
     bookmarkFolders?.forEach((bookmarkFolder) => {
       bookmarkFolder.bookmarks.forEach((bookmark) => {
         if (bookmark.page._id === currentPage?._id) {
@@ -44,7 +46,7 @@ const BookmarkFolderMenu = (props: Props): JSX.Element => {
         }
       });
     });
-  }, [bookmarkFolders, currentPage?._id]);
+  }, [bookmarkFolders, currentPage?._id, mutateBookmarkFolderData]);
 
   const isBookmarkFolderExists = useCallback((): boolean => {
     if (bookmarkFolders && bookmarkFolders.length > 0) {
@@ -69,14 +71,17 @@ const BookmarkFolderMenu = (props: Props): JSX.Element => {
   const onMenuItemClickHandler = useCallback(async(itemId: string) => {
     try {
       await apiv3Post('/bookmark-folder/add-boookmark-to-folder', { pageId: currentPage?._id, folderId: itemId });
-      setSelectedItem(itemId);
+
       mutateBookmarkInfo();
       toastSuccess('Bookmark added to bookmark folder successfully');
     }
     catch (err) {
       toastError(err);
     }
-  }, [currentPage, mutateBookmarkInfo]);
+
+    mutateBookmarkFolderData();
+    setSelectedItem(itemId);
+  }, [currentPage?._id, mutateBookmarkFolderData, mutateBookmarkInfo]);
 
   const renderBookmarkMenuItem = useCallback(() => {
     return (
@@ -102,8 +107,8 @@ const BookmarkFolderMenu = (props: Props): JSX.Element => {
                 {
                   <div className='dropdown-item grw-bookmark-folder-menu-item' tabIndex={0} role="menuitem" onClick={() => onMenuItemClickHandler(folder._id)}>
                     <BookmarkFolderMenuItem
-                      isSelected={selectedItem === folder._id}
                       item={folder}
+                      isSelected={selectedItem === folder._id}
                       onSelectedChild={() => setSelectedItem(null)}
                     />
                   </div>
@@ -120,12 +125,13 @@ const BookmarkFolderMenu = (props: Props): JSX.Element => {
       onClickNewBookmarkFolder,
       onMenuItemClickHandler,
       onPressEnterHandlerForCreate,
-      selectedItem,
       t,
+      selectedItem,
   ]);
 
   return (
     <UncontrolledDropdown
+      onToggle={toggleHandler}
       direction={ isBookmarkFolderExists() ? 'up' : 'down' }
       className='grw-bookmark-folder-dropdown'>
       {children}

+ 20 - 12
packages/app/src/components/Bookmarks/BookmarkFolderMenuItem.tsx

@@ -21,17 +21,18 @@ import BookmarkFolderNameInput from './BookmarkFolderNameInput';
 
 type Props ={
   item: BookmarkFolderItems
-  isSelected: boolean
   onSelectedChild: () => void
+  isSelected: boolean
 }
 const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
   const {
-    item, isSelected,
+    item, isSelected, onSelectedChild,
   } = props;
   const { t } = useTranslation();
   const [isOpen, setIsOpen] = useState(false);
+  const [currentChildFolders, setCurrentChildFolders] = useState<BookmarkFolderItems[]>();
   const { data: childFolders, mutate: mutateChildFolders } = useSWRxBookamrkFolderAndChild(item._id);
-
+  const { mutate: mutateParentFolders } = useSWRxBookamrkFolderAndChild(item.parent);
   const [selectedItem, setSelectedItem] = useState<string | null>(null);
   const [isCreateAction, setIsCreateAction] = useState<boolean>(false);
   const { data: currentPage } = useSWRxCurrentPage();
@@ -50,11 +51,13 @@ const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
 
   }, [item, mutateChildFolders, t]);
 
+
   useEffect(() => {
-    if (isOpen) {
+    if (isOpen && childFolders != null) {
       mutateChildFolders();
+      setCurrentChildFolders(childFolders);
     }
-    childFolders?.forEach((bookmarkFolder) => {
+    currentChildFolders?.forEach((bookmarkFolder) => {
       bookmarkFolder.bookmarks.forEach((bookmark) => {
         if (bookmark.page._id === currentPage?._id) {
           setSelectedItem(bookmarkFolder._id);
@@ -62,7 +65,7 @@ const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
       });
     });
 
-  }, [childFolders, currentPage?._id, isOpen, mutateChildFolders]);
+  }, [childFolders, currentChildFolders, currentPage?._id, isOpen, item, mutateChildFolders, mutateParentFolders]);
 
   const onClickNewBookmarkFolder = useCallback((e) => {
     e.stopPropagation();
@@ -84,16 +87,21 @@ const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
 
   const onClickChildMenuItemHandler = useCallback(async(e, item) => {
     e.stopPropagation();
-    setSelectedItem(item._id);
     mutateBookmarkInfo();
+    onSelectedChild();
     try {
       await apiv3Post('/bookmark-folder/add-boookmark-to-folder', { pageId: currentPage?._id, folderId: item._id });
       toastSuccess('Bookmark added to bookmark folder successfully');
+      mutateParentFolders();
+      mutateChildFolders();
+      setSelectedItem(item._id);
     }
     catch (err) {
       toastError(err);
     }
-  }, [currentPage, mutateBookmarkInfo]);
+
+
+  }, [mutateBookmarkInfo, onSelectedChild, currentPage?._id, mutateParentFolders, mutateChildFolders]);
 
   const renderBookmarkSubMenuItem = useCallback(() => {
     return (
@@ -114,9 +122,9 @@ const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
               </DropdownItem>
             )}
 
-            { childFolders && childFolders?.length > 0 && (<DropdownItem divider />)}
+            { currentChildFolders && currentChildFolders?.length > 0 && (<DropdownItem divider />)}
 
-            {childFolders?.map(child => (
+            {currentChildFolders?.map(child => (
               <div key={child._id} >
 
                 <div
@@ -125,8 +133,8 @@ const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
                   onClick={e => onClickChildMenuItemHandler(e, child)}>
                   <BookmarkFolderMenuItem
                     onSelectedChild={() => setSelectedItem(null)}
-                    isSelected={selectedItem === child._id}
                     item={child}
+                    isSelected={selectedItem === child._id}
                   />
                 </div>
               </div>
@@ -135,7 +143,7 @@ const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
         )}
       </>
     );
-  }, [childFolders, isCreateAction, onClickChildMenuItemHandler, onClickNewBookmarkFolder, onPressEnterHandlerForCreate, selectedItem, t]);
+  }, [childFolders, currentChildFolders, isCreateAction, onClickChildMenuItemHandler, onClickNewBookmarkFolder, onPressEnterHandlerForCreate, selectedItem, t]);
 
   return (
     <UncontrolledDropdown

+ 1 - 1
packages/app/src/components/Bookmarks/BookmarkItem.tsx

@@ -96,7 +96,7 @@ const BookmarkItem = (props: Props): JSX.Element => {
 
   return (
     <div className="grw-foldertree-item-container" key={bookmarkedPage._id}>
-      <li className="bookmark-item-list list-group-item list-group-item-action border-0 py-0 pl-3 d-flex align-items-center" id={bookmarkItemId}>
+      <li className="bookmark-item-list list-group-item list-group-item-action border-0 py-0 pl-5 d-flex align-items-center" id={bookmarkItemId}>
         { isRenameInputShown ? (
           <ClosableTextInput
             value={nodePath.basename(bookmarkedPage.path ?? '')}

+ 0 - 2
packages/app/src/components/Sidebar/Bookmarks/BookmarkContents.tsx

@@ -6,7 +6,6 @@ import { toastError, toastSuccess } from '~/client/util/apiNotification';
 import { apiv3Post } from '~/client/util/apiv3-client';
 import BookmarkFolderNameInput from '~/components/Bookmarks/BookmarkFolderNameInput';
 import BookmarkFolderTree from '~/components/Bookmarks/BookmarkFolderTree';
-import BookmarkItemList from '~/components/Bookmarks/BookmarkItemList';
 import FolderPlusIcon from '~/components/Icons/FolderPlusIcon';
 import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
 
@@ -66,7 +65,6 @@ const BookmarkContents = (): JSX.Element => {
         renderAddNewBookmarkFolder()
       }
       <BookmarkFolderTree />
-      <BookmarkItemList />
     </>
   );
 };