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

Merge pull request #6552 from weseek/fix/104363-rendering-trash-page

fix:  Rendering trash page
Shun Miyazawa 3 лет назад
Родитель
Сommit
6623adb2cd

+ 1 - 1
packages/app/src/client/services/ContextExtractor.tsx

@@ -145,7 +145,7 @@ const ContextExtractorOnce: FC = () => {
   useIsIdenticalPath(isIdenticalPath);
   useIsNotCreatable(isNotCreatable);
   useIsForbidden(isForbidden);
-  useIsTrashPage(isTrashPage);
+  // useIsTrashPage(isTrashPage);
   useIsUserPage(isUserPage);
   useLastUpdateUsername(lastUpdateUsername);
   useCurrentPageId(pageId);

+ 3 - 3
packages/app/src/components/EmptyTrashButton.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { FC, useCallback } from 'react';
 
 import { useTranslation } from 'next-i18next';
 
@@ -12,7 +12,7 @@ import { useEmptyTrashModal } from '~/stores/modal';
 import { useSWRxDescendantsPageListForCurrrentPath, useSWRxPageInfoForList } from '~/stores/page-listing';
 
 
-const EmptyTrashButton = () => {
+const EmptyTrashButton: FC = () => {
   const { t } = useTranslation();
   const { open: openEmptyTrashModal } = useEmptyTrashModal();
   const { data: pagingResult, mutate } = useSWRxDescendantsPageListForCurrrentPath();
@@ -40,7 +40,6 @@ const EmptyTrashButton = () => {
   }, [t, mutate]);
 
   const emptyTrashClickHandler = () => {
-    if (deletablePages.length === 0) { return }
     openEmptyTrashModal(deletablePages, { onEmptiedTrash: onEmptiedTrashHandler, canDelepeAllPages: pagingResult?.totalCount === deletablePages.length });
   };
 
@@ -49,6 +48,7 @@ const EmptyTrashButton = () => {
       <button
         type="button"
         className="btn btn-outline-secondary rounded-pill text-danger d-flex align-items-center"
+        disabled={deletablePages.length === 0}
         onClick={() => emptyTrashClickHandler()}
       >
         <i className="icon-fw icon-trash"></i>

+ 5 - 6
packages/app/src/components/Navbar/GrowiNavbar.tsx

@@ -19,18 +19,17 @@ import { HasChildren } from '../../interfaces/common';
 import GrowiLogo from '../Icons/GrowiLogo';
 
 import { GlobalSearchProps } from './GlobalSearch';
-import PersonalDropdown from './PersonalDropdown';
 
 import styles from './GrowiNavbar.module.scss';
 
+const PersonalDropdown = dynamic(() => import('./PersonalDropdown'), { ssr: false });
+const InAppNotificationDropdown = dynamic(() => import('../InAppNotification/InAppNotificationDropdown')
+  .then(mod => mod.InAppNotificationDropdown), { ssr: false });
+const AppearanceModeDropdown = dynamic(() => import('./AppearanceModeDropdown').then(mod => mod.AppearanceModeDropdown), { ssr: false });
 
 const NavbarRight = memo((): JSX.Element => {
   const { t } = useTranslation();
 
-  const InAppNotificationDropdown = dynamic(() => import('../InAppNotification/InAppNotificationDropdown')
-    .then(mod => mod.InAppNotificationDropdown), { ssr: false });
-  const AppearanceModeDropdown = dynamic(() => import('./AppearanceModeDropdown').then(mod => mod.AppearanceModeDropdown), { ssr: false });
-
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: isGuestUser } = useIsGuestUser();
 
@@ -71,7 +70,7 @@ const NavbarRight = memo((): JSX.Element => {
         </li>
       </>
     );
-  }, [InAppNotificationDropdown, t, AppearanceModeDropdown, isAuthenticated, openCreateModal, currentPagePath]);
+  }, [t, isAuthenticated, openCreateModal, currentPagePath]);
 
   const notAuthenticatedNavItem = useMemo(() => {
     return (

+ 8 - 5
packages/app/src/components/PagePathNav.tsx

@@ -1,6 +1,6 @@
 import React, { FC } from 'react';
 
-import { DevidedPagePath } from '@growi/core';
+import { DevidedPagePath, pagePathUtils } from '@growi/core';
 import dynamic from 'next/dynamic';
 
 import { useIsNotFound } from '~/stores/context';
@@ -9,6 +9,7 @@ import LinkedPagePath from '../models/linked-page-path';
 
 import PagePathHierarchicalLink from './PagePathHierarchicalLink';
 
+const { isTrashPage } = pagePathUtils;
 
 type Props = {
   pagePath: string,
@@ -17,6 +18,8 @@ type Props = {
   isCompactMode?:boolean,
 }
 
+const CopyDropdown = dynamic(() => import('./Page/CopyDropdown'), { ssr: false });
+
 const PagePathNav: FC<Props> = (props: Props) => {
   const {
     pageId, pagePath, isSingleLineMode, isCompactMode,
@@ -25,7 +28,7 @@ const PagePathNav: FC<Props> = (props: Props) => {
 
   const { data: isNotFound } = useIsNotFound();
 
-  const CopyDropdown = dynamic(() => import('./Page/CopyDropdown'), { ssr: false });
+  const isInTrash = isTrashPage(pagePath);
 
   let formerLink;
   let latterLink;
@@ -33,14 +36,14 @@ const PagePathNav: FC<Props> = (props: Props) => {
   // one line
   if (dPagePath.isRoot || dPagePath.isFormerRoot || isSingleLineMode) {
     const linkedPagePath = new LinkedPagePath(pagePath);
-    latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePath} />;
+    latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePath} isInTrash={isInTrash} />;
   }
   // two line
   else {
     const linkedPagePathFormer = new LinkedPagePath(dPagePath.former);
     const linkedPagePathLatter = new LinkedPagePath(dPagePath.latter);
-    formerLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePathFormer} />;
-    latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePathLatter} basePath={dPagePath.former} />;
+    formerLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePathFormer} isInTrash={isInTrash} />;
+    latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePathLatter} basePath={dPagePath.former} isInTrash={isInTrash} />;
   }
 
   const copyDropdownId = `copydropdown${isCompactMode ? '-subnav-compact' : ''}-${pageId}`;

+ 0 - 1
packages/app/src/pages/[[...path]].page.tsx

@@ -242,7 +242,6 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
 
   useCurrentPageId(pageId);
   useSWRxCurrentPage(undefined, pageWithMeta?.data); // store initial data
-  useIsTrashPage(_isTrashPage(pagePath));
   useIsUserPage(isUserPage(pagePath));
   useIsNotCreatable(props.isForbidden || !isCreatablePage(pagePath)); // TODO: need to include props.isIdentical
   useCurrentPagePath(pagePath);

+ 16 - 7
packages/app/src/pages/trash.page.tsx

@@ -1,18 +1,19 @@
+import React from 'react';
+
 import {
   IUser, IUserHasId,
 } from '@growi/core';
-
-import dynamic from 'next/dynamic';
 import { NextPage, GetServerSideProps, GetServerSidePropsContext } from 'next';
+import dynamic from 'next/dynamic';
 
-import GrowiContextualSubNavigation from '~/components/Navbar/GrowiContextualSubNavigation';
 import { CrowiRequest } from '~/interfaces/crowi-request';
 import { IUserUISettings } from '~/interfaces/user-ui-settings';
 import UserUISettings from '~/server/models/user-ui-settings';
 
 import { BasicLayout } from '../components/Layout/BasicLayout';
+import GrowiContextualSubNavigation from '../components/Navbar/GrowiContextualSubNavigation';
 import {
-  useCurrentUser, useIsTrashPage, useCurrentPagePath, useCurrentPathname,
+  useCurrentUser, useCurrentPageId, useCurrentPagePath, useCurrentPathname,
   useIsSearchServiceConfigured, useIsSearchServiceReachable,
   useIsSearchScopeChildrenAsDefault,
 } from '../stores/context';
@@ -21,6 +22,10 @@ import {
   CommonProps, getServerSideCommonProps, useCustomTitle,
 } from './utils/commons';
 
+const TrashPageList = dynamic(() => import('~/components/TrashPageList').then(mod => mod.TrashPageList), { ssr: false });
+const EmptyTrashModal = dynamic(() => import('~/components/EmptyTrashModal'), { ssr: false });
+const PutbackPageModal = dynamic(() => import('~/components/PutbackPageModal'), { ssr: false });
+
 type Props = CommonProps & {
   currentUser: IUser,
   isSearchServiceConfigured: boolean,
@@ -30,15 +35,13 @@ type Props = CommonProps & {
 };
 
 const TrashPage: NextPage<CommonProps> = (props: Props) => {
-  const TrashPageList = dynamic(() => import('~/components/TrashPageList').then(mod => mod.TrashPageList), { ssr: false });
-
   useCurrentUser(props.currentUser ?? null);
 
   useIsSearchServiceConfigured(props.isSearchServiceConfigured);
   useIsSearchServiceReachable(props.isSearchServiceReachable);
   useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
 
-  useIsTrashPage(true);
+  useCurrentPageId(null);
   useCurrentPathname('/trash');
   useCurrentPagePath('/trash');
 
@@ -48,10 +51,16 @@ const TrashPage: NextPage<CommonProps> = (props: Props) => {
         <header className="py-0 position-relative">
           <GrowiContextualSubNavigation isLinkSharingDisabled={false} />
         </header>
+
         <div className="grw-container-convertible mb-5 pb-5">
           <TrashPageList />
         </div>
+
+        <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
       </BasicLayout>
+
+      <EmptyTrashModal />
+      <PutbackPageModal />
     </>
   );
 };