Shun Miyazawa 3 лет назад
Родитель
Сommit
a752197952

+ 5 - 6
packages/app/src/components/Admin/App/MaintenanceMode.tsx

@@ -1,14 +1,13 @@
 import React, { FC, useState, useCallback } from 'react';
-import { useTranslation } from 'next-i18next';
 
-import loggerFactory from '~/utils/logger';
+import { useTranslation } from 'next-i18next';
 
-import { ConfirmModal } from './ConfirmModal';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
-
 import { apiv3Post } from '~/client/util/apiv3-client';
-
 import { useIsMaintenanceMode } from '~/stores/context';
+import loggerFactory from '~/utils/logger';
+
+import { ConfirmModal } from './ConfirmModal';
 
 const logger = loggerFactory('growi:maintenanceMode');
 
@@ -53,7 +52,7 @@ export const MaintenanceMode: FC = () => {
 
     // eslint-disable-next-line max-len
     toastSuccess(isMaintenanceMode ? t('admin:maintenance_mode.successfully_ended_maintenance_mode') : t('admin:maintenance_mode.successfully_started_maintenance_mode'));
-  }, [isMaintenanceMode, closeModal]);
+  }, [isMaintenanceMode, closeModal, startMaintenanceMode, endMaintenanceMode, mutateIsMaintenanceMode, t]);
 
   return (
     <div className="mb-5">

+ 77 - 83
packages/app/src/pages/[[...path]].page.tsx

@@ -19,7 +19,6 @@ import superjson from 'superjson';
 
 import { Comments } from '~/components/Comments';
 import { PageAlerts } from '~/components/PageAlert/PageAlerts';
-import { MaintenanceMode } from '~/components/MaintenanceMode';
 // import { useTranslation } from '~/i18n';
 import { PageContentFooter } from '~/components/PageContentFooter';
 import { CrowiRequest } from '~/interfaces/crowi-request';
@@ -71,6 +70,7 @@ import {
 } from './utils/commons';
 // import { useCurrentPageSWR } from '../stores/page';
 
+import styles from './[[...path]].page.module.scss';
 
 const NotCreatablePage = dynamic(() => import('../components/NotCreatablePage').then(mod => mod.NotCreatablePage), { ssr: false });
 const ForbiddenPage = dynamic(() => import('../components/ForbiddenPage'), { ssr: false });
@@ -162,8 +162,6 @@ type Props = CommonProps & {
   // isIndentSizeForced: boolean,
   disableLinkSharing: boolean,
 
-  isMaintenanceMode: boolean,
-
   rendererConfig: RendererConfig,
 
   // UI
@@ -177,7 +175,6 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   const router = useRouter();
 
   const { data: currentUser } = useCurrentUser(props.currentUser ?? null);
-  const title = useCustomTitle(props, 'GROWI');
 
   // register global EventEmitter
   if (isClient()) {
@@ -282,10 +279,6 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   //   classNames.push('not-found-page');
   // }
 
-  if (props.isMaintenanceMode) {
-    return <MaintenanceMode />;
-  }
-
   return (
     <>
       <Head>
@@ -297,90 +290,93 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
         */}
       </Head>
       {/* <BasicLayout title={useCustomTitle(props, t('GROWI'))} className={classNames.join(' ')}> */}
-      <BasicLayout title={title} className={classNames.join(' ')} expandContainer={props.isContainerFluid}>
-        <header className="py-0 position-relative">
-          <GrowiContextualSubNavigation isLinkSharingDisabled={props.disableLinkSharing} />
-        </header>
-        <div className="d-edit-none">
-          <GrowiSubNavigationSwitcher />
-        </div>
+      <BasicLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')} expandContainer={props.isContainerFluid}>
+        <div className="h-100 d-flex flex-column justify-content-between">
+          <header className="py-0 position-relative">
+            <GrowiContextualSubNavigation isLinkSharingDisabled={props.disableLinkSharing} />
+          </header>
+          <div className="d-edit-none">
+            <GrowiSubNavigationSwitcher />
+          </div>
 
-        <div id="grw-subnav-sticky-trigger" className="sticky-top"></div>
-        <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
-
-        <div id="main" className={`main ${isUsersHomePage(props.currentPathname) && 'user-page'}`}>
-          <div id="content-main" className="content-main grw-container-convertible">
-            <div className="row">
-              <div className="col">
-                { props.isIdenticalPathPage && <IdenticalPathPage /> }
-
-                { !props.isIdenticalPathPage && (
-                  <>
-                    <PageAlerts />
-                    { props.isForbidden && <ForbiddenPage /> }
-                    { props.IsNotCreatable && <NotCreatablePage />}
-                    { !props.isForbidden && !props.IsNotCreatable && <DisplaySwitcher />}
-                    {/* <DisplaySwitcher /> */}
-                    <div id="page-editor-navbar-bottom-container" className="d-none d-edit-block"></div>
-                    {/* <PageStatusAlert /> */}
-                  </>
-                ) }
+          <div id="grw-subnav-sticky-trigger" className="sticky-top"></div>
+          <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
+
+          <div className="flex-grow-1">
+            <div id="main" className={`main ${isUsersHomePage(props.currentPathname) && 'user-page'}`}>
+              <div id="content-main" className="content-main grw-container-convertible">
+                <div className="row">
+                  <div className="col">
+                    { props.isIdenticalPathPage && <IdenticalPathPage /> }
+
+                    { !props.isIdenticalPathPage && (
+                      <>
+                        <PageAlerts />
+                        { props.isForbidden && <ForbiddenPage /> }
+                        { props.IsNotCreatable && <NotCreatablePage />}
+                        { !props.isForbidden && !props.IsNotCreatable && <DisplaySwitcher />}
+                        {/* <DisplaySwitcher /> */}
+                        <div id="page-editor-navbar-bottom-container" className="d-none d-edit-block"></div>
+                        {/* <PageStatusAlert /> */}
+                      </>
+                    ) }
 
-              </div>
-            </div>
+                  </div>
+                </div>
 
-            {/* <div className="col-xl-2 col-lg-3 d-none d-lg-block revision-toc-container">
-              <div id="revision-toc" className="revision-toc mt-3 sps sps--abv" data-sps-offset="123">
-                <div id="revision-toc-content" className="revision-toc-content"></div>
+                {/* <div className="col-xl-2 col-lg-3 d-none d-lg-block revision-toc-container">
+                  <div id="revision-toc" className="revision-toc mt-3 sps sps--abv" data-sps-offset="123">
+                    <div id="revision-toc-content" className="revision-toc-content"></div>
+                  </div>
+                </div> */}
               </div>
-            </div> */}
+            </div>
           </div>
-        </div>
-        {/* TODO: Check CSS import */}
-        <footer className="footer d-edit-none">
-          {/* TODO: Enable page_list.html */}
-          {/* TODO: Enable isIdenticalPathPage or useIdenticalPath */}
-          {/* { !props.isIdenticalPathPage && ( */}
-          <Comments pageId={pageId} />
-          {/* )} */}
-          {/* TODO: Create UsersHomePageFooter conponent */}
-          { isUsersHomePage(props.currentPathname) && (
-            <div className="container-lg user-page-footer py-5">
-              <div className="grw-user-page-list-m d-edit-none">
-                <h2 id="bookmarks-list" className="grw-user-page-header border-bottom pb-2 mb-3">
-                  <i style={{ fontSize: '1.3em' }} className="fa fa-fw fa-bookmark-o"></i>
-                  Bookmarks
-                </h2>
-                <div id="user-bookmark-list" className="page-list">
-                  {/* TODO: No need page-list-container class ? */}
-                  <div className="page-list-container">
-                    {/* <BookmarkList userId={pageContainer.state.creator._id} /> */}
+          {/* TODO: Check CSS import */}
+          <footer className="footer d-edit-none">
+            {/* TODO: Enable page_list.html */}
+            {/* TODO: Enable isIdenticalPathPage or useIdenticalPath */}
+            {/* { !props.isIdenticalPathPage && ( */}
+            <Comments pageId={pageId} />
+            {/* )} */}
+            {/* TODO: Create UsersHomePageFooter conponent */}
+            { isUsersHomePage(props.currentPathname) && (
+              <div className="container-lg user-page-footer py-5">
+                <div className="grw-user-page-list-m d-edit-none">
+                  <h2 id="bookmarks-list" className="grw-user-page-header border-bottom pb-2 mb-3">
+                    <i style={{ fontSize: '1.3em' }} className="fa fa-fw fa-bookmark-o"></i>
+                    Bookmarks
+                  </h2>
+                  <div id="user-bookmark-list" className={`page-list ${styles['page-list']}`}>
+                    {/* TODO: No need page-list-container class ? */}
+                    <div className="page-list-container">
+                      {/* <BookmarkList userId={pageContainer.state.creator._id} /> */}
+                    </div>
                   </div>
                 </div>
-              </div>
-              <div className="grw-user-page-list-m mt-5 d-edit-none">
-                <h2 id="recently-created-list" className="grw-user-page-header border-bottom pb-2 mb-3">
-                  <i id="recent-created-icon" className="mr-1">
-                    {/* <RecentlyCreatedIcon /> */}
-                  </i>
-                  Recently Created
-                </h2>
-                <div id="user-created-list" className="page-list">
-                  {/* TODO: No need page-list-container class ? */}
-                  <div className="page-list-container">
-                    {/* <RecentCreated userId={pageContainer.state.creator._id} /> */}
+                <div className="grw-user-page-list-m mt-5 d-edit-none">
+                  <h2 id="recently-created-list" className="grw-user-page-header border-bottom pb-2 mb-3">
+                    <i id="recent-created-icon" className="mr-1">
+                      {/* <RecentlyCreatedIcon /> */}
+                    </i>
+                    Recently Created
+                  </h2>
+                  <div id="user-created-list" className={`page-list ${styles['page-list']}`}>
+                    {/* TODO: No need page-list-container class ? */}
+                    <div className="page-list-container">
+                      {/* <RecentCreated userId={pageContainer.state.creator._id} /> */}
+                    </div>
                   </div>
                 </div>
               </div>
-            </div>
-          )}
-          <PageContentFooter />
-        </footer>
-
-        <UnsavedAlertDialog />
-        <DescendantsPageListModal />
-        {shouldRenderPutbackPageModal && <PutbackPageModal />}
+            )}
+            <PageContentFooter />
+          </footer>
 
+          <UnsavedAlertDialog />
+          <DescendantsPageListModal />
+          {shouldRenderPutbackPageModal && <PutbackPageModal />}
+        </div>
       </BasicLayout>
     </>
   );
@@ -548,8 +544,6 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
   // props.adminPreferredIndentSize = configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize');
   // props.isIndentSizeForced = configManager.getConfig('markdown', 'markdown:isIndentSizeForced');
 
-  props.isMaintenanceMode = crowi.appService.isMaintenanceMode();
-
   props.rendererConfig = {
     isEnabledLinebreaks: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
     isEnabledLinebreaksInComments: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),

+ 8 - 6
packages/app/src/server/routes/index.js

@@ -7,7 +7,9 @@ import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order
 import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware';
 import * as loginFormValidator from '../middlewares/login-form-validator';
 import * as registerFormValidator from '../middlewares/register-form-validator';
-import { generateUnavailableWhenMaintenanceModeMiddlewareForApi } from '../middlewares/unavailable-when-maintenance-mode';
+import {
+  generateUnavailableWhenMaintenanceModeMiddleware, generateUnavailableWhenMaintenanceModeMiddlewareForApi,
+} from '../middlewares/unavailable-when-maintenance-mode';
 
 import * as allInAppNotifications from './all-in-app-notifications';
 import * as forgotPassword from './forgot-password';
@@ -52,7 +54,7 @@ module.exports = function(crowi, app) {
 
   const next = nextFactory(crowi);
 
-  // const unavailableWhenMaintenanceMode = generateUnavailableWhenMaintenanceModeMiddleware(crowi);
+  const unavailableWhenMaintenanceMode = generateUnavailableWhenMaintenanceModeMiddleware(crowi);
   const unavailableWhenMaintenanceModeForApi = generateUnavailableWhenMaintenanceModeMiddlewareForApi(crowi);
 
   const isInstalled = crowi.configManager.getConfig('crowi', 'app:installed');
@@ -74,7 +76,7 @@ module.exports = function(crowi, app) {
 
   app.get('/_next/*'                  , next.delegateToNext);
 
-  app.get('/'                         , applicationInstalled, loginRequired, autoReconnectToSearch, next.delegateToNext);
+  app.get('/'                         , applicationInstalled, unavailableWhenMaintenanceMode, loginRequired, autoReconnectToSearch, next.delegateToNext);
 
   app.get('/login/error/:reason'      , applicationInstalled, login.error);
   app.get('/login'                    , applicationInstalled, login.preLogin, next.delegateToNext);
@@ -179,8 +181,8 @@ module.exports = function(crowi, app) {
   apiV1Router.get('/pages.updatePost'    , accessTokenParser, loginRequired, page.api.getUpdatePost);
   apiV1Router.get('/pages.getPageTag'    , accessTokenParser , loginRequired , page.api.getPageTag);
   // allow posting to guests because the client doesn't know whether the user logged in
-  apiV1Router.post('/pages.remove'       , loginRequiredStrictly , addActivity, page.validator.remove, apiV1FormValidator, page.api.remove); // (Avoid from API Token)
-  apiV1Router.post('/pages.revertRemove' , loginRequiredStrictly , addActivity, page.validator.revertRemove, apiV1FormValidator, page.api.revertRemove); // (Avoid from API Token)
+  apiV1Router.post('/pages.remove'       , loginRequiredStrictly , page.validator.remove, apiV1FormValidator, page.api.remove); // (Avoid from API Token)
+  apiV1Router.post('/pages.revertRemove' , loginRequiredStrictly , page.validator.revertRemove, apiV1FormValidator, page.api.revertRemove); // (Avoid from API Token)
   apiV1Router.post('/pages.unlink'       , loginRequiredStrictly , page.api.unlink); // (Avoid from API Token)
   apiV1Router.post('/pages.duplicate'    , accessTokenParser, loginRequiredStrictly, page.api.duplicate);
   apiV1Router.get('/tags.list'           , accessTokenParser, loginRequired, tag.api.list);
@@ -200,7 +202,7 @@ module.exports = function(crowi, app) {
   // API v1
   app.use('/_api', unavailableWhenMaintenanceModeForApi, apiV1Router);
 
-  // app.use(unavailableWhenMaintenanceMode);
+  app.use(unavailableWhenMaintenanceMode);
 
   // app.get('/tags'                     , loginRequired, tag.showPage);
   app.get('/tags', loginRequired, next.delegateToNext);