Explorar o código

Move bookmarks item component

https://youtrack.weseek.co.jp/issue/GW-7861
- Remove rendering bookmark items from Bookmarks component
- Move BookmarkItem component implementation to BookmarkFolderTree
- Fix tooltip text of bookmark item
- Adjust styling of bookmark item
- Adjust Bookmark folder display for guest user
- Adjust render bookmark item when no bookmarked pages
- Remove unused definition of virtual bookmarks
- Remove folder from bookmark Schema
- Update return value of bookmark folder list route
Mudana-Grune %!s(int64=3) %!d(string=hai) anos
pai
achega
b5566f67bd

+ 5 - 64
packages/app/src/components/Sidebar/Bookmarks.tsx

@@ -3,88 +3,29 @@ import React from 'react';
 
 import { useTranslation } from 'react-i18next';
 
-import { toastSuccess } from '~/client/util/apiNotification';
-import { IPageToDeleteWithMeta } from '~/interfaces/page';
-import { OnDeletedFunction } from '~/interfaces/ui';
-import { useSWRxCurrentUserBookmarks } from '~/stores/bookmark';
 import { useIsGuestUser } from '~/stores/context';
-import { usePageDeleteModal } from '~/stores/modal';
-
 
 import BookmarkFolder from './Bookmarks/BookmarkFolder';
-import BookmarkItem from './Bookmarks/BookmarkItem';
 
 const Bookmarks = () : JSX.Element => {
   const { t } = useTranslation();
   const { data: isGuestUser } = useIsGuestUser();
-  const { data: currentUserBookmarksData, mutate: mutateCurrentUserBookmarks } = useSWRxCurrentUserBookmarks();
-  const { open: openDeleteModal } = usePageDeleteModal();
-
-
-  const deleteMenuItemClickHandler = (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 }));
-      }
-      mutateCurrentUserBookmarks();
-    };
-    openDeleteModal([pageToDelete], { onDeleted: pageDeletedHandler });
-  };
-
-
-  const renderBookmarkList = () => {
-    if (currentUserBookmarksData?.length === 0) {
-      return (
-        <h4 className="pl-3">
-          { t('No bookmarks yet') }
-        </h4>
-      );
-    }
-    return (
-      <ul className="grw-bookmarks-list list-group p-3">
-        <div className="grw-bookmarks-item-container">
-          { currentUserBookmarksData?.map((currentUserBookmark) => {
-            return (
-              <BookmarkItem
-                key={currentUserBookmark._id}
-                bookmarkedPage={currentUserBookmark}
-                onUnbookmarked={mutateCurrentUserBookmarks}
-                onRenamed={mutateCurrentUserBookmarks}
-                onClickDeleteMenuItem={deleteMenuItemClickHandler}
-              />
-            );
-          })}
-        </div>
-      </ul>
-    );
-  };
 
   return (
     <>
       <div className="grw-sidebar-content-header p-3">
         <h3 className="mb-0">{t('Bookmarks')}</h3>
       </div>
-      {!isGuestUser && (
+      {!isGuestUser ? (
         <>
           <BookmarkFolder />
         </>
+      ) : (
+        <h4 className="pl-3">
+          { t('Not available for guest') }
+        </h4>
       )
       }
-      { isGuestUser
-        ? (
-          <h4 className="pl-3">
-            { t('Not available for guest') }
-          </h4>
-        ) : renderBookmarkList()
-      }
     </>
   );
 };

+ 4 - 0
packages/app/src/components/Sidebar/Bookmarks/BookmarkFolderTree.module.scss

@@ -58,6 +58,10 @@ $grw-foldertree-item-padding-left: 10px;
         min-width: 35px;
         height: 40px;
       }
+      .bookmark-item-list{
+        min-width: 30px;
+        height: 35px;
+      }
     }
   }
   &:global{

+ 61 - 12
packages/app/src/components/Sidebar/Bookmarks/BookmarkFolderTree.tsx

@@ -1,27 +1,76 @@
 
+import { useTranslation } from 'next-i18next';
+
+import { toastSuccess } from '~/client/util/apiNotification';
+import { IPageToDeleteWithMeta } from '~/interfaces/page';
+import { OnDeletedFunction } from '~/interfaces/ui';
+import { useSWRxCurrentUserBookmarks } from '~/stores/bookmark';
 import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
+import { usePageDeleteModal } from '~/stores/modal';
 
 import BookmarkFolderItem from './BookmarkFolderItem';
+import BookmarkItem from './BookmarkItem';
 
 import styles from './BookmarkFolderTree.module.scss';
 
 
 const BookmarkFolderTree = (): JSX.Element => {
+  const { t } = useTranslation();
+  const { data: currentUserBookmarksData, mutate: mutateCurrentUserBookmarks } = useSWRxCurrentUserBookmarks();
   const { data: bookmarkFolderData } = useSWRxBookamrkFolderAndChild();
+  const { open: openDeleteModal } = usePageDeleteModal();
+
+  const deleteMenuItemClickHandler = (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 }));
+      }
+      mutateCurrentUserBookmarks();
+    };
+    openDeleteModal([pageToDelete], { onDeleted: pageDeletedHandler });
+  };
+
   if (bookmarkFolderData != null) {
     return (
-
-      <ul className={`grw-foldertree ${styles['grw-foldertree']} list-group p-3`}>
-        {bookmarkFolderData.map((item) => {
-          return (
-            <BookmarkFolderItem
-              key={item._id}
-              bookmarkFolder={item}
-              isOpen={false}
-            />
-          );
-        })}
-      </ul>
+      <>
+        <ul className={`grw-foldertree ${styles['grw-foldertree']} list-group p-3`}>
+          {bookmarkFolderData.map((item) => {
+            return (
+              <BookmarkFolderItem
+                key={item._id}
+                bookmarkFolder={item}
+                isOpen={false}
+              />
+            );
+          })}
+          {currentUserBookmarksData?.length === 0 && (
+            <div className="pt-3">
+              <h5 className="pl-3">
+                { t('No bookmarks yet') }
+              </h5>
+            </div>
+          )}
+          { currentUserBookmarksData?.map((currentUserBookmark) => {
+            return (
+              <BookmarkItem
+                key={currentUserBookmark._id}
+                bookmarkedPage={currentUserBookmark}
+                onUnbookmarked={mutateCurrentUserBookmarks}
+                onRenamed={mutateCurrentUserBookmarks}
+                onClickDeleteMenuItem={deleteMenuItemClickHandler}
+              />
+            );
+          })}
+        </ul>
+      </>
     );
   }
   return <></>;

+ 4 - 4
packages/app/src/components/Sidebar/Bookmarks/BookmarkItem.tsx

@@ -96,8 +96,8 @@ const BookmarkItem = (props: Props): JSX.Element => {
   }, [bookmarkedPage, onClickDeleteMenuItem]);
 
   return (
-    <div className="d-flex justify-content-between" key={bookmarkedPage._id}>
-      <li className="list-group-item list-group-item-action border-0 py-0 pr-3 d-flex align-items-center" id={bookmarkItemId}>
+    <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}>
         { isRenameInputShown ? (
           <ClosableTextInput
             value={nodePath.basename(bookmarkedPage.path ?? '')}
@@ -107,7 +107,7 @@ const BookmarkItem = (props: Props): JSX.Element => {
             inputValidator={inputValidator}
           />
         ) : (
-          <a href={`/${bookmarkedPage._id}`} className="grw-bookmarks-title-anchor flex-grow-1">
+          <a href={`/${bookmarkedPage._id}`} className="grw-foldertree-title-anchor flex-grow-1 pr-3">
             <p className={`text-truncate m-auto ${bookmarkedPage.isEmpty && 'grw-sidebar-text-muted'}`}>{pageTitle}</p>
           </a>
         )}
@@ -130,7 +130,7 @@ const BookmarkItem = (props: Props): JSX.Element => {
           target={bookmarkItemId}
           fade={false}
         >
-          { formerPagePath }
+          { formerPagePath !== null ? `${formerPagePath}/` : '/' }
         </UncontrolledTooltip>
       </li>
     </div>

+ 0 - 1
packages/app/src/interfaces/bookmark-info.ts

@@ -29,5 +29,4 @@ export interface BookmarkFolderItems {
   name: string
   parent: string
   children: this[]
-  bookmarks: BookmarkedPage[]
 }

+ 3 - 10
packages/app/src/server/models/bookmark-folder.ts

@@ -32,6 +32,8 @@ const bookmarkFolderSchema = new Schema<BookmarkFolderDocument, BookmarkFolderMo
   name: { type: String },
   owner: { type: Schema.Types.ObjectId, ref: 'User', index: true },
   parent: { type: Schema.Types.ObjectId, ref: 'BookmarkFolder', required: false },
+}, {
+  toObject: { virtuals: true },
 });
 
 bookmarkFolderSchema.virtual('children', {
@@ -40,12 +42,6 @@ bookmarkFolderSchema.virtual('children', {
   foreignField: 'parent',
 });
 
-bookmarkFolderSchema.virtual('bookmarks', {
-  ref: 'Bookmark',
-  localField: '_id',
-  foreignField: 'folder',
-});
-
 bookmarkFolderSchema.statics.createByParameters = async function(params: IBookmarkFolder): Promise<BookmarkFolderDocument> {
   const { name, owner, parent } = params;
   let bookmarkFolder;
@@ -75,9 +71,7 @@ bookmarkFolderSchema.statics.findFolderAndChildren = async function(
     parentId?: Types.ObjectId | string,
 ): Promise<BookmarkFolderItems[]> {
 
-  const parentFolder = await this.findById(parentId).populate({ path: 'bookmarks' }).exec() as unknown as BookmarkFolderDocument;
-
-  // TODO : forms the return value for the bookmark
+  const parentFolder = await this.findById(parentId) as unknown as BookmarkFolderDocument;
   const bookmarkFolders = await this.find({ owner: userId, parent: parentFolder })
     .populate({ path: 'children' }).exec() as unknown as BookmarkFolderItems[];
   return bookmarkFolders;
@@ -112,6 +106,5 @@ bookmarkFolderSchema.statics.updateBookmarkFolder = async function(bookmarkFolde
 
 };
 
-bookmarkFolderSchema.set('toObject', { virtuals: true });
 
 export default getOrCreateModel<BookmarkFolderDocument, BookmarkFolderModel>('BookmarkFolder', bookmarkFolderSchema);

+ 0 - 1
packages/app/src/server/models/bookmark.js

@@ -16,7 +16,6 @@ module.exports = function(crowi) {
   bookmarkSchema = new mongoose.Schema({
     page: { type: ObjectId, ref: 'Page', index: true },
     user: { type: ObjectId, ref: 'User', index: true },
-    folder: { type: ObjectId, ref: 'BookmarkFolder', required: false },
   }, {
     timestamps: { createdAt: true, updatedAt: false },
   });

+ 0 - 1
packages/app/src/server/routes/apiv3/bookmark-folder.ts

@@ -56,7 +56,6 @@ module.exports = (crowi) => {
         name: bookmarkFolder.name,
         parent: bookmarkFolder.parent,
         children: bookmarkFolder.children,
-        bookmarks: bookmarkFolder.bookmarks,
       }));
       return res.apiv3({ bookmarkFolderItems });
     }