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

Merge branch 'master' into imprv/89795-add-cursor-pointer-to-sort-elm-on-search-page

kaori 4 лет назад
Родитель
Сommit
9044751fa5

+ 40 - 58
packages/app/src/components/Sidebar/PageTree/Item.tsx

@@ -16,7 +16,7 @@ import { toastWarning, toastError, toastSuccess } from '~/client/util/apiNotific
 
 import { useSWRxPageChildren } from '~/stores/page-listing';
 import { apiv3Put, apiv3Post } from '~/client/util/apiv3-client';
-import { IPageForPageRenameModal, IPageForPageDuplicateModal } from '~/stores/modal';
+import { IPageForPageDuplicateModal } from '~/stores/modal';
 
 import TriangleIcon from '~/components/Icons/TriangleIcon';
 import { bookmark, unbookmark } from '~/client/services/page-operation';
@@ -37,8 +37,8 @@ interface ItemProps {
   isScrolled: boolean,
   isOpen?: boolean
   isEnabledAttachTitleHeader?: boolean
+  onRenamed?(): void
   onClickDuplicateMenuItem?(pageToDuplicate: IPageForPageDuplicateModal): void
-  onClickRenameMenuItem?(pageToRename: IPageForPageRenameModal): void
   onClickDeleteMenuItem?(pageToDelete: IPageToDeleteWithMeta): void
 }
 
@@ -111,7 +111,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
   const { t } = useTranslation();
   const {
     itemNode, targetPathOrId, isOpen: _isOpen = false, isEnabledAttachTitleHeader,
-    onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteMenuItem, isEnableActions,
+    onRenamed, onClickDuplicateMenuItem, onClickDeleteMenuItem, isEnableActions,
   } = props;
 
   const { page, children } = itemNode;
@@ -120,7 +120,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
   const [isOpen, setIsOpen] = useState(_isOpen);
   const [isNewPageInputShown, setNewPageInputShown] = useState(false);
   const [shouldHide, setShouldHide] = useState(false);
-  // const [isRenameInputShown, setRenameInputShown] = useState(false);
+  const [isRenameInputShown, setRenameInputShown] = useState(false);
 
   const { data, mutate: mutateChildren } = useSWRxPageChildren(isOpen ? page._id : null);
 
@@ -256,55 +256,38 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
     onClickDuplicateMenuItem(pageToDuplicate);
   }, [onClickDuplicateMenuItem, page]);
 
+  const renameMenuItemClickHandler = useCallback(() => {
+    setRenameInputShown(true);
+  }, []);
 
-  /*
-  * Rename: TODO: rename page title on input form by #87757
-  */
-
-  // const onClickRenameButton = useCallback(async(_pageId: string): Promise<void> => {
-  //   setRenameInputShown(true);
-  // }, []);
-
-  // const onPressEnterForRenameHandler = async(inputText: string) => {
-  //   const parentPath = getParentPagePath(page.path as string)
-  //   const newPagePath = `${parentPath}/${inputText}`;
-
-  //   try {
-  //     setPageTitle(inputText);
-  //     setRenameInputShown(false);
-  //     await apiv3Put('/pages/rename', { newPagePath, pageId: page._id, revisionId: page.revision });
-  //   }
-  //   catch (err) {
-  //     // open ClosableInput and set pageTitle back to the previous title
-  //     setPageTitle(nodePath.basename(pageTitle as string));
-  //     setRenameInputShown(true);
-  //     toastError(err);
-  //   }
-  // };
-
-  const renameMenuItemClickHandler = useCallback((): void => {
-    if (onClickRenameMenuItem == null) {
+  const onPressEnterForRenameHandler = async(inputText: string) => {
+    const parentPath = pathUtils.addTrailingSlash(nodePath.dirname(page.path ?? ''));
+    const newPagePath = nodePath.resolve(parentPath, inputText);
+
+    if (newPagePath === page.path) {
+      setRenameInputShown(false);
       return;
     }
 
-    const { _id: pageId, revision: revisionId, path } = page;
+    try {
+      setRenameInputShown(false);
+      await apiv3Put('/pages/rename', {
+        pageId: page._id,
+        revisionId: page.revision,
+        newPagePath,
+      });
 
-    if (!page.isEmpty && revisionId == null) {
-      throw Error('Existing page should have revisionId');
-    }
+      if (onRenamed != null) {
+        onRenamed();
+      }
 
-    if (pageId == null || path == null) {
-      throw Error('Any of _id and revisionId and path must not be null.');
+      toastSuccess(t('renamed_pages', { path: page.path }));
     }
-
-    const pageToRename: IPageForPageRenameModal = {
-      pageId,
-      revisionId: revisionId as string,
-      path,
-    };
-
-    onClickRenameMenuItem(pageToRename);
-  }, [onClickRenameMenuItem, page]);
+    catch (err) {
+      setRenameInputShown(true);
+      toastError(err);
+    }
+  };
 
   const deleteMenuItemClickHandler = useCallback(async(_pageId: string, pageInfo: IPageInfoAll | undefined): Promise<void> => {
     if (page._id == null || page.revision == null || page.path == null) {
@@ -417,7 +400,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
     >
       <li
         ref={(c) => { drag(c); drop(c) }}
-        className={`list-group-item list-group-item-action border-0 py-0 d-flex align-items-center ${page.isTarget ? 'grw-pagetree-is-target' : ''}`}
+        className={`list-group-item list-group-item-action border-0 py-0 pr-3 d-flex align-items-center ${page.isTarget ? 'grw-pagetree-is-target' : ''}`}
         id={page.isTarget ? 'grw-pagetree-is-target' : `grw-pagetree-list-${page._id}`}
       >
         <div className="grw-triangle-container d-flex justify-content-center">
@@ -433,22 +416,21 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
             </button>
           )}
         </div>
-        {/* TODO: rename page title on input form by 87757 */}
-        {/* { isRenameInputShown && (
+        { isRenameInputShown && (
           <ClosableTextInput
             isShown
-            value={nodePath.basename(pageTitle as string)}
+            value={nodePath.basename(page.path ?? '')}
             placeholder={t('Input page name')}
             onClickOutside={() => { setRenameInputShown(false) }}
             onPressEnter={onPressEnterForRenameHandler}
             inputValidator={inputValidator}
           />
         )}
-        { !isRenameInputShown && ( */}
-        <a href={`/${page._id}`} className="grw-pagetree-title-anchor flex-grow-1">
-          <p className={`text-truncate m-auto ${page.isEmpty && 'text-muted'}`}>{nodePath.basename(page.path ?? '') || '/'}</p>
-        </a>
-        {/* )} */}
+        { !isRenameInputShown && (
+          <a href={`/${page._id}`} className="grw-pagetree-title-anchor flex-grow-1">
+            <p className={`text-truncate m-auto ${page.isEmpty && 'text-muted'}`}>{nodePath.basename(page.path ?? '') || '/'}</p>
+          </a>
+        )}
         {(descendantCount > 0) && (
           <div className="grw-pagetree-count-wrapper">
             <ItemCount descendantCount={descendantCount} />
@@ -464,7 +446,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
             onClickDeleteMenuItem={deleteMenuItemClickHandler}
           >
             {/* pass the color property to reactstrap dropdownToggle props. https://6-4-0--reactstrap.netlify.app/components/dropdowns/  */}
-            <DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control p-0 grw-visible-on-hover">
+            <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 text-muted p-1"></i>
             </DropdownToggle>
           </PageItemControl>
@@ -473,7 +455,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
             className="border-0 rounded btn btn-page-item-control p-0 grw-visible-on-hover"
             onClick={onClickPlusButton}
           >
-            <i className="icon-plus text-muted d-block p-1" />
+            <i className="icon-plus text-muted d-block p-0" />
           </button>
         </div>
       </li>
@@ -497,8 +479,8 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
               isScrolled={props.isScrolled}
               targetPathOrId={targetPathOrId}
               isEnabledAttachTitleHeader={isEnabledAttachTitleHeader}
+              onRenamed={onRenamed}
               onClickDuplicateMenuItem={onClickDuplicateMenuItem}
-              onClickRenameMenuItem={onClickRenameMenuItem}
               onClickDeleteMenuItem={onClickDeleteMenuItem}
             />
           </div>

+ 12 - 19
packages/app/src/components/Sidebar/PageTree/ItemsTree.tsx

@@ -4,11 +4,11 @@ import { useTranslation } from 'react-i18next';
 import { usePageTreeTermManager, useSWRxPageAncestorsChildren, useSWRxRootPage } from '~/stores/page-listing';
 import { TargetAndAncestors } from '~/interfaces/page-listing-results';
 import { IPageHasId, IPageToDeleteWithMeta } from '~/interfaces/page';
-import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
+import { OnDuplicatedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import { SocketEventName, UpdateDescCountData, UpdateDescCountRawData } from '~/interfaces/websocket';
 import { toastError, toastSuccess } from '~/client/util/apiNotification';
 import {
-  IPageForPageDuplicateModal, usePageDuplicateModal, IPageForPageRenameModal, usePageRenameModal, usePageDeleteModal,
+  IPageForPageDuplicateModal, usePageDuplicateModal, usePageDeleteModal,
 } from '~/stores/modal';
 import { smoothScrollIntoView } from '~/client/util/smooth-scroll';
 
@@ -74,8 +74,8 @@ const renderByInitialNode = (
     isScrolled: boolean,
     targetPathOrId?: string,
     isEnabledAttachTitleHeader?: boolean,
+    onRenamed?: () => void,
     onClickDuplicateMenuItem?: (pageToDuplicate: IPageForPageDuplicateModal) => void,
-    onClickRenameMenuItem?: (pageToRename: IPageForPageRenameModal) => void,
     onClickDeleteMenuItem?: (pageToDelete: IPageToDeleteWithMeta) => void,
 ): JSX.Element => {
 
@@ -88,8 +88,8 @@ const renderByInitialNode = (
         isOpen
         isEnabledAttachTitleHeader={isEnabledAttachTitleHeader}
         isEnableActions={isEnableActions}
+        onRenamed={onRenamed}
         onClickDuplicateMenuItem={onClickDuplicateMenuItem}
-        onClickRenameMenuItem={onClickRenameMenuItem}
         onClickDeleteMenuItem={onClickDeleteMenuItem}
         isScrolled={isScrolled}
       />
@@ -125,7 +125,6 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
   const { data: rootPageData, error: error2 } = useSWRxRootPage();
   const { data: isEnabledAttachTitleHeader } = useIsEnabledAttachTitleHeader();
   const { open: openDuplicateModal } = usePageDuplicateModal();
-  const { open: openRenameModal } = usePageRenameModal();
   const { open: openDeleteModal } = usePageDeleteModal();
   const [isScrolled, setIsScrolled] = useState(false);
 
@@ -166,6 +165,12 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
 
   }, [socket, ptDescCountMap, updatePtDescCountMap]);
 
+  const onRenamed = () => {
+    advancePt();
+    advanceFts();
+    advanceDpl();
+  };
+
   const onClickDuplicateMenuItem = (pageToDuplicate: IPageForPageDuplicateModal) => {
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
@@ -179,18 +184,6 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
     openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler });
   };
 
-  const onClickRenameMenuItem = (pageToRename: IPageForPageRenameModal) => {
-    const renamedHandler: OnRenamedFunction = (path) => {
-      toastSuccess(t('renamed_pages', { path }));
-
-      advancePt();
-      advanceFts();
-      advanceDpl();
-    };
-
-    openRenameModal(pageToRename, { onRenamed: renamedHandler });
-  };
-
   const onClickDeleteMenuItem = (pageToDelete: IPageToDeleteWithMeta) => {
     const onDeletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => {
       if (typeof pathOrPathsToDelete !== 'string') {
@@ -227,7 +220,7 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
     const initialNode = generateInitialNodeAfterResponse(ancestorsChildrenData.ancestorsChildren, new ItemNode(rootPageData.rootPage));
     return renderByInitialNode(
       // eslint-disable-next-line max-len
-      initialNode, isEnableActions, isScrolled, targetPathOrId, isEnabledAttachTitleHeader, onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteMenuItem,
+      initialNode, isEnableActions, isScrolled, targetPathOrId, isEnabledAttachTitleHeader, onRenamed, onClickDuplicateMenuItem, onClickDeleteMenuItem,
     );
   }
 
@@ -238,7 +231,7 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
     const initialNode = generateInitialNodeBeforeResponse(targetAndAncestorsData.targetAndAncestors);
     return renderByInitialNode(
       // eslint-disable-next-line max-len
-      initialNode, isEnableActions, isScrolled, targetPathOrId, isEnabledAttachTitleHeader, onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteMenuItem,
+      initialNode, isEnableActions, isScrolled, targetPathOrId, isEnabledAttachTitleHeader, onRenamed, onClickDuplicateMenuItem, onClickDeleteMenuItem,
     );
   }
 

+ 6 - 0
packages/app/src/styles/_page-tree.scss

@@ -5,6 +5,12 @@ $grw-pagetree-item-padding-left: 10px;
 .grw-pagetree {
   min-height: calc(100vh - ($grw-navbar-height + $grw-navbar-border-width + $grw-sidebar-content-header-height + $grw-sidebar-content-footer-height));
 
+  .btn-page-item-control {
+    .icon-plus::before {
+      font-size: 18px;
+    }
+  }
+
   .list-group-item {
     .grw-visible-on-hover {
       display: none;