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

Merge pull request #4699 from weseek/feat/show-link-to-private-legacy-pages

feat: Show link to private legacy pages
Yuki Takei 4 лет назад
Родитель
Сommit
738c1cfb8c

+ 15 - 2
packages/app/src/components/Sidebar/PageTree.tsx

@@ -1,21 +1,34 @@
 import React, { FC, memo } from 'react';
 import React, { FC, memo } from 'react';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
+import { useSWRxV5MigrationStatus } from '~/stores/page-listing';
+
 import ItemsTree from './PageTree/ItemsTree';
 import ItemsTree from './PageTree/ItemsTree';
+import PrivateLegacyPages from './PageTree/PrivateLegacyPages';
 
 
 
 
 const PageTree: FC = memo(() => {
 const PageTree: FC = memo(() => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
+  const { data } = useSWRxV5MigrationStatus();
+
   return (
   return (
     <>
     <>
-      <div className="grw-sidebar-content-header p-3 d-flex">
+      <div className="grw-sidebar-content-header p-3">
         <h3 className="mb-0">{t('Page Tree')}</h3>
         <h3 className="mb-0">{t('Page Tree')}</h3>
       </div>
       </div>
 
 
-      <div className="grw-sidebar-content-body p-3">
+      <div className="grw-sidebar-content-body">
         <ItemsTree />
         <ItemsTree />
       </div>
       </div>
+
+      <div className="grw-sidebar-content-footer">
+        {
+          data?.migratablePagesCount != null && data.migratablePagesCount !== 0 && (
+            <PrivateLegacyPages />
+          )
+        }
+      </div>
     </>
     </>
   );
   );
 });
 });

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

@@ -85,7 +85,7 @@ const ItemsTree: FC = () => {
 
 
   const isOpen = true;
   const isOpen = true;
   return (
   return (
-    <div className="grw-pagetree">
+    <div className="grw-page-tree p-3">
       <Item key={(initialNode as ItemNode).page.path} itemNode={(initialNode as ItemNode)} isOpen={isOpen} />
       <Item key={(initialNode as ItemNode).page.path} itemNode={(initialNode as ItemNode)} isOpen={isOpen} />
     </div>
     </div>
   );
   );

+ 16 - 0
packages/app/src/components/Sidebar/PageTree/PrivateLegacyPages.tsx

@@ -0,0 +1,16 @@
+import React, { FC, memo } from 'react';
+import { useTranslation } from 'react-i18next';
+
+const PrivateLegacyPages: FC = memo(() => {
+  const { t } = useTranslation();
+
+  return (
+    <div className="grw-prvt-legacy-pages p-3">
+      <a href="#" className="h5">
+        <i className="icon-drawer mr-2"></i> PrivateLegacyPages
+      </a>
+    </div>
+  );
+});
+
+export default PrivateLegacyPages;

+ 5 - 0
packages/app/src/interfaces/page-listing-results.ts

@@ -16,3 +16,8 @@ export interface TargetAndAncestors {
   targetAndAncestors: Partial<IPageForItem>[]
   targetAndAncestors: Partial<IPageForItem>[]
   rootPage: Partial<IPageForItem>,
   rootPage: Partial<IPageForItem>,
 }
 }
+
+
+export interface V5MigrationStatus {
+  migratablePagesCount: number
+}

+ 10 - 0
packages/app/src/server/routes/apiv3/pages.js

@@ -710,5 +710,15 @@ module.exports = (crowi) => {
     return res.apiv3({ isV5Compatible });
     return res.apiv3({ isV5Compatible });
   });
   });
 
 
+  router.get('/v5-migration-status', accessTokenParser, loginRequired, async(req, res) => {
+    try {
+      const migratablePagesCount = await crowi.pageService.v5MigratablePrivatePagesCount(req.user);
+      return res.apiv3({ migratablePagesCount });
+    }
+    catch (err) {
+      return res.apiv3Err(new ErrorV3('Failed to obtain migration status'));
+    }
+  });
+
   return router;
   return router;
 };
 };

+ 9 - 0
packages/app/src/server/service/page.js

@@ -1,4 +1,5 @@
 import { pagePathUtils } from '@growi/core';
 import { pagePathUtils } from '@growi/core';
+import Page from '~/components/Page';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 const mongoose = require('mongoose');
 const mongoose = require('mongoose');
@@ -952,6 +953,14 @@ class PageService {
     }
     }
   }
   }
 
 
+  async v5MigratablePrivatePagesCount(user) {
+    if (user == null) {
+      throw Error('user is required');
+    }
+    const Page = this.crowi.model('Page');
+    return Page.count({ parent: null, creator: user, grant: { $ne: Page.GRANT_PUBLIC } });
+  }
+
 }
 }
 
 
 module.exports = PageService;
 module.exports = PageService;

+ 12 - 1
packages/app/src/stores/page-listing.tsx

@@ -1,7 +1,7 @@
 import useSWR, { SWRResponse } from 'swr';
 import useSWR, { SWRResponse } from 'swr';
 
 
 import { apiv3Get } from '../client/util/apiv3-client';
 import { apiv3Get } from '../client/util/apiv3-client';
-import { AncestorsChildrenResult, ChildrenResult } from '../interfaces/page-listing-results';
+import { AncestorsChildrenResult, ChildrenResult, V5MigrationStatus } from '../interfaces/page-listing-results';
 
 
 
 
 export const useSWRxPageAncestorsChildren = (
 export const useSWRxPageAncestorsChildren = (
@@ -30,3 +30,14 @@ export const useSWRxPageChildren = (
     }),
     }),
   );
   );
 };
 };
+
+export const useSWRxV5MigrationStatus = (): SWRResponse<V5MigrationStatus, Error> => {
+  return useSWR(
+    '/pages/v5-migration-status',
+    endpoint => apiv3Get(endpoint).then((response) => {
+      return {
+        migratablePagesCount: response.data.migratablePagesCount,
+      };
+    }),
+  );
+};

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

@@ -28,3 +28,8 @@
     }
     }
   }
   }
 }
 }
+
+// TODO: improve style
+.grw-prvt-legacy-pages {
+  border-top: solid 1px $border-color;
+}