Browse Source

impl mutatePageTree instead of usePageTreeTermManager

Yuki Takei 3 years ago
parent
commit
b1224a8932

+ 6 - 6
packages/app/src/components/DescendantsPageList.tsx

@@ -15,7 +15,8 @@ import {
 } from '~/stores/context';
 } from '~/stores/context';
 import { useIsTrashPage } from '~/stores/page';
 import { useIsTrashPage } from '~/stores/page';
 import {
 import {
-  usePageTreeTermManager, useDescendantsPageListForCurrentPathTermManager, useSWRxDescendantsPageListForCurrrentPath,
+  mutatePageTree,
+  useDescendantsPageListForCurrentPathTermManager, useSWRxDescendantsPageListForCurrrentPath,
   useSWRxPageInfoForList, useSWRxPageList,
   useSWRxPageInfoForList, useSWRxPageList,
 } from '~/stores/page-listing';
 } from '~/stores/page-listing';
 
 
@@ -53,7 +54,6 @@ export const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element
   let pageWithMetas: IDataWithMeta<IPageHasId, IPageInfoForOperation>[] = [];
   let pageWithMetas: IDataWithMeta<IPageHasId, IPageInfoForOperation>[] = [];
 
 
   // for mutation
   // for mutation
-  const { advance: advancePt } = usePageTreeTermManager();
   const { advance: advanceDpl } = useDescendantsPageListForCurrentPathTermManager();
   const { advance: advanceDpl } = useDescendantsPageListForCurrentPathTermManager();
 
 
   // initial data
   // initial data
@@ -74,23 +74,23 @@ export const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element
       toastSuccess(t('deleted_pages_completely', { path }));
       toastSuccess(t('deleted_pages_completely', { path }));
     }
     }
 
 
-    advancePt();
+    mutatePageTree();
 
 
     if (onPagesDeleted != null) {
     if (onPagesDeleted != null) {
       onPagesDeleted(...args);
       onPagesDeleted(...args);
     }
     }
-  }, [advancePt, onPagesDeleted, t]);
+  }, [onPagesDeleted, t]);
 
 
   const pagePutBackedHandler: OnPutBackedFunction = useCallback((path) => {
   const pagePutBackedHandler: OnPutBackedFunction = useCallback((path) => {
     toastSuccess(t('page_has_been_reverted', { path }));
     toastSuccess(t('page_has_been_reverted', { path }));
 
 
-    advancePt();
+    mutatePageTree();
     advanceDpl();
     advanceDpl();
 
 
     if (onPagePutBacked != null) {
     if (onPagePutBacked != null) {
       onPagePutBacked(path);
       onPagePutBacked(path);
     }
     }
-  }, [advanceDpl, advancePt, onPagePutBacked, t]);
+  }, [advanceDpl, onPagePutBacked, t]);
 
 
   function setPageNumber(selectedPageNumber) {
   function setPageNumber(selectedPageNumber) {
     setActivePage(selectedPageNumber);
     setActivePage(selectedPageNumber);

+ 4 - 6
packages/app/src/components/PageEditor.tsx

@@ -7,7 +7,7 @@ import nodePath from 'path';
 
 
 
 
 import {
 import {
-  IPageHasId, PageGrant, pathUtils,
+  IPageHasId, pathUtils,
 } from '@growi/core';
 } from '@growi/core';
 import detectIndent from 'detect-indent';
 import detectIndent from 'detect-indent';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
@@ -34,7 +34,7 @@ import { useConflictDiffModal } from '~/stores/modal';
 import {
 import {
   useCurrentPagePath, useSWRMUTxCurrentPage, useSWRxCurrentPage, useSWRxTagsInfo,
   useCurrentPagePath, useSWRMUTxCurrentPage, useSWRxCurrentPage, useSWRxTagsInfo,
 } from '~/stores/page';
 } from '~/stores/page';
-import { usePageTreeTermManager } from '~/stores/page-listing';
+import { mutatePageTree } from '~/stores/page-listing';
 import { usePreviewOptions } from '~/stores/renderer';
 import { usePreviewOptions } from '~/stores/renderer';
 import {
 import {
   EditorMode,
   EditorMode,
@@ -92,7 +92,6 @@ const PageEditor = React.memo((): JSX.Element => {
   const { data: isUploadableFile } = useIsUploadableFile();
   const { data: isUploadableFile } = useIsUploadableFile();
   const { data: isUploadableImage } = useIsUploadableImage();
   const { data: isUploadableImage } = useIsUploadableImage();
   const { data: conflictDiffModalStatus, close: closeConflictDiffModal } = useConflictDiffModal();
   const { data: conflictDiffModalStatus, close: closeConflictDiffModal } = useConflictDiffModal();
-  const { advance: advancePt } = usePageTreeTermManager();
 
 
   const { data: rendererOptions, mutate: mutateRendererOptions } = usePreviewOptions();
   const { data: rendererOptions, mutate: mutateRendererOptions } = usePreviewOptions();
   const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
   const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
@@ -211,7 +210,7 @@ const PageEditor = React.memo((): JSX.Element => {
       );
       );
 
 
       // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
       // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
-      advancePt();
+      mutatePageTree();
 
 
       return page;
       return page;
     }
     }
@@ -229,8 +228,7 @@ const PageEditor = React.memo((): JSX.Element => {
       return null;
       return null;
     }
     }
 
 
-  // eslint-disable-next-line max-len
-  }, [currentPathname, optionsToSave, grantData, isSlackEnabled, saveOrUpdate, pageId, currentPagePath, currentRevisionId, advancePt]);
+  }, [currentPathname, optionsToSave, grantData, isSlackEnabled, saveOrUpdate, pageId, currentPagePath, currentRevisionId]);
 
 
   const saveAndReturnToViewHandler = useCallback(async(opts: {slackChannels: string, overwriteScopesOfDescendants?: boolean}) => {
   const saveAndReturnToViewHandler = useCallback(async(opts: {slackChannels: string, overwriteScopesOfDescendants?: boolean}) => {
     if (editorMode !== EditorMode.Editor) {
     if (editorMode !== EditorMode.Editor) {

+ 6 - 8
packages/app/src/components/PageEditorByHackmd.tsx

@@ -27,7 +27,7 @@ import {
 import {
 import {
   useCurrentPagePath, useSWRMUTxCurrentPage, useSWRxCurrentPage, useSWRxTagsInfo,
   useCurrentPagePath, useSWRMUTxCurrentPage, useSWRxCurrentPage, useSWRxTagsInfo,
 } from '~/stores/page';
 } from '~/stores/page';
-import { usePageTreeTermManager } from '~/stores/page-listing';
+import { mutatePageTree } from '~/stores/page-listing';
 import { useRemoteRevisionId } from '~/stores/remote-latest-page';
 import { useRemoteRevisionId } from '~/stores/remote-latest-page';
 import {
 import {
   EditorMode,
   EditorMode,
@@ -66,7 +66,6 @@ export const PageEditorByHackmd = (): JSX.Element => {
   const { data: grantData } = useSelectedGrant();
   const { data: grantData } = useSelectedGrant();
   const { data: hackmdUri } = useHackmdUri();
   const { data: hackmdUri } = useHackmdUri();
   const saveOrUpdate = useSaveOrUpdate();
   const saveOrUpdate = useSaveOrUpdate();
-  const { advance: advancePt } = usePageTreeTermManager();
 
 
   const { returnPathForURL } = pathUtils;
   const { returnPathForURL } = pathUtils;
 
 
@@ -134,7 +133,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
         mutateIsHackmdDraftUpdatingInRealtime(false);
         mutateIsHackmdDraftUpdatingInRealtime(false);
 
 
         // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
         // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
-        advancePt();
+        mutatePageTree();
       }
       }
       setIsInitialized(false);
       setIsInitialized(false);
       mutateEditorMode(EditorMode.View);
       mutateEditorMode(EditorMode.View);
@@ -144,7 +143,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
       toastError(error.message);
       toastError(error.message);
     }
     }
   // eslint-disable-next-line max-len
   // eslint-disable-next-line max-len
-  }, [editorMode, currentPathname, revision, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, pageId, currentPagePath, isNotFound, mutateEditorMode, router, updateStateAfterSave, mutateIsHackmdDraftUpdatingInRealtime, advancePt]);
+  }, [editorMode, currentPathname, revision, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, pageId, currentPagePath, isNotFound, mutateEditorMode, router, updateStateAfterSave, mutateIsHackmdDraftUpdatingInRealtime]);
 
 
   // set handler to save and reload Page
   // set handler to save and reload Page
   useEffect(() => {
   useEffect(() => {
@@ -267,7 +266,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
       mutateTagsInfo();
       mutateTagsInfo();
 
 
       // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
       // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
-      advancePt();
+      mutatePageTree();
 
 
       mutateIsEnabledUnsavedWarning(false);
       mutateIsEnabledUnsavedWarning(false);
 
 
@@ -279,9 +278,8 @@ export const PageEditorByHackmd = (): JSX.Element => {
       logger.error('failed to save', error);
       logger.error('failed to save', error);
       toastError(error.message);
       toastError(error.message);
     }
     }
-  }, [
-    currentPagePath, currentPathname, pageId, revisionIdHackmdSynced, optionsToSave,
-    saveOrUpdate, mutatePageData, updateStateAfterSave, mutateTagsInfo, advancePt, mutateIsEnabledUnsavedWarning, t]);
+  // eslint-disable-next-line max-len
+  }, [currentPagePath, currentPathname, pageId, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, mutatePageData, updateStateAfterSave, mutateTagsInfo, mutateIsEnabledUnsavedWarning, t]);
 
 
   /**
   /**
    * onChange event of HackmdEditor handler
    * onChange event of HackmdEditor handler

+ 8 - 8
packages/app/src/components/PrivateLegacyPages.tsx

@@ -18,7 +18,7 @@ import { useCurrentUser } from '~/stores/context';
 import {
 import {
   ILegacyPrivatePage, usePrivateLegacyPagesMigrationModal,
   ILegacyPrivatePage, usePrivateLegacyPagesMigrationModal,
 } from '~/stores/modal';
 } from '~/stores/modal';
-import { usePageTreeTermManager, useSWRxV5MigrationStatus } from '~/stores/page-listing';
+import { mutatePageTree, useSWRxV5MigrationStatus } from '~/stores/page-listing';
 import {
 import {
   useSWRxSearch,
   useSWRxSearch,
 } from '~/stores/search';
 } from '~/stores/search';
@@ -213,13 +213,12 @@ const PrivateLegacyPages = (): JSX.Element => {
   });
   });
 
 
   const { data: migrationStatus, mutate: mutateMigrationStatus } = useSWRxV5MigrationStatus();
   const { data: migrationStatus, mutate: mutateMigrationStatus } = useSWRxV5MigrationStatus();
-  const { advance: advancePt } = usePageTreeTermManager();
 
 
   const searchInvokedHandler = useCallback((_keyword: string) => {
   const searchInvokedHandler = useCallback((_keyword: string) => {
     mutateMigrationStatus();
     mutateMigrationStatus();
     setKeyword(_keyword);
     setKeyword(_keyword);
     setOffset(0);
     setOffset(0);
-  }, []);
+  }, [mutateMigrationStatus]);
 
 
   const { open: openModal, close: closeModal } = usePrivateLegacyPagesMigrationModal();
   const { open: openModal, close: closeModal } = usePrivateLegacyPagesMigrationModal();
   const { data: socket } = useGlobalSocket();
   const { data: socket } = useGlobalSocket();
@@ -245,7 +244,7 @@ const PrivateLegacyPages = (): JSX.Element => {
       socket?.off(SocketEventName.PageMigrationSuccess);
       socket?.off(SocketEventName.PageMigrationSuccess);
       socket?.off(SocketEventName.PageMigrationError);
       socket?.off(SocketEventName.PageMigrationError);
     };
     };
-  }, [socket]);
+  }, [socket, t]);
 
 
   const selectAllCheckboxChangedHandler = useCallback((isChecked: boolean) => {
   const selectAllCheckboxChangedHandler = useCallback((isChecked: boolean) => {
     const instance = searchPageBaseRef.current;
     const instance = searchPageBaseRef.current;
@@ -315,10 +314,10 @@ const PrivateLegacyPages = (): JSX.Element => {
         closeModal();
         closeModal();
         mutateMigrationStatus();
         mutateMigrationStatus();
         mutate();
         mutate();
-        advancePt();
+        mutatePageTree();
       },
       },
     );
     );
-  }, [data, mutate, openModal, closeModal, mutateMigrationStatus]);
+  }, [data, openModal, t, closeModal, mutateMigrationStatus, mutate]);
 
 
   const pagingSizeChangedHandler = useCallback((pagingSize: number) => {
   const pagingSizeChangedHandler = useCallback((pagingSize: number) => {
     setOffset(0);
     setOffset(0);
@@ -381,7 +380,8 @@ const PrivateLegacyPages = (): JSX.Element => {
         {isAdmin && renderOpenModalButton()}
         {isAdmin && renderOpenModalButton()}
       </div>
       </div>
     );
     );
-  }, [convertMenuItemClickedHandler, deleteAllButtonClickedHandler, hitsCount, isControlEnabled, selectAllCheckboxChangedHandler, t]);
+  // eslint-disable-next-line max-len
+  }, [convertMenuItemClickedHandler, deleteAllButtonClickedHandler, hitsCount, isAdmin, isControlEnabled, renderOpenModalButton, selectAllCheckboxChangedHandler, t]);
 
 
   const searchControl = useMemo(() => {
   const searchControl = useMemo(() => {
     return (
     return (
@@ -455,7 +455,7 @@ const PrivateLegacyPages = (): JSX.Element => {
             toastSuccess(t('private_legacy_pages.by_path_modal.success'));
             toastSuccess(t('private_legacy_pages.by_path_modal.success'));
             setOpenConvertModal(false);
             setOpenConvertModal(false);
             mutate();
             mutate();
-            advancePt();
+            mutatePageTree();
           }
           }
           catch (errs) {
           catch (errs) {
             if (errs.length === 1) {
             if (errs.length === 1) {

+ 2 - 5
packages/app/src/components/SearchPage/SearchPageBase.tsx

@@ -11,7 +11,7 @@ import { IFormattedSearchResult, IPageWithSearchMeta } from '~/interfaces/search
 import { OnDeletedFunction } from '~/interfaces/ui';
 import { OnDeletedFunction } from '~/interfaces/ui';
 import { useIsGuestUser, useIsSearchServiceConfigured, useIsSearchServiceReachable } from '~/stores/context';
 import { useIsGuestUser, useIsSearchServiceConfigured, useIsSearchServiceReachable } from '~/stores/context';
 import { usePageDeleteModal } from '~/stores/modal';
 import { usePageDeleteModal } from '~/stores/modal';
-import { usePageTreeTermManager } from '~/stores/page-listing';
+import { mutatePageTree } from '~/stores/page-listing';
 
 
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 
 
@@ -228,9 +228,6 @@ export const usePageDeleteModalForBulkDeletion = (
 
 
   const { open: openDeleteModal } = usePageDeleteModal();
   const { open: openDeleteModal } = usePageDeleteModal();
 
 
-  // for PageTree mutation
-  const { advance: advancePt } = usePageTreeTermManager();
-
   return () => {
   return () => {
     if (data == null) {
     if (data == null) {
       return;
       return;
@@ -260,7 +257,7 @@ export const usePageDeleteModalForBulkDeletion = (
         else {
         else {
           toastSuccess(t('deleted_pages_completely', { path }));
           toastSuccess(t('deleted_pages_completely', { path }));
         }
         }
-        advancePt();
+        mutatePageTree();
 
 
         if (onDeleted != null) {
         if (onDeleted != null) {
           onDeleted(...args);
           onDeleted(...args);

+ 7 - 8
packages/app/src/components/SearchPage/SearchResultContent.tsx

@@ -18,7 +18,7 @@ import { useCurrentUser, useIsContainerFluid } from '~/stores/context';
 import {
 import {
   usePageDuplicateModal, usePageRenameModal, usePageDeleteModal,
   usePageDuplicateModal, usePageRenameModal, usePageDeleteModal,
 } from '~/stores/modal';
 } from '~/stores/modal';
-import { useDescendantsPageListForCurrentPathTermManager, usePageTreeTermManager } from '~/stores/page-listing';
+import { mutatePageTree, useDescendantsPageListForCurrentPathTermManager } from '~/stores/page-listing';
 import { useSearchResultOptions } from '~/stores/renderer';
 import { useSearchResultOptions } from '~/stores/renderer';
 import { useFullTextSearchTermManager } from '~/stores/search';
 import { useFullTextSearchTermManager } from '~/stores/search';
 
 
@@ -92,7 +92,6 @@ export const SearchResultContent: FC<Props> = (props: Props) => {
   const [isPageCommentLoaded, setPageCommentLoaded] = useState(false);
   const [isPageCommentLoaded, setPageCommentLoaded] = useState(false);
 
 
   // for mutation
   // for mutation
-  const { advance: advancePt } = usePageTreeTermManager();
   const { advance: advanceFts } = useFullTextSearchTermManager();
   const { advance: advanceFts } = useFullTextSearchTermManager();
   const { advance: advanceDpl } = useDescendantsPageListForCurrentPathTermManager();
   const { advance: advanceDpl } = useDescendantsPageListForCurrentPathTermManager();
 
 
@@ -167,23 +166,23 @@ export const SearchResultContent: FC<Props> = (props: Props) => {
     const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
     const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
       toastSuccess(t('duplicated_pages', { fromPath }));
       toastSuccess(t('duplicated_pages', { fromPath }));
 
 
-      advancePt();
+      mutatePageTree();
       advanceFts();
       advanceFts();
       advanceDpl();
       advanceDpl();
     };
     };
     openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler });
     openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler });
-  }, [advanceDpl, advanceFts, advancePt, openDuplicateModal, t]);
+  }, [advanceDpl, advanceFts, openDuplicateModal, t]);
 
 
   const renameItemClickedHandler = useCallback((pageToRename: IPageToRenameWithMeta) => {
   const renameItemClickedHandler = useCallback((pageToRename: IPageToRenameWithMeta) => {
     const renamedHandler: OnRenamedFunction = (path) => {
     const renamedHandler: OnRenamedFunction = (path) => {
       toastSuccess(t('renamed_pages', { path }));
       toastSuccess(t('renamed_pages', { path }));
 
 
-      advancePt();
+      mutatePageTree();
       advanceFts();
       advanceFts();
       advanceDpl();
       advanceDpl();
     };
     };
     openRenameModal(pageToRename, { onRenamed: renamedHandler });
     openRenameModal(pageToRename, { onRenamed: renamedHandler });
-  }, [advanceDpl, advanceFts, advancePt, openRenameModal, t]);
+  }, [advanceDpl, advanceFts, openRenameModal, t]);
 
 
   const onDeletedHandler: OnDeletedFunction = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => {
   const onDeletedHandler: OnDeletedFunction = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => {
     if (typeof pathOrPathsToDelete !== 'string') {
     if (typeof pathOrPathsToDelete !== 'string') {
@@ -197,10 +196,10 @@ export const SearchResultContent: FC<Props> = (props: Props) => {
     else {
     else {
       toastSuccess(t('deleted_pages', { path }));
       toastSuccess(t('deleted_pages', { path }));
     }
     }
-    advancePt();
+    mutatePageTree();
     advanceFts();
     advanceFts();
     advanceDpl();
     advanceDpl();
-  }, [advanceDpl, advanceFts, advancePt, t]);
+  }, [advanceDpl, advanceFts, t]);
 
 
   const deleteItemClickedHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
   const deleteItemClickedHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
     openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler });
     openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler });

+ 4 - 5
packages/app/src/components/SearchPage/SearchResultList.tsx

@@ -13,7 +13,7 @@ import {
 import { IPageSearchMeta, IPageWithSearchMeta } from '~/interfaces/search';
 import { IPageSearchMeta, IPageWithSearchMeta } from '~/interfaces/search';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import { useIsGuestUser } from '~/stores/context';
 import { useIsGuestUser } from '~/stores/context';
-import { useSWRxPageInfoForList, usePageTreeTermManager } from '~/stores/page-listing';
+import { mutatePageTree, useSWRxPageInfoForList } from '~/stores/page-listing';
 import { useFullTextSearchTermManager } from '~/stores/search';
 import { useFullTextSearchTermManager } from '~/stores/search';
 
 
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
@@ -45,7 +45,6 @@ const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props>
   const { data: idToPageInfo } = useSWRxPageInfoForList(pageIdsWithNoSnippet, null, true, true);
   const { data: idToPageInfo } = useSWRxPageInfoForList(pageIdsWithNoSnippet, null, true, true);
 
 
   // for mutation
   // for mutation
-  const { advance: advancePt } = usePageTreeTermManager();
   const { advance: advanceFts } = useFullTextSearchTermManager();
   const { advance: advanceFts } = useFullTextSearchTermManager();
 
 
   const itemsRef = useRef<(ISelectable|null)[]>([]);
   const itemsRef = useRef<(ISelectable|null)[]>([]);
@@ -98,14 +97,14 @@ const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props>
   const duplicatedHandler : OnDuplicatedFunction = (fromPath, toPath) => {
   const duplicatedHandler : OnDuplicatedFunction = (fromPath, toPath) => {
     toastSuccess(t('duplicated_pages', { fromPath }));
     toastSuccess(t('duplicated_pages', { fromPath }));
 
 
-    advancePt();
+    mutatePageTree();
     advanceFts();
     advanceFts();
   };
   };
 
 
   const renamedHandler: OnRenamedFunction = (path) => {
   const renamedHandler: OnRenamedFunction = (path) => {
     toastSuccess(t('renamed_pages', { path }));
     toastSuccess(t('renamed_pages', { path }));
 
 
-    advancePt();
+    mutatePageTree();
     advanceFts();
     advanceFts();
   };
   };
   const deletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => {
   const deletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => {
@@ -121,7 +120,7 @@ const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props>
     else {
     else {
       toastSuccess(t('deleted_pages', { path }));
       toastSuccess(t('deleted_pages', { path }));
     }
     }
-    advancePt();
+    mutatePageTree();
     advanceFts();
     advanceFts();
   };
   };
 
 

+ 7 - 8
packages/app/src/components/Sidebar/PageTree/ItemsTree.tsx

@@ -18,7 +18,7 @@ import {
 } from '~/stores/modal';
 } from '~/stores/modal';
 import { useCurrentPagePath, usePageInfoTermManager, useSWRMUTxCurrentPage } from '~/stores/page';
 import { useCurrentPagePath, usePageInfoTermManager, useSWRMUTxCurrentPage } from '~/stores/page';
 import {
 import {
-  usePageTreeTermManager, useSWRxPageAncestorsChildren, useSWRxRootPage, useDescendantsPageListForCurrentPathTermManager,
+  useSWRxPageAncestorsChildren, useSWRxRootPage, useDescendantsPageListForCurrentPathTermManager, mutatePageTree,
 } from '~/stores/page-listing';
 } from '~/stores/page-listing';
 import { useFullTextSearchTermManager } from '~/stores/search';
 import { useFullTextSearchTermManager } from '~/stores/search';
 import { usePageTreeDescCountMap, useSidebarScrollerRef } from '~/stores/ui';
 import { usePageTreeDescCountMap, useSidebarScrollerRef } from '~/stores/ui';
@@ -118,7 +118,6 @@ const ItemsTree = (props: ItemsTreeProps): JSX.Element => {
 
 
   // for mutation
   // for mutation
   const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage();
   const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage();
-  const { advance: advancePt } = usePageTreeTermManager();
   const { advance: advanceFts } = useFullTextSearchTermManager();
   const { advance: advanceFts } = useFullTextSearchTermManager();
   const { advance: advanceDpl } = useDescendantsPageListForCurrentPathTermManager();
   const { advance: advanceDpl } = useDescendantsPageListForCurrentPathTermManager();
   const { advance: advancePi } = usePageInfoTermManager();
   const { advance: advancePi } = usePageInfoTermManager();
@@ -151,27 +150,27 @@ const ItemsTree = (props: ItemsTreeProps): JSX.Element => {
   }, [socket, ptDescCountMap, updatePtDescCountMap]);
   }, [socket, ptDescCountMap, updatePtDescCountMap]);
 
 
   const onRenamed = useCallback((fromPath: string | undefined, toPath: string) => {
   const onRenamed = useCallback((fromPath: string | undefined, toPath: string) => {
-    advancePt();
+    mutatePageTree();
     advanceFts();
     advanceFts();
     advanceDpl();
     advanceDpl();
 
 
     if (currentPagePath === fromPath || currentPagePath === toPath) {
     if (currentPagePath === fromPath || currentPagePath === toPath) {
       mutateCurrentPage();
       mutateCurrentPage();
     }
     }
-  }, [advanceDpl, advanceFts, advancePt, currentPagePath, mutateCurrentPage]);
+  }, [advanceDpl, advanceFts, currentPagePath, mutateCurrentPage]);
 
 
   const onClickDuplicateMenuItem = useCallback((pageToDuplicate: IPageForPageDuplicateModal) => {
   const onClickDuplicateMenuItem = useCallback((pageToDuplicate: IPageForPageDuplicateModal) => {
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
     const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
       toastSuccess(t('duplicated_pages', { fromPath }));
       toastSuccess(t('duplicated_pages', { fromPath }));
 
 
-      advancePt();
+      mutatePageTree();
       advanceFts();
       advanceFts();
       advanceDpl();
       advanceDpl();
     };
     };
 
 
     openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler });
     openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler });
-  }, [advanceDpl, advanceFts, advancePt, openDuplicateModal, t]);
+  }, [advanceDpl, advanceFts, openDuplicateModal, t]);
 
 
   const onClickDeleteMenuItem = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
   const onClickDeleteMenuItem = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
     const onDeletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => {
     const onDeletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => {
@@ -188,7 +187,7 @@ const ItemsTree = (props: ItemsTreeProps): JSX.Element => {
         toastSuccess(t('deleted_pages', { path }));
         toastSuccess(t('deleted_pages', { path }));
       }
       }
 
 
-      advancePt();
+      mutatePageTree();
       advanceFts();
       advanceFts();
       advanceDpl();
       advanceDpl();
       advancePi();
       advancePi();
@@ -200,7 +199,7 @@ const ItemsTree = (props: ItemsTreeProps): JSX.Element => {
     };
     };
 
 
     openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler });
     openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler });
-  }, [advanceDpl, advanceFts, advancePi, advancePt, currentPagePath, mutateCurrentPage, openDeleteModal, router, t]);
+  }, [advanceDpl, advanceFts, advancePi, currentPagePath, mutateCurrentPage, openDeleteModal, router, t]);
 
 
   // ***************************  Scroll on init ***************************
   // ***************************  Scroll on init ***************************
   const scrollOnInit = useCallback(() => {
   const scrollOnInit = useCallback(() => {

+ 34 - 15
packages/app/src/stores/page-listing.tsx

@@ -1,5 +1,7 @@
+import assert from 'assert';
+
 import { Nullable, HasObjectId } from '@growi/core';
 import { Nullable, HasObjectId } from '@growi/core';
-import useSWR, { SWRResponse } from 'swr';
+import useSWR, { Arguments, mutate, SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 import useSWRImmutable from 'swr/immutable';
 import useSWRInfinite, { SWRInfiniteResponse } from 'swr/infinite';
 import useSWRInfinite, { SWRInfiniteResponse } from 'swr/infinite';
 
 
@@ -133,10 +135,6 @@ export const useSWRxPageInfoForList = (
   };
   };
 };
 };
 
 
-export const usePageTreeTermManager = (isDisabled?: boolean) : SWRResponse<number, Error> & ITermNumberManagerUtil => {
-  return useTermNumberManager(isDisabled === true ? null : 'pageTreeTermManager');
-};
-
 export const useSWRxRootPage = (): SWRResponse<RootPageResult, Error> => {
 export const useSWRxRootPage = (): SWRResponse<RootPageResult, Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
     '/page-listing/root',
     '/page-listing/root',
@@ -145,27 +143,41 @@ export const useSWRxRootPage = (): SWRResponse<RootPageResult, Error> => {
         rootPage: response.data.rootPage,
         rootPage: response.data.rootPage,
       };
       };
     }),
     }),
+    {
+      keepPreviousData: true,
+    },
   );
   );
 };
 };
 
 
+const MUTATION_ID_FOR_PAGETREE = 'pageTree';
+const keyMatcherForPageTree = (key: Arguments): boolean => {
+  return Array.isArray(key) && key[0] === MUTATION_ID_FOR_PAGETREE;
+};
+export const mutatePageTree = async(): Promise<undefined[]> => {
+  return mutate(keyMatcherForPageTree);
+};
+
 export const useSWRxPageAncestorsChildren = (
 export const useSWRxPageAncestorsChildren = (
     path: string | null,
     path: string | null,
 ): SWRResponse<AncestorsChildrenResult, Error> => {
 ): SWRResponse<AncestorsChildrenResult, Error> => {
-  const { data: termNumber } = usePageTreeTermManager();
+  const key = path ? [MUTATION_ID_FOR_PAGETREE, '/page-listing/ancestors-children', path] : null;
 
 
-  // HACKME: Consider using global mutation from useSWRConfig and not to use term number -- 2022/12/08 @hakumizuki
-  const prevTermNumber = termNumber ? termNumber - 1 : 0;
-  const prevSWRRes = useSWRImmutable(path ? [`/page-listing/ancestors-children?path=${path}`, prevTermNumber] : null);
+  // take care of the degration
+  // see: https://github.com/weseek/growi/pull/7038
+
+  if (key != null) {
+    assert(keyMatcherForPageTree(key));
+  }
 
 
   return useSWRImmutable(
   return useSWRImmutable(
-    path ? [`/page-listing/ancestors-children?path=${path}`, termNumber] : null,
-    ([endpoint]) => apiv3Get(endpoint).then((response) => {
+    key,
+    ([, endpoint, path]) => apiv3Get(endpoint, { path }).then((response) => {
       return {
       return {
         ancestorsChildren: response.data.ancestorsChildren,
         ancestorsChildren: response.data.ancestorsChildren,
       };
       };
     }),
     }),
     {
     {
-      fallbackData: prevSWRRes.data, // avoid data to be undefined due to the termNumber to change
+      keepPreviousData: true,
     },
     },
   );
   );
 };
 };
@@ -173,15 +185,22 @@ export const useSWRxPageAncestorsChildren = (
 export const useSWRxPageChildren = (
 export const useSWRxPageChildren = (
     id?: string | null,
     id?: string | null,
 ): SWRResponse<ChildrenResult, Error> => {
 ): SWRResponse<ChildrenResult, Error> => {
-  const { data: termNumber } = usePageTreeTermManager();
+  const key = id ? [MUTATION_ID_FOR_PAGETREE, '/page-listing/children', id] : null;
+
+  if (key != null) {
+    assert(keyMatcherForPageTree(key));
+  }
 
 
   return useSWR(
   return useSWR(
-    id ? [`/page-listing/children?id=${id}`, termNumber] : null,
-    ([endpoint]) => apiv3Get(endpoint).then((response) => {
+    key,
+    ([, endpoint, id]) => apiv3Get(endpoint, { id }).then((response) => {
       return {
       return {
         children: response.data.children,
         children: response.data.children,
       };
       };
     }),
     }),
+    {
+      keepPreviousData: true,
+    },
   );
   );
 };
 };