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

Merge pull request #5259 from weseek/imprv/87710-show-page-rename-modal-by-clicking-on-pagetree-drop-down-menu

show rename modal
cao 4 лет назад
Родитель
Сommit
84e6d16db6

+ 10 - 2
packages/app/src/components/Common/Dropdown/PageItemControl.tsx

@@ -24,7 +24,7 @@ type CommonProps = {
   showBookmarkMenuItem?: boolean,
   onClickBookmarkMenuItem?: (pageId: string, newValue?: boolean) => Promise<void>,
   onClickDuplicateMenuItem?: () => Promise<void> | void,
-  onClickRenameMenuItem?: (pageId: string) => void,
+  onClickRenameMenuItem?: (pageId: string) => Promise<void> | void,
   onClickDeleteMenuItem?: (pageId: string) => void,
 
   additionalMenuItemRenderer?: React.FunctionComponent<AdditionalMenuItemsRendererProps>,
@@ -167,7 +167,7 @@ export const PageItemControlSubstance = (props: PageItemControlSubstanceProps):
   const {
     pageId, pageInfo: presetPageInfo, fetchOnInit,
     children,
-    onClickBookmarkMenuItem, onClickDuplicateMenuItem,
+    onClickBookmarkMenuItem, onClickDuplicateMenuItem, onClickRenameMenuItem,
   } = props;
 
   const [isOpen, setIsOpen] = useState(false);
@@ -197,6 +197,13 @@ export const PageItemControlSubstance = (props: PageItemControlSubstanceProps):
     await onClickDuplicateMenuItem();
   }, [onClickDuplicateMenuItem]);
 
+  const renameMenuItemClickHandler = useCallback(async() => {
+    if (onClickRenameMenuItem == null) {
+      return;
+    }
+    await onClickRenameMenuItem(pageId);
+  }, [onClickRenameMenuItem, pageId]);
+
   return (
     <Dropdown isOpen={isOpen} toggle={() => setIsOpen(!isOpen)}>
 
@@ -212,6 +219,7 @@ export const PageItemControlSubstance = (props: PageItemControlSubstanceProps):
         pageInfo={fetchedPageInfo ?? presetPageInfo}
         onClickBookmarkMenuItem={bookmarkMenuItemClickHandler}
         onClickDuplicateMenuItem={duplicateMenuItemClickHandler}
+        onClickRenameMenuItem={renameMenuItemClickHandler}
       />
     </Dropdown>
   );

+ 57 - 35
packages/app/src/components/Sidebar/PageTree/Item.tsx

@@ -26,6 +26,7 @@ interface ItemProps {
   targetPathOrId?: string
   isOpen?: boolean
   onClickDuplicateMenuItem?(pageId: string, path: string): void
+  onClickRenameMenuItem?(pageId: string, revisionId: string, path: string): void
   onClickDeleteByPage?(pageToDelete: IPageForPageDeleteModal | null): void
 }
 
@@ -67,7 +68,7 @@ const ItemCount: FC<ItemCountProps> = (props:ItemCountProps) => {
 const Item: FC<ItemProps> = (props: ItemProps) => {
   const { t } = useTranslation();
   const {
-    itemNode, targetPathOrId, isOpen: _isOpen = false, onClickDuplicateMenuItem, onClickDeleteByPage, isEnableActions,
+    itemNode, targetPathOrId, isOpen: _isOpen = false, onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteByPage, isEnableActions,
   } = props;
 
   const { page, children } = itemNode;
@@ -76,7 +77,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
   const [currentChildren, setCurrentChildren] = useState(children);
   const [isOpen, setIsOpen] = useState(_isOpen);
   const [isNewPageInputShown, setNewPageInputShown] = useState(false);
-  const [isRenameInputShown, setRenameInputShown] = useState(false);
+  // const [isRenameInputShown, setRenameInputShown] = useState(false);
 
   const { data, error } = useSWRxPageChildren(isOpen ? page._id : null);
 
@@ -140,6 +141,51 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
     onClickDuplicateMenuItem(pageId, path);
   }, [onClickDuplicateMenuItem, page]);
 
+
+  /*
+  * 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) => {
+  //   if (inputText == null || inputText === '' || inputText.trim() === '' || inputText.includes('/')) {
+  //     return;
+  //   }
+
+  //   const parentPath = nodePath.dirname(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) {
+      return;
+    }
+
+    const { _id: pageId, revision: revisionId, path } = page;
+
+    if (pageId == null || revisionId == null || path == null) {
+      throw Error('Any of _id and revisionId and path must not be null.');
+    }
+
+    onClickRenameMenuItem(pageId, revisionId as string, path);
+  }, [onClickRenameMenuItem, page]);
+
+
   const onClickDeleteButton = useCallback(async(_pageId: string): Promise<void> => {
     if (onClickDeleteByPage == null) {
       return;
@@ -161,32 +207,6 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
   }, [page, onClickDeleteByPage]);
 
 
-  const onClickRenameButton = useCallback(async(_pageId: string): Promise<void> => {
-    setRenameInputShown(true);
-  }, []);
-
-  const onPressEnterForRenameHandler = async(inputText: string) => {
-    if (inputText == null || inputText === '' || inputText.trim() === '' || inputText.includes('/')) {
-      return;
-    }
-
-    const parentPath = nodePath.dirname(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);
-    }
-  };
-
-
   // TODO: go to create page page
   const onPressEnterForCreateHandler = () => {
     toastWarning(t('search_result.currently_not_implemented'));
@@ -256,7 +276,8 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
             </button>
           )}
         </div>
-        { isRenameInputShown && (
+        {/* TODO: rename page title on input form by 87757 */}
+        {/* { isRenameInputShown && (
           <ClosableTextInput
             isShown
             value={nodePath.basename(pageTitle as string)}
@@ -266,11 +287,11 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
             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(pageTitle as string) || '/'}</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(pageTitle as string) || '/'}</p>
+        </a>
+        {/* )} */}
         {(page.descendantCount != null && page.descendantCount > 0) && (
           <div className="grw-pagetree-count-wrapper">
             <ItemCount descendantCount={page.descendantCount} />
@@ -284,7 +305,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
             onClickBookmarkMenuItem={bookmarkMenuItemClickHandler}
             onClickDuplicateMenuItem={duplicateMenuItemClickHandler}
             onClickDeleteMenuItem={onClickDeleteButton}
-            onClickRenameMenuItem={onClickRenameButton}
+            onClickRenameMenuItem={renameMenuItemClickHandler}
           >
             <DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control p-0">
               <i className="icon-options fa fa-rotate-90 text-muted p-1"></i>
@@ -318,6 +339,7 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
               isOpen={false}
               targetPathOrId={targetPathOrId}
               onClickDuplicateMenuItem={onClickDuplicateMenuItem}
+              onClickRenameMenuItem={onClickRenameMenuItem}
               onClickDeleteByPage={onClickDeleteByPage}
             />
           </div>

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

@@ -6,7 +6,9 @@ import Item from './Item';
 import { useSWRxPageAncestorsChildren, useSWRxRootPage } from '../../../stores/page-listing';
 import { TargetAndAncestors } from '~/interfaces/page-listing-results';
 import { toastError } from '~/client/util/apiNotification';
-import { IPageForPageDeleteModal, usePageDuplicateModalStatus, usePageDeleteModalStatus } from '~/stores/ui';
+import {
+  IPageForPageDeleteModal, usePageDuplicateModalStatus, usePageRenameModalStatus, usePageDeleteModalStatus,
+} from '~/stores/ui';
 
 /*
  * Utility to generate initial node
@@ -59,6 +61,7 @@ const renderByInitialNode = (
     isEnableActions: boolean,
     targetPathOrId?: string,
     onClickDuplicateMenuItem?: (pageId: string, path: string) => void,
+    onClickRenameMenuItem?: (pageId: string, revisionId: string, path: string) => void,
     onClickDeleteByPage?: (pageToDelete: IPageForPageDeleteModal | null) => void,
 ): JSX.Element => {
 
@@ -71,6 +74,7 @@ const renderByInitialNode = (
         isOpen
         isEnableActions={isEnableActions}
         onClickDuplicateMenuItem={onClickDuplicateMenuItem}
+        onClickRenameMenuItem={onClickRenameMenuItem}
         onClickDeleteByPage={onClickDeleteByPage}
       />
     </ul>
@@ -89,12 +93,17 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
   const { data: ancestorsChildrenData, error: error1 } = useSWRxPageAncestorsChildren(targetPath);
   const { data: rootPageData, error: error2 } = useSWRxRootPage();
   const { open: openDuplicateModal } = usePageDuplicateModalStatus();
+  const { open: openRenameModal } = usePageRenameModalStatus();
   const { open: openDeleteModal } = usePageDeleteModalStatus();
 
   const onClickDuplicateMenuItem = (pageId: string, path: string) => {
     openDuplicateModal(pageId, path);
   };
 
+  const onClickRenameMenuItem = (pageId: string, revisionId: string, path: string) => {
+    openRenameModal(pageId, revisionId, path);
+  };
+
   const onClickDeleteByPage = (pageToDelete: IPageForPageDeleteModal) => {
     openDeleteModal([pageToDelete]);
   };
@@ -110,7 +119,7 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
    */
   if (ancestorsChildrenData != null && rootPageData != null) {
     const initialNode = generateInitialNodeAfterResponse(ancestorsChildrenData.ancestorsChildren, new ItemNode(rootPageData.rootPage));
-    return renderByInitialNode(initialNode, isEnableActions, targetPathOrId, onClickDuplicateMenuItem, onClickDeleteByPage);
+    return renderByInitialNode(initialNode, isEnableActions, targetPathOrId, onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteByPage);
   }
 
   /*
@@ -118,7 +127,7 @@ const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
    */
   if (targetAndAncestorsData != null) {
     const initialNode = generateInitialNodeBeforeResponse(targetAndAncestorsData.targetAndAncestors);
-    return renderByInitialNode(initialNode, isEnableActions, targetPathOrId, onClickDuplicateMenuItem, onClickDeleteByPage);
+    return renderByInitialNode(initialNode, isEnableActions, targetPathOrId, onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteByPage);
   }
 
   return null;