Просмотр исходного кода

refactor bookmark menu and bookmark list

ryoji-s 2 лет назад
Родитель
Сommit
0829cfc3eb

+ 52 - 12
apps/app/src/components/Bookmarks/BookmarkFolderMenu.tsx

@@ -10,8 +10,10 @@ import {
 import { addBookmarkToFolder, addNewFolder, toggleBookmark } from '~/client/util/bookmark-utils';
 import { addBookmarkToFolder, addNewFolder, toggleBookmark } from '~/client/util/bookmark-utils';
 import { toastError } from '~/client/util/toastr';
 import { toastError } from '~/client/util/toastr';
 import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
 import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
+import { onDeletedBookmarkFolderFunction } from '~/interfaces/ui';
 import { useSWRBookmarkInfo, useSWRxCurrentUserBookmarks } from '~/stores/bookmark';
 import { useSWRBookmarkInfo, useSWRxCurrentUserBookmarks } from '~/stores/bookmark';
 import { useSWRxBookmarkFolderAndChild } from '~/stores/bookmark-folder';
 import { useSWRxBookmarkFolderAndChild } from '~/stores/bookmark-folder';
+import { useBookmarkFolderDeleteModal } from '~/stores/modal';
 import { useSWRxCurrentPage, useSWRxPageInfo } from '~/stores/page';
 import { useSWRxCurrentPage, useSWRxPageInfo } from '~/stores/page';
 
 
 import { FolderIcon } from '../Icons/FolderIcon';
 import { FolderIcon } from '../Icons/FolderIcon';
@@ -31,6 +33,7 @@ export const BookmarkFolderMenu: React.FC<{children?: React.ReactNode}> = ({ chi
   const { data: bookmarkInfo, mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
   const { data: bookmarkInfo, mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
   const { mutate: mutateUserBookmarks } = useSWRxCurrentUserBookmarks();
   const { mutate: mutateUserBookmarks } = useSWRxCurrentUserBookmarks();
   const { mutate: mutatePageInfo } = useSWRxPageInfo(currentPage?._id);
   const { mutate: mutatePageInfo } = useSWRxPageInfo(currentPage?._id);
+  const { open: openDeleteBookmarkFolderModal } = useBookmarkFolderDeleteModal();
 
 
   const isBookmarked = bookmarkInfo?.isBookmarked ?? false;
   const isBookmarked = bookmarkInfo?.isBookmarked ?? false;
 
 
@@ -99,9 +102,9 @@ export const BookmarkFolderMenu: React.FC<{children?: React.ReactNode}> = ({ chi
     return bookmarkFolders != null && bookmarkFolders.length > 0;
     return bookmarkFolders != null && bookmarkFolders.length > 0;
   }, [bookmarkFolders]);
   }, [bookmarkFolders]);
 
 
-  const onPressEnterHandlerForCreate = useCallback(async(folderName: string) => {
+  const onPressEnterHandlerForCreate = useCallback(async(folderName: string, item?: BookmarkFolderItems) => {
     try {
     try {
-      await addNewFolder(folderName, null);
+      await addNewFolder(folderName, item ? item._id : null);
       await mutateBookmarkFolders();
       await mutateBookmarkFolders();
       setIsCreateAction(false);
       setIsCreateAction(false);
     }
     }
@@ -129,6 +132,47 @@ export const BookmarkFolderMenu: React.FC<{children?: React.ReactNode}> = ({ chi
     setSelectedItem(itemId);
     setSelectedItem(itemId);
   }, [mutateBookmarkFolders, isBookmarked, currentPage, mutateBookmarkInfo, mutateUserBookmarks, toggleBookmarkHandler]);
   }, [mutateBookmarkFolders, isBookmarked, currentPage, mutateBookmarkInfo, mutateUserBookmarks, toggleBookmarkHandler]);
 
 
+  // Delete folder handler
+  const onClickDeleteHandler = useCallback(async(e, item) => {
+    e.stopPropagation();
+
+    const bookmarkFolderDeleteHandler: onDeletedBookmarkFolderFunction = (folderId) => {
+      if (typeof folderId !== 'string') {
+        return;
+      }
+      mutateBookmarkInfo();
+      mutateBookmarkFolders();
+    };
+
+    if (item == null) {
+      return;
+    }
+    openDeleteBookmarkFolderModal(item, { onDeleted: bookmarkFolderDeleteHandler });
+  }, [mutateBookmarkFolders, mutateBookmarkInfo, openDeleteBookmarkFolderModal]);
+
+  const onClickChildMenuItemHandler = useCallback(async(e, item) => {
+    e.stopPropagation();
+
+    setSelectedItem(null);
+
+    try {
+      if (isBookmarked && currentPage != null) {
+        await toggleBookmark(currentPage._id, isBookmarked);
+      }
+      if (currentPage != null) {
+        await addBookmarkToFolder(currentPage._id, item._id);
+      }
+      mutateUserBookmarks();
+      mutateBookmarkFolders();
+      setSelectedItem(item._id);
+      mutateBookmarkInfo();
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [isBookmarked, currentPage, mutateUserBookmarks, mutateBookmarkFolders, mutateBookmarkInfo]);
+
+
   const renderBookmarkMenuItem = (child?: BookmarkFolderItems[]) => {
   const renderBookmarkMenuItem = (child?: BookmarkFolderItems[]) => {
     const renderSubmenu = () => {
     const renderSubmenu = () => {
       if (child == null || currentPage == null || bookmarkInfo == null) {
       if (child == null || currentPage == null || bookmarkInfo == null) {
@@ -147,12 +191,10 @@ export const BookmarkFolderMenu: React.FC<{children?: React.ReactNode}> = ({ chi
                 <BookmarkFolderMenuItem
                 <BookmarkFolderMenuItem
                   item={folder}
                   item={folder}
                   isSelected={selectedItem === folder._id}
                   isSelected={selectedItem === folder._id}
-                  onSelectedChild={() => setSelectedItem(null)}
                   currentPage={currentPage}
                   currentPage={currentPage}
-                  bookmarkInfo={bookmarkInfo}
-                  mutateBookmarkFolders={mutateBookmarkFolders}
-                  mutateBookmarkInfo={mutateBookmarkInfo}
-                  mutateUserBookmarks={mutateUserBookmarks}
+                  onClickDeleteHandler={onClickDeleteHandler}
+                  onClickChildMenuItemHandler={onClickChildMenuItemHandler}
+                  onPressEnterHandlerForCreate={onPressEnterHandlerForCreate}
                 />
                 />
                 {isOpen && renderSubmenu()}
                 {isOpen && renderSubmenu()}
               </div>
               </div>
@@ -212,12 +254,10 @@ export const BookmarkFolderMenu: React.FC<{children?: React.ReactNode}> = ({ chi
                   <BookmarkFolderMenuItem
                   <BookmarkFolderMenuItem
                     item={folder}
                     item={folder}
                     isSelected={selectedItem === folder._id}
                     isSelected={selectedItem === folder._id}
-                    onSelectedChild={() => setSelectedItem(null)}
                     currentPage={currentPage}
                     currentPage={currentPage}
-                    bookmarkInfo={bookmarkInfo}
-                    mutateBookmarkFolders={mutateBookmarkFolders}
-                    mutateBookmarkInfo={mutateBookmarkInfo}
-                    mutateUserBookmarks={mutateUserBookmarks}
+                    onClickDeleteHandler={onClickDeleteHandler}
+                    onClickChildMenuItemHandler={onClickChildMenuItemHandler}
+                    onPressEnterHandlerForCreate={onPressEnterHandlerForCreate}
                   />
                   />
                   {isOpen && renderSubmenu()}
                   {isOpen && renderSubmenu()}
                 </div>
                 </div>

+ 24 - 86
apps/app/src/components/Bookmarks/BookmarkFolderMenuItem.tsx

@@ -8,16 +8,9 @@ import {
   DropdownItem,
   DropdownItem,
   DropdownMenu, DropdownToggle, UncontrolledDropdown,
   DropdownMenu, DropdownToggle, UncontrolledDropdown,
 } from 'reactstrap';
 } from 'reactstrap';
-import type { KeyedMutator } from 'swr';
 
 
-import {
-  addBookmarkToFolder, addNewFolder, hasChildren, toggleBookmark,
-} from '~/client/util/bookmark-utils';
-import { toastError } from '~/client/util/toastr';
-import { BookmarkFolderItems, IBookmarkInfo } from '~/interfaces/bookmark-info';
-import { IPageHasId } from '~/interfaces/page';
-import { onDeletedBookmarkFolderFunction } from '~/interfaces/ui';
-import { useBookmarkFolderDeleteModal } from '~/stores/modal';
+import { hasChildren } from '~/client/util/bookmark-utils';
+import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
 
 
 import { FolderIcon } from '../Icons/FolderIcon';
 import { FolderIcon } from '../Icons/FolderIcon';
 import { TriangleIcon } from '../Icons/TriangleIcon';
 import { TriangleIcon } from '../Icons/TriangleIcon';
@@ -27,21 +20,17 @@ import { BookmarkFolderNameInput } from './BookmarkFolderNameInput';
 export const BookmarkFolderMenuItem: React.FC<{
 export const BookmarkFolderMenuItem: React.FC<{
   item: BookmarkFolderItems
   item: BookmarkFolderItems
   isSelected: boolean
   isSelected: boolean
-  onSelectedChild: () => void
   currentPage: IPagePopulatedToShowRevision
   currentPage: IPagePopulatedToShowRevision
-  bookmarkInfo: IBookmarkInfo
-  mutateBookmarkFolders: KeyedMutator<BookmarkFolderItems[]>
-  mutateBookmarkInfo: KeyedMutator<IBookmarkInfo>
-  mutateUserBookmarks: KeyedMutator<IPageHasId[]>
+  onClickDeleteHandler: (e: any, item: any) => Promise<void>
+  onClickChildMenuItemHandler: (e: any, item: any) => Promise<void>
+  onPressEnterHandlerForCreate: (folderName: string, item?: BookmarkFolderItems) => Promise<void>
 }> = ({
 }> = ({
   item,
   item,
   isSelected,
   isSelected,
-  onSelectedChild,
   currentPage,
   currentPage,
-  bookmarkInfo,
-  mutateBookmarkFolders,
-  mutateBookmarkInfo,
-  mutateUserBookmarks,
+  onClickDeleteHandler,
+  onClickChildMenuItemHandler,
+  onPressEnterHandlerForCreate,
 }) => {
 }) => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
@@ -49,23 +38,8 @@ export const BookmarkFolderMenuItem: React.FC<{
   const [selectedItem, setSelectedItem] = useState<string | null>(null);
   const [selectedItem, setSelectedItem] = useState<string | null>(null);
   const [isCreateAction, setIsCreateAction] = useState<boolean>(false);
   const [isCreateAction, setIsCreateAction] = useState<boolean>(false);
 
 
-  const { open: openDeleteBookmarkFolderModal } = useBookmarkFolderDeleteModal();
-
-  const isBookmarked = bookmarkInfo?.isBookmarked ?? false;
-
   const childrenExists = hasChildren(item);
   const childrenExists = hasChildren(item);
 
 
-  const onPressEnterHandlerForCreate = useCallback(async(folderName: string) => {
-    try {
-      await addNewFolder(folderName, item._id);
-      await mutateBookmarkFolders();
-      setIsCreateAction(false);
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }, [item._id, mutateBookmarkFolders]);
-
   useEffect(() => {
   useEffect(() => {
     if (isOpen) {
     if (isOpen) {
       item.children?.forEach((bookmarkFolder) => {
       item.children?.forEach((bookmarkFolder) => {
@@ -92,43 +66,6 @@ export const BookmarkFolderMenuItem: React.FC<{
     setIsOpen(true);
     setIsOpen(true);
   }, []);
   }, []);
 
 
-  // Delete folder handler
-  const onClickDeleteHandler = useCallback(async(e) => {
-    e.stopPropagation();
-    const bookmarkFolderDeleteHandler: onDeletedBookmarkFolderFunction = (folderId) => {
-      if (typeof folderId !== 'string') {
-        return;
-      }
-      mutateBookmarkInfo();
-      mutateBookmarkFolders();
-    };
-
-    if (item == null) {
-      return;
-    }
-    openDeleteBookmarkFolderModal(item, { onDeleted: bookmarkFolderDeleteHandler });
-  }, [item, mutateBookmarkFolders, mutateBookmarkInfo, openDeleteBookmarkFolderModal]);
-
-  const onClickChildMenuItemHandler = useCallback(async(e, item) => {
-    e.stopPropagation();
-    onSelectedChild();
-    try {
-      if (isBookmarked && currentPage != null) {
-        await toggleBookmark(currentPage._id, isBookmarked);
-      }
-      if (currentPage != null) {
-        await addBookmarkToFolder(currentPage._id, item._id);
-      }
-      mutateUserBookmarks();
-      mutateBookmarkFolders();
-      setSelectedItem(item._id);
-      mutateBookmarkInfo();
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }, [onSelectedChild, isBookmarked, currentPage, mutateUserBookmarks, mutateBookmarkFolders, mutateBookmarkInfo]);
-
   const renderBookmarkSubMenuItem = useCallback(() => {
   const renderBookmarkSubMenuItem = useCallback(() => {
     if (!isOpen) {
     if (!isOpen) {
       return <></>;
       return <></>;
@@ -158,29 +95,30 @@ export const BookmarkFolderMenuItem: React.FC<{
               tabIndex={0} role="menuitem"
               tabIndex={0} role="menuitem"
               onClick={e => onClickChildMenuItemHandler(e, child)}>
               onClick={e => onClickChildMenuItemHandler(e, child)}>
               <BookmarkFolderMenuItem
               <BookmarkFolderMenuItem
-                onSelectedChild={() => setSelectedItem(null)}
                 item={child}
                 item={child}
                 isSelected={selectedItem === child._id}
                 isSelected={selectedItem === child._id}
                 currentPage={currentPage}
                 currentPage={currentPage}
-                bookmarkInfo={bookmarkInfo}
-                mutateBookmarkFolders={mutateBookmarkFolders}
-                mutateBookmarkInfo={mutateBookmarkInfo}
-                mutateUserBookmarks={mutateUserBookmarks}
+                onClickDeleteHandler={onClickDeleteHandler}
+                onClickChildMenuItemHandler={onClickChildMenuItemHandler}
+                onPressEnterHandlerForCreate={onPressEnterHandlerForCreate}
               />
               />
             </div>
             </div>
           </div>
           </div>
         ))}
         ))}
       </DropdownMenu>
       </DropdownMenu>
     );
     );
-  }, [isOpen,
-      isCreateAction,
-      onPressEnterHandlerForCreate,
-      t,
-      childrenExists,
-      item.children,
-      onClickNewBookmarkFolder,
-      selectedItem,
-      onClickChildMenuItemHandler,
+  }, [
+    isOpen,
+    isCreateAction,
+    onPressEnterHandlerForCreate,
+    t,
+    childrenExists,
+    item.children,
+    onClickNewBookmarkFolder,
+    selectedItem,
+    currentPage,
+    onClickDeleteHandler,
+    onClickChildMenuItemHandler,
   ]);
   ]);
 
 
   return (
   return (
@@ -210,7 +148,7 @@ export const BookmarkFolderMenuItem: React.FC<{
           id={`bookmark-delete-button-${item._id}`}
           id={`bookmark-delete-button-${item._id}`}
           className="text-danger ml-auto"
           className="text-danger ml-auto"
           color="transparent"
           color="transparent"
-          onClick={e => onClickDeleteHandler(e)}
+          onClick={e => onClickDeleteHandler(e, item)}
         >
         >
           <i className="icon-fw icon-trash grw-page-control-dropdown-icon"></i>
           <i className="icon-fw icon-trash grw-page-control-dropdown-icon"></i>
         </DropdownToggle>
         </DropdownToggle>

+ 4 - 3
apps/app/src/components/Bookmarks/BookmarkMoveToRootBtn.tsx

@@ -4,13 +4,14 @@ import { useTranslation } from 'react-i18next';
 import { DropdownItem } from 'reactstrap';
 import { DropdownItem } from 'reactstrap';
 
 
 export const BookmarkMoveToRootBtn: React.FC<{
 export const BookmarkMoveToRootBtn: React.FC<{
-  moveToRootClickedHandler: () => Promise<void>
-}> = React.memo(({ moveToRootClickedHandler }) => {
+  pageId: string
+  moveToRootClickedHandler: (pageId: string) => Promise<void>
+}> = React.memo(({ pageId, moveToRootClickedHandler }) => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
   return (
   return (
     <DropdownItem
     <DropdownItem
-      onClick={moveToRootClickedHandler}
+      onClick={() => moveToRootClickedHandler(pageId)}
       className="grw-page-control-dropdown-item"
       className="grw-page-control-dropdown-item"
       data-testid="add-remove-bookmark-btn"
       data-testid="add-remove-bookmark-btn"
     >
     >

+ 4 - 1
apps/app/src/components/PageList/BookmarkList.tsx

@@ -124,7 +124,10 @@ export const BookmarkList = (props:Props): JSX.Element => {
         onClickBookmarkMenuItem={bookmarkMenuItemClickHandler}
         onClickBookmarkMenuItem={bookmarkMenuItemClickHandler}
         onClickRenameMenuItem={() => setIsRenameInputShown(true)}
         onClickRenameMenuItem={() => setIsRenameInputShown(true)}
         onClickDeleteMenuItem={deleteMenuItemClickHandler}
         onClickDeleteMenuItem={deleteMenuItemClickHandler}
-        additionalMenuItemOnTopRenderer={isMoveToRoot ? (() => <BookmarkMoveToRootBtn moveToRootClickedHandler={moveToRootClickedHandler}/>) : undefined}
+        additionalMenuItemOnTopRenderer={isMoveToRoot
+          ? () => <BookmarkMoveToRootBtn pageId={pageId} moveToRootClickedHandler={moveToRootClickedHandler}/>
+          : undefined
+        }
       >
       >
         <DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control p-0 grw-visible-on-hover mr-1">
         <DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control p-0 grw-visible-on-hover mr-1">
           <i className="icon-options fa fa-rotate-90 p-1"></i>
           <i className="icon-options fa fa-rotate-90 p-1"></i>

+ 1 - 1
apps/app/src/components/Sidebar/PageTree/Item.tsx

@@ -30,7 +30,7 @@ import { shouldRecoverPagePaths } from '~/utils/page-operation';
 
 
 import ClosableTextInput from '../../Common/ClosableTextInput';
 import ClosableTextInput from '../../Common/ClosableTextInput';
 import CountBadge from '../../Common/CountBadge';
 import CountBadge from '../../Common/CountBadge';
-import { MenuItemType, PageItemControl } from '../../Common/Dropdown/PageItemControl';
+import { PageItemControl } from '../../Common/Dropdown/PageItemControl';
 
 
 import { ItemNode } from './ItemNode';
 import { ItemNode } from './ItemNode';