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

Improve Bookmark Menu component

https://youtrack.weseek.co.jp/issue/GW-7910
- Rename BookmarkFolderDropdown to BookmarkFolderMenu
- Implement folder data fetching in BookmarkButtons component
- Implement mutatebookmarkFolderData on bookmark button click
- Add bookmarkFolders props to BookmarkFolderMenu
- Improve Dropdown component rendering for recursive bookmark folder
- Rename BookmarkFolderSubMenu to BookmarkFolderMenuItem
- Implement triangle icon to Bookmark menu item if item has children
- Change dropdown toggle button to div instead of button
- Fix unique key error on bookmark item rendering
Mudana-Grune 3 лет назад
Родитель
Сommit
71c8240f9f

+ 11 - 4
packages/app/src/components/BookmarkButtons.tsx

@@ -7,11 +7,12 @@ import {
   UncontrolledTooltip, Popover, PopoverBody, DropdownToggle,
 } from 'reactstrap';
 
+import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
 import { useIsGuestUser } from '~/stores/context';
 
 import { IUser } from '../interfaces/user';
 
-import BookmarkFolderDropdown from './Bookmarks/BookmarkFolderDropdown';
+import BookmarkFolderMenu from './Bookmarks/BookmarkFolderMenu';
 import UserPictureList from './User/UserPictureList';
 
 import styles from './BookmarkButtons.module.scss';
@@ -33,6 +34,8 @@ const BookmarkButtons: FC<Props> = (props: Props) => {
   const [isPopoverOpen, setIsPopoverOpen] = useState(false);
 
   const { data: isGuestUser } = useIsGuestUser();
+  const { data: bookmarkFolderData, mutate: mutatebookmarkFolderData } = useSWRxBookamrkFolderAndChild();
+
 
   const togglePopover = () => {
     setIsPopoverOpen(!isPopoverOpen);
@@ -49,14 +52,18 @@ const BookmarkButtons: FC<Props> = (props: Props) => {
     return 'tooltip.bookmark';
   }, [isGuestUser, isBookmarked]);
 
+  const onClickBookmarkButtonHandler = useCallback(() => {
+    mutatebookmarkFolderData();
+  }, [mutatebookmarkFolderData]);
+
   return (
     <div className={`btn-group btn-group-bookmark ${styles['btn-group-bookmark']}`} role="group" aria-label="Bookmark buttons">
-      <BookmarkFolderDropdown >
-        <DropdownToggle id='bookmark-dropdown-btn' color="transparent" className={`shadow-none btn btn-bookmark border-0
+      <BookmarkFolderMenu bookmarkFolders={bookmarkFolderData}>
+        <DropdownToggle id='bookmark-dropdown-btn' color="transparent" onClick={onClickBookmarkButtonHandler} className={`shadow-none btn btn-bookmark border-0
           ${isBookmarked ? 'active' : ''} ${isGuestUser ? 'disabled' : ''}`}>
           <i className={`fa ${isBookmarked ? 'fa-bookmark' : 'fa-bookmark-o'}`}></i>
         </DropdownToggle>
-      </BookmarkFolderDropdown>
+      </BookmarkFolderMenu>
 
       <UncontrolledTooltip placement="top" target="bookmark-dropdown-btn" fade={false}>
         {t(getTooltipMessage())}

+ 0 - 55
packages/app/src/components/Bookmarks/BookmarkFolderDropdown.tsx

@@ -1,55 +0,0 @@
-import React, { useState } from 'react';
-
-import { useTranslation } from 'next-i18next';
-import {
-  Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Nav, NavItem, UncontrolledDropdown,
-} from 'reactstrap';
-
-import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
-
-import FolderIcon from '../Icons/FolderIcon';
-
-import BookmarkFolderSubMenu from './BookmarkFolderSubMenu';
-
-
-type Props = {
-  children?: React.ReactNode
-}
-
-const BookmarkFolderDropdown = (props: Props): JSX.Element => {
-  const { t } = useTranslation();
-  const { children } = props;
-  const [isOpen, setIsOpen] = useState(false);
-
-  const { data: bookmarkFolderData } = useSWRxBookamrkFolderAndChild();
-
-
-  return (
-    <Nav className="ml-auto">
-      <UncontrolledDropdown nav >
-        {children}
-        <DropdownMenu right >
-          {bookmarkFolderData?.map((folder) => {
-            return folder.children.length > 0 ? (
-              <>
-                <DropdownItem >
-                  {folder.name}
-                </DropdownItem>
-
-                {folder.children.map(child => (
-                  <BookmarkFolderSubMenu key={child._id} item={child} />
-                ))}
-              </>
-            ) : (
-              <DropdownItem>
-                {folder.name}
-              </DropdownItem>
-            );
-          })}
-        </DropdownMenu>
-      </UncontrolledDropdown>
-    </Nav>
-  );
-};
-
-export default BookmarkFolderDropdown;

+ 52 - 0
packages/app/src/components/Bookmarks/BookmarkFolderMenu.tsx

@@ -0,0 +1,52 @@
+import React from 'react';
+
+import { useTranslation } from 'next-i18next';
+import {
+  DropdownItem, DropdownMenu, UncontrolledDropdown,
+} from 'reactstrap';
+
+import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
+
+import FolderIcon from '../Icons/FolderIcon';
+
+import BookmarkFolderMenuItem from './BookmarkFolderMenuItem';
+
+
+type Props = {
+  children?: React.ReactNode
+  bookmarkFolders: BookmarkFolderItems[] | undefined
+}
+
+const BookmarkFolderMenu = (props: Props): JSX.Element => {
+  const { t } = useTranslation();
+  const { children, bookmarkFolders } = props;
+
+  return (
+    <UncontrolledDropdown >
+      {children}
+      <DropdownMenu right className='rounded-0'>
+        <DropdownItem toggle={false}>
+          <FolderIcon isOpen={false}/>
+          <span className="mx-2 ">{t('bookmark_folder.new_folder')}</span>
+        </DropdownItem>
+        <DropdownItem divider />
+        {bookmarkFolders?.map(folder => (
+          <div key={folder._id} >
+            { folder.children.length > 0 ? (
+              <div className='dropdown-item' tabIndex={0} role="menuitem">
+                <BookmarkFolderMenuItem item={folder} />
+              </div>
+            ) : (
+              <DropdownItem toggle={false}>
+                {folder.name}
+              </DropdownItem>
+            )}
+          </div>
+        ))}
+      </DropdownMenu>
+    </UncontrolledDropdown>
+
+  );
+};
+
+export default BookmarkFolderMenu;

+ 69 - 0
packages/app/src/components/Bookmarks/BookmarkFolderMenuItem.tsx

@@ -0,0 +1,69 @@
+import React, { useCallback, useEffect, useState } from 'react';
+
+import {
+  DropdownItem, DropdownMenu, DropdownToggle, Dropdown,
+} from 'reactstrap';
+
+import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
+import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
+
+import TriangleIcon from '../Icons/TriangleIcon';
+
+
+type Props ={
+  item: BookmarkFolderItems
+}
+const BookmarkFolderMenuItem = (props: Props):JSX.Element => {
+  const { item } = props;
+  const [isOpen, setIsOpen] = useState(false);
+  const { data: childFolders, mutate: mutateChildFolders } = useSWRxBookamrkFolderAndChild(item._id);
+
+  useEffect(() => {
+    if (isOpen) {
+      mutateChildFolders();
+    }
+  }, [isOpen, mutateChildFolders]);
+
+  const onMouseEnterHandler = useCallback(() => {
+    setIsOpen(true);
+  }, []);
+
+  const onMouseLeaveHandler = useCallback(() => {
+    setIsOpen(false);
+  }, []);
+  const toggleHandler = useCallback(() => {
+    setIsOpen(!isOpen);
+  }, [isOpen]);
+
+  return (
+    <Dropdown direction="right"
+      onMouseOver={onMouseEnterHandler} onMouseLeave={onMouseLeaveHandler} isOpen={isOpen} toggle={toggleHandler}>
+      <DropdownToggle color="transparent" className={'border-0 px-0 d-flex justify-content-between'} style={{ minWidth: '100%' }}>
+        {item.name}
+        <span className='pl-2'>
+          <TriangleIcon/>
+        </span>
+      </DropdownToggle>
+      { childFolders != null
+          && (<DropdownMenu className='rounded-0 py-1 m-0'>
+            {childFolders?.map(child => (
+              <div key={child._id} >
+                {child.children.length > 0 ? (
+                  <div className='dropdown-item' tabIndex={0} role="menuitem">
+                    <BookmarkFolderMenuItem item={child} />
+                  </div>
+
+                ) : (
+                  <DropdownItem toggle={false}>
+                    {child.name}
+                  </DropdownItem>
+                )}
+              </div>
+            ))}
+          </DropdownMenu>
+          )
+      }
+    </Dropdown>
+  );
+};
+export default BookmarkFolderMenuItem;

+ 0 - 42
packages/app/src/components/Bookmarks/BookmarkFolderSubMenu.tsx

@@ -1,42 +0,0 @@
-import React from 'react';
-
-import {
-  DropdownItem, DropdownMenu, Nav, UncontrolledDropdown,
-} from 'reactstrap';
-
-import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
-import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
-
-
-type Props ={
-  item: BookmarkFolderItems
-}
-const BookmarkFolderSubMenu = (props: Props):JSX.Element => {
-  const { item } = props;
-  const { data: childFolders } = useSWRxBookamrkFolderAndChild(item._id);
-
-  return (
-    <>
-
-      {childFolders?.map((folder) => {
-        return folder.children.length > 0 ? (
-          <>
-            <DropdownItem >
-              {folder.name}
-            </DropdownItem>
-
-            {folder.children.map(child => (
-              <BookmarkFolderSubMenu key={child._id} item={child} />
-            ))}
-          </>
-        ) : (
-          <DropdownItem>
-            {folder.name}
-          </DropdownItem>
-        );
-      })}
-
-    </>
-  );
-};
-export default BookmarkFolderSubMenu;