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

Fix rename action and add delete modal component

https://youtrack.weseek.co.jp/issue/GW-7905
- Add load parent method to reload folder data after rename
- Adjust mutation parameter
- Implement rename action to onPressEnter method
- Create delete modal component
- Implement onClickDelete in BookmarkFolderItemControl component
- Implement DeleteBookmarkFolderModal to BookmarkFolderItem component
Mudana-Grune 3 лет назад
Родитель
Сommit
5b444aeb8c

+ 54 - 10
packages/app/src/components/Sidebar/Bookmarks/BookmarkFolderItem.tsx

@@ -6,7 +6,7 @@ import { useTranslation } from 'next-i18next';
 import { DropdownToggle } from 'reactstrap';
 
 import { toastError, toastSuccess } from '~/client/util/apiNotification';
-import { apiv3Post } from '~/client/util/apiv3-client';
+import { apiv3Delete, apiv3Post, apiv3Put } from '~/client/util/apiv3-client';
 import CountBadge from '~/components/Common/CountBadge';
 import FolderIcon from '~/components/Icons/FolderIcon';
 import TriangleIcon from '~/components/Icons/TriangleIcon';
@@ -15,6 +15,7 @@ import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
 
 import BookmarkFolderItemControl from './BookmarkFolderItemControl';
 import BookmarkFolderNameInput from './BookmarkFolderNameInput';
+import DeleteBookmarkFolderModal from './DeleteBookmarkFolderModal';
 
 
 type BookmarkFolderItemProps = {
@@ -32,8 +33,10 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
   const [isRenameInputShown, setIsRenameInputShown] = useState<boolean>(false);
   const [currentParentFolder, setCurrentParentFolder] = useState<string | null>(folderId);
   const [isOpen, setIsOpen] = useState(_isOpen);
-  const { data: childBookmarkFolderData, mutate: mutateChildBookmarkData } = useSWRxBookamrkFolderAndChild(isOpen ? currentParentFolder : null);
+  const [isLoadParent, setIsLoadParent] = useState<boolean>(false);
+  const { data: childBookmarkFolderData, mutate: mutateChildBookmarkData } = useSWRxBookamrkFolderAndChild(isOpen || isLoadParent ? currentParentFolder : null);
   const [isRenameAction, setIsRenameAction] = useState<boolean>(false);
+  const [isDeleteFolderModalShown, setIsDeleteFolderModalShown] = useState<boolean>(false);
 
   const childCount = useCallback((): number => {
     if (currentChildren != null && currentChildren.length > children.length) {
@@ -47,7 +50,10 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
       mutateChildBookmarkData();
       setCurrentChildren(childBookmarkFolderData);
     }
-  }, [childBookmarkFolderData, isOpen, mutateChildBookmarkData]);
+    else if (isLoadParent) {
+      mutateChildBookmarkData();
+    }
+  }, [childBookmarkFolderData, isLoadParent, isOpen, mutateChildBookmarkData]);
 
   const hasChildren = useCallback((): boolean => {
     if (currentChildren != null && currentChildren.length > children.length) {
@@ -56,26 +62,38 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
     return children.length > 0;
   }, [children.length, currentChildren]);
 
-
   const loadChildFolder = useCallback(async() => {
     setIsOpen(!isOpen);
+    setIsLoadParent(false);
     setCurrentParentFolder(folderId);
   }, [folderId, isOpen]);
 
+  const loadParent = useCallback(async() => {
+    setCurrentParentFolder(parent);
+    setIsLoadParent(true);
+  }, [parent]);
 
   const onPressEnterHandler = useCallback(async(folderName: string) => {
-
     try {
-      await apiv3Post('/bookmark-folder', { name: folderName, parent: currentParentFolder });
-      setIsOpen(true);
-      setIsRenameInputShown(false);
-      toastSuccess(t('Create New Bookmark Folder Success'));
+      if (isRenameAction) {
+        await apiv3Put('/bookmark-folder', { bookmarkFolderId: folderId, name: folderName, parent });
+        loadParent();
+        setIsRenameAction(false);
+        toastSuccess(t('Rename Bookmark Folder Success'));
+      }
+      else {
+        await apiv3Post('/bookmark-folder', { name: folderName, parent: currentParentFolder });
+        setIsOpen(true);
+        setIsRenameInputShown(false);
+        mutateChildBookmarkData();
+        toastSuccess(t('Create New Bookmark Folder Success'));
+      }
     }
     catch (err) {
       toastError(err);
     }
 
-  }, [currentParentFolder, t]);
+  }, [currentParentFolder, folderId, isRenameAction, loadParent, mutateChildBookmarkData, parent, t]);
 
   const onClickPlusButton = useCallback(async() => {
     if (!isOpen && hasChildren()) {
@@ -101,6 +119,26 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
     setIsRenameAction(true);
   }, []);
 
+  const onClickDeleteHandler = useCallback(() => {
+    setIsDeleteFolderModalShown(true);
+  }, []);
+
+  const onDeleteFolderModalClose = useCallback(() => {
+    setIsDeleteFolderModalShown(false);
+  }, []);
+
+  const onClickDeleteButtonHandler = useCallback(async() => {
+    try {
+      await apiv3Delete(`/bookmark-folder/${folderId}`);
+      setIsDeleteFolderModalShown(false);
+      toastSuccess(t('Delete bookmark folder success'));
+
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [folderId, t]);
+
   return (
     <div id={`bookmark-folder-item-${folderId}`} className="grw-foldertree-item-container"
     >
@@ -145,6 +183,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
         <div className="grw-foldertree-control d-flex">
           <BookmarkFolderItemControl
             onClickRename={onClickRenameHandler}
+            onClickDelete={onClickDeleteHandler}
           >
             <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>
@@ -172,6 +211,11 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
       {
         RenderChildFolder()
       }
+      <DeleteBookmarkFolderModal
+        bookmarkFolder={bookmarkFolder}
+        isOpen={isDeleteFolderModalShown}
+        onClickDeleteButton={onClickDeleteButtonHandler}
+        onModalClose={onDeleteFolderModalClose}/>
     </div>
   );
 };

+ 3 - 2
packages/app/src/components/Sidebar/Bookmarks/BookmarkFolderItemControl.tsx

@@ -9,10 +9,11 @@ import {
 type BookmarkFolderItemControlProps = {
   children?: React.ReactNode
   onClickRename: () => void
+  onClickDelete: () => void
 }
 const BookmarkFolderItemControl = (props: BookmarkFolderItemControlProps): JSX.Element => {
   const { t } = useTranslation();
-  const { children, onClickRename } = props;
+  const { children, onClickRename, onClickDelete } = props;
   const [isOpen, setIsOpen] = useState(false);
   return (
     <Dropdown isOpen={isOpen} toggle={() => setIsOpen(!isOpen)}>
@@ -36,7 +37,7 @@ const BookmarkFolderItemControl = (props: BookmarkFolderItemControlProps): JSX.E
         <DropdownItem divider/>
         <DropdownItem
           className='pt-2 grw-page-control-dropdown-item text-danger'
-          onClick={() => {}}
+          onClick={onClickDelete}
         >
           <i className="icon-fw icon-trash grw-page-control-dropdown-icon"></i>
           {t('Delete')}

+ 53 - 0
packages/app/src/components/Sidebar/Bookmarks/DeleteBookmarkFolderModal.tsx

@@ -0,0 +1,53 @@
+
+import React from 'react';
+
+import { useTranslation } from 'next-i18next';
+import {
+  Modal, ModalBody, ModalFooter, ModalHeader,
+} from 'reactstrap';
+
+import FolderIcon from '~/components/Icons/FolderIcon';
+import { BookmarkFolderItems } from '~/server/models/bookmark-folder';
+
+type DeleteBookmarkFolderModalProps = {
+  isOpen: boolean
+  bookmarkFolder: BookmarkFolderItems
+  onClickDeleteButton: () => void
+  onModalClose: () => void
+}
+
+const DeleteBookmarkFolderModal = (props: DeleteBookmarkFolderModalProps): JSX.Element => {
+  const { t } = useTranslation();
+  const {
+    isOpen, onClickDeleteButton, bookmarkFolder, onModalClose,
+  } = props;
+
+  return (
+    <Modal size="md" isOpen={isOpen} toggle={onModalClose} data-testid="page-delete-modal" className="grw-create-page">
+      <ModalHeader tag="h4" toggle={onModalClose} className="bg-danger text-light">
+        <i className="icon-fw icon-trash"></i>
+        {t('Delete Bookmark Folder')}
+      </ModalHeader>
+      <ModalBody>
+        <div className="form-group pb-1">
+          <label>{ t('Delete this bookmark folder and its contents') }:</label><br />
+          <FolderIcon isOpen={false}/> {bookmarkFolder.name}
+        </div>
+        {t('Deleted folder and its contents cannot be recovered')}
+      </ModalBody>
+      <ModalFooter>
+        <button
+          type="button"
+          className="btn btn-danger"
+          onClick={onClickDeleteButton}
+        >
+          <i className="mr-1 icon-trash" aria-hidden="true"></i>
+          {t('Delete Folder')}
+        </button>
+      </ModalFooter>
+    </Modal>
+
+  );
+};
+
+export default DeleteBookmarkFolderModal;