Browse Source

Merge branch 'master' into feat/GW-4172-control-priority-of-config-about-file-uploader

yusuketk 5 years ago
parent
commit
1a4f71a631
56 changed files with 398 additions and 439 deletions
  1. 4 4
      .github/workflows/ci.yml
  2. 3 0
      CHANGES.md
  3. 2 2
      package.json
  4. 5 4
      src/client/js/app.jsx
  5. 0 2
      src/client/js/base.jsx
  6. 1 1
      src/client/js/components/Icons/PresentationIcon.jsx
  7. 5 48
      src/client/js/components/Navbar/GrowiSubNavigation.jsx
  8. 4 5
      src/client/js/components/Page/NotFoundAlert.jsx
  9. 1 1
      src/client/js/components/Page/PageManagement.jsx
  10. 8 1
      src/client/js/components/PageTimeline.jsx
  11. 2 0
      src/client/js/services/PageContainer.js
  12. 2 1
      src/client/styles/scss/_admin.scss
  13. 4 0
      src/client/styles/scss/_attachments.scss
  14. 0 5
      src/client/styles/scss/_comment_growi.scss
  15. 34 2
      src/client/styles/scss/_layout.scss
  16. 0 37
      src/client/styles/scss/_layout_growi.scss
  17. 6 0
      src/client/styles/scss/_mixins.scss
  18. 0 7
      src/client/styles/scss/_on-edit.scss
  19. 19 0
      src/client/styles/scss/_override-bootstrap.scss
  20. 1 0
      src/client/styles/scss/_page_list.scss
  21. 2 1
      src/client/styles/scss/_subnav.scss
  22. 4 1
      src/client/styles/scss/molecules/slack-notification.scss
  23. 0 1
      src/client/styles/scss/style-app.scss
  24. 9 0
      src/client/styles/scss/theme/_apply-colors.scss
  25. 2 2
      src/client/styles/scss/theme/_reboot-bootstrap-theme-colors.scss
  26. 6 7
      src/server/routes/page.js
  27. 1 4
      src/server/views/admin/app.html
  28. 3 6
      src/server/views/admin/customize.html
  29. 1 5
      src/server/views/admin/export.html
  30. 1 4
      src/server/views/admin/external-accounts.html
  31. 5 9
      src/server/views/admin/global-notification-detail.html
  32. 1 5
      src/server/views/admin/importer.html
  33. 1 4
      src/server/views/admin/index.html
  34. 1 5
      src/server/views/admin/markdown.html
  35. 1 4
      src/server/views/admin/notification.html
  36. 1 10
      src/server/views/admin/search.html
  37. 1 4
      src/server/views/admin/security.html
  38. 4 8
      src/server/views/admin/user-group-detail.html
  39. 1 4
      src/server/views/admin/user-groups.html
  40. 1 8
      src/server/views/admin/users.html
  41. 18 7
      src/server/views/layout-growi/expired_shared_page.html
  42. 8 5
      src/server/views/layout-growi/forbidden.html
  43. 8 5
      src/server/views/layout-growi/not_creatable.html
  44. 8 5
      src/server/views/layout-growi/not_found.html
  45. 8 5
      src/server/views/layout-growi/not_found_shared_page.html
  46. 2 12
      src/server/views/layout-growi/page.html
  47. 5 16
      src/server/views/layout-growi/page_list.html
  48. 19 28
      src/server/views/layout-growi/shared_page.html
  49. 21 49
      src/server/views/layout-growi/user_page.html
  50. 10 8
      src/server/views/layout-growi/widget/comments.html
  51. 31 8
      src/server/views/layout/admin.html
  52. 7 9
      src/server/views/widget/page_attachments.html
  53. 18 5
      src/server/views/widget/page_content.html
  54. 1 1
      src/test/models/share-link.test.js
  55. 0 0
      src/test/models/update-post.test.js
  56. 87 64
      yarn.lock

+ 4 - 4
.github/workflows/ci.yml

@@ -156,11 +156,11 @@ jobs:
       uses: actions/cache@v2
       uses: actions/cache@v2
       with:
       with:
         path: node_modules/.cache
         path: node_modules/.cache
-        key: ${{ runner.OS }}-hard_source_webpack_dev-${{ matrix.node-version }}-${{ steps.date.outputs.YmdH }}
+        key: ${{ runner.OS }}-hard_source_webpack-${{ matrix.node-version }}-${{ steps.date.outputs.YmdH }}
         restore-keys: |
         restore-keys: |
-          ${{ runner.os }}-hard_source_webpack_dev-${{ matrix.node-version }}-${{ steps.date.outputs.Ymd }}
-          ${{ runner.os }}-hard_source_webpack_dev-${{ matrix.node-version }}-${{ steps.date.outputs.Ym }}
-          ${{ runner.os }}-hard_source_webpack_dev-${{ matrix.node-version }}-${{ steps.date.outputs.Y }}
+          ${{ runner.os }}-hard_source_webpack-${{ matrix.node-version }}-${{ steps.date.outputs.Ymd }}
+          ${{ runner.os }}-hard_source_webpack-${{ matrix.node-version }}-${{ steps.date.outputs.Ym }}
+          ${{ runner.os }}-hard_source_webpack-${{ matrix.node-version }}-${{ steps.date.outputs.Y }}
     - name: Get yarn cache dir
     - name: Get yarn cache dir
       if: steps.cache-dependencies.outputs.cache-hit != 'true'
       if: steps.cache-dependencies.outputs.cache-hit != 'true'
       id: cache-yarn
       id: cache-yarn

+ 3 - 0
CHANGES.md

@@ -11,6 +11,9 @@
 
 
 * Improvement: Basic layout of page
 * Improvement: Basic layout of page
 * Support: Support MongoDB 4.0, 4.2 and 4.4
 * Support: Support MongoDB 4.0, 4.2 and 4.4
+* Support: Upgrade libs
+    * migrate-mongo
+    * mongoose
 
 
 ## v4.1.9
 ## v4.1.9
 
 

+ 2 - 2
package.json

@@ -114,10 +114,10 @@
     "lucene-query-parser": "^1.2.0",
     "lucene-query-parser": "^1.2.0",
     "md5": "^2.2.1",
     "md5": "^2.2.1",
     "method-override": "^3.0.0",
     "method-override": "^3.0.0",
-    "migrate-mongo": "^7.0.1",
+    "migrate-mongo": "^8.1.4",
     "mkdirp": "^1.0.3",
     "mkdirp": "^1.0.3",
     "module-alias": "^2.0.6",
     "module-alias": "^2.0.6",
-    "mongoose": "5.9.18",
+    "mongoose": "5.10.11",
     "mongoose-gridfs": "^1.2.42",
     "mongoose-gridfs": "^1.2.42",
     "mongoose-paginate-v2": "^1.3.9",
     "mongoose-paginate-v2": "^1.3.9",
     "mongoose-unique-validator": "^2.0.3",
     "mongoose-unique-validator": "^2.0.3",

+ 5 - 4
src/client/js/app.jsx

@@ -15,6 +15,7 @@ import PageComments from './components/PageComments';
 import PageTimeline from './components/PageTimeline';
 import PageTimeline from './components/PageTimeline';
 import CommentEditorLazyRenderer from './components/PageComment/CommentEditorLazyRenderer';
 import CommentEditorLazyRenderer from './components/PageComment/CommentEditorLazyRenderer';
 import PageManagement from './components/Page/PageManagement';
 import PageManagement from './components/Page/PageManagement';
+import ShareLinkAlert from './components/Page/ShareLinkAlert';
 import TrashPageList from './components/TrashPageList';
 import TrashPageList from './components/TrashPageList';
 import TrashPageAlert from './components/Page/TrashPageAlert';
 import TrashPageAlert from './components/Page/TrashPageAlert';
 import NotFoundPage from './components/NotFoundPage';
 import NotFoundPage from './components/NotFoundPage';
@@ -86,8 +87,7 @@ Object.assign(componentMappings, {
 
 
   'not-found-alert': <NotFoundAlert
   'not-found-alert': <NotFoundAlert
     onPageCreateClicked={navigationContainer.setEditorMode}
     onPageCreateClicked={navigationContainer.setEditorMode}
-    isForbidden={pageContainer.state.isForbidden}
-    isNotCreatable={pageContainer.state.isNotCreatable}
+    isHidden={pageContainer.state.isForbidden || pageContainer.state.isNotCreatable || pageContainer.state.isTrashPage}
   />,
   />,
 
 
   'page-timeline': <PageTimeline />,
   'page-timeline': <PageTimeline />,
@@ -97,6 +97,8 @@ Object.assign(componentMappings, {
   'my-drafts': <MyDraftList />,
   'my-drafts': <MyDraftList />,
 
 
   'grw-fab-container': <Fab />,
   'grw-fab-container': <Fab />,
+
+  'share-link-alert': <ShareLinkAlert />,
 });
 });
 
 
 // additional definitions if data exists
 // additional definitions if data exists
@@ -110,14 +112,13 @@ if (pageContainer.state.pageId != null) {
     'liker-list': <LikerList />,
     'liker-list': <LikerList />,
 
 
     'recent-created-icon': <RecentlyCreatedIcon />,
     'recent-created-icon': <RecentlyCreatedIcon />,
-    'user-created-list': <RecentCreated userId={pageContainer.state.creator._id} />,
     'user-bookmark-icon': <BookmarkIcon />,
     'user-bookmark-icon': <BookmarkIcon />,
-    'user-bookmark-list': <BookmarkList userId={pageContainer.state.creator._id} />,
   });
   });
 }
 }
 if (pageContainer.state.creator != null) {
 if (pageContainer.state.creator != null) {
   Object.assign(componentMappings, {
   Object.assign(componentMappings, {
     'user-created-list': <RecentCreated userId={pageContainer.state.creator._id} />,
     'user-created-list': <RecentCreated userId={pageContainer.state.creator._id} />,
+    'user-bookmark-list': <BookmarkList userId={pageContainer.state.creator._id} />,
   });
   });
 }
 }
 if (pageContainer.state.path != null) {
 if (pageContainer.state.path != null) {

+ 0 - 2
src/client/js/base.jsx

@@ -6,7 +6,6 @@ import Xss from '@commons/service/xss';
 import GrowiNavbar from './components/Navbar/GrowiNavbar';
 import GrowiNavbar from './components/Navbar/GrowiNavbar';
 import GrowiNavbarBottom from './components/Navbar/GrowiNavbarBottom';
 import GrowiNavbarBottom from './components/Navbar/GrowiNavbarBottom';
 import Sidebar from './components/Sidebar';
 import Sidebar from './components/Sidebar';
-import ShareLinkAlert from './components/Page/ShareLinkAlert';
 import HotkeysManager from './components/Hotkeys/HotkeysManager';
 import HotkeysManager from './components/Hotkeys/HotkeysManager';
 
 
 import AppContainer from './services/AppContainer';
 import AppContainer from './services/AppContainer';
@@ -47,7 +46,6 @@ const componentMappings = {
 
 
   'grw-hotkeys-manager': <HotkeysManager />,
   'grw-hotkeys-manager': <HotkeysManager />,
 
 
-  'share-link-alert': <ShareLinkAlert />,
 };
 };
 
 
 export { appContainer, componentMappings };
 export { appContainer, componentMappings };

+ 1 - 1
src/client/js/components/Icons/PresentationIcon.jsx

@@ -3,7 +3,7 @@ import React from 'react';
 const PresentationIcon = () => (
 const PresentationIcon = () => (
   <svg
   <svg
     xmlns="http://www.w3.org/2000/svg"
     xmlns="http://www.w3.org/2000/svg"
-    width="12.25"
+    width="14"
     height="14"
     height="14"
     viewBox="0 0 12.25 14"
     viewBox="0 0 12.25 14"
   >
   >

+ 5 - 48
src/client/js/components/Navbar/GrowiSubNavigation.jsx

@@ -64,51 +64,7 @@ const PagePathNav = ({ pageId, pagePath, isPageForbidden }) => {
   );
   );
 };
 };
 
 
-/* eslint-disable react/prop-types */
-// eslint-disable-next-line no-unused-vars
-const UserPagePathNav = ({ pageId, pagePath }) => {
-  const linkedPagePath = new LinkedPagePath(pagePath);
-  const latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePath} />;
 
 
-  return (
-    <div className="grw-page-path-nav">
-      <span className="d-flex align-items-center flex-wrap">
-        <h4 className="grw-user-page-path">{latterLink}</h4>
-        <div className="mx-2">
-          <RevisionPathControls
-            pageId={pageId}
-            pagePath={pagePath}
-          />
-        </div>
-      </span>
-    </div>
-  );
-};
-
-// eslint-disable-next-line no-unused-vars
-const UserInfo = ({ pageUser }) => {
-  return (
-    <div className="grw-users-info d-flex align-items-center">
-      {/* eslint-disable-next-line react/jsx-no-undef */}
-      <UserPicture user={pageUser} />
-
-      <div className="users-meta">
-        <h1 className="user-page-name">
-          {pageUser.name}
-        </h1>
-        <div className="user-page-meta mt-1 mb-0">
-          <span className="user-page-username mr-2"><i className="icon-user mr-1"></i>{pageUser.username}</span>
-          <span className="user-page-email mr-2">
-            <i className="icon-envelope mr-1"></i>
-            {pageUser.isEmailPublished ? pageUser.email : '*****'}
-          </span>
-          {pageUser.introduction && <span className="user-page-introduction">{pageUser.introduction}</span>}
-        </div>
-      </div>
-
-    </div>
-  );
-};
 /* eslint-enable react/prop-types */
 /* eslint-enable react/prop-types */
 
 
 /* eslint-disable react/prop-types */
 /* eslint-disable react/prop-types */
@@ -140,7 +96,7 @@ const GrowiSubNavigation = (props) => {
   const { isDrawerMode, editorMode } = navigationContainer.state;
   const { isDrawerMode, editorMode } = navigationContainer.state;
   const {
   const {
     pageId, path, createdAt, creator, updatedAt, revisionAuthor,
     pageId, path, createdAt, creator, updatedAt, revisionAuthor,
-    isForbidden: isPageForbidden, pageUser, isCreatable,
+    isForbidden: isPageForbidden, pageUser, isNotCreatable, shareLinkId,
   } = pageContainer.state;
   } = pageContainer.state;
 
 
   const { currentUser } = appContainer;
   const { currentUser } = appContainer;
@@ -149,13 +105,14 @@ const GrowiSubNavigation = (props) => {
   const isTagLabelHidden = (editorMode !== 'edit' && isPageNotFound);
   const isTagLabelHidden = (editorMode !== 'edit' && isPageNotFound);
   const isUserPage = pageUser != null;
   const isUserPage = pageUser != null;
   const isPageInTrash = isTrashPage(path);
   const isPageInTrash = isTrashPage(path);
+  const isSharedPage = shareLinkId != null;
 
 
   function onThreeStrandedButtonClicked(viewType) {
   function onThreeStrandedButtonClicked(viewType) {
     navigationContainer.setEditorMode(viewType);
     navigationContainer.setEditorMode(viewType);
   }
   }
 
 
   return (
   return (
-    <div className={`grw-subnav d-flex align-items-center justify-content-between ${isCompactMode ? 'grw-subnav-compact d-print-none' : ''}`}>
+    <div className={`grw-subnav container-fluid d-flex align-items-center justify-content-between ${isCompactMode ? 'grw-subnav-compact d-print-none' : ''}`}>
 
 
       {/* Left side */}
       {/* Left side */}
       <div className="d-flex grw-subnav-left-side">
       <div className="d-flex grw-subnav-left-side">
@@ -166,7 +123,7 @@ const GrowiSubNavigation = (props) => {
         ) }
         ) }
 
 
         <div className="grw-path-nav-container">
         <div className="grw-path-nav-container">
-          { !isCompactMode && !isTagLabelHidden && !isPageForbidden && !isUserPage && (
+          { !isCompactMode && !isTagLabelHidden && !isPageForbidden && !isUserPage && !isSharedPage && (
             <div className="mb-2">
             <div className="mb-2">
               <TagLabels editorMode={editorMode} />
               <TagLabels editorMode={editorMode} />
             </div>
             </div>
@@ -184,7 +141,7 @@ const GrowiSubNavigation = (props) => {
             { !isPageNotFound && !isPageForbidden && <PageManagement isCompactMode={isCompactMode} /> }
             { !isPageNotFound && !isPageForbidden && <PageManagement isCompactMode={isCompactMode} /> }
           </div>
           </div>
           <div className="mt-2">
           <div className="mt-2">
-            { !isCreatable && !isPageInTrash && !isPageForbidden && (
+            {!isNotCreatable && !isPageInTrash && !isPageForbidden && (
               <ThreeStrandedButton
               <ThreeStrandedButton
                 onThreeStrandedButtonClicked={onThreeStrandedButtonClicked}
                 onThreeStrandedButtonClicked={onThreeStrandedButtonClicked}
                 isBtnDisabled={currentUser == null}
                 isBtnDisabled={currentUser == null}

+ 4 - 5
src/client/js/components/Page/NotFoundAlert.jsx

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import { withTranslation } from 'react-i18next';
 
 
 const NotFoundAlert = (props) => {
 const NotFoundAlert = (props) => {
-  const { t, isForbidden, isNotCreatable } = props;
+  const { t, isHidden } = props;
   function clickHandler(viewType) {
   function clickHandler(viewType) {
     if (props.onPageCreateClicked === null) {
     if (props.onPageCreateClicked === null) {
       return;
       return;
@@ -11,12 +11,12 @@ const NotFoundAlert = (props) => {
     props.onPageCreateClicked(viewType);
     props.onPageCreateClicked(viewType);
   }
   }
 
 
-  if (isForbidden || isNotCreatable) {
+  if (isHidden) {
     return null;
     return null;
   }
   }
 
 
   return (
   return (
-    <div className="border border-info m-4 p-3">
+    <div className="border border-info p-3">
       <div className="col-md-12 p-0">
       <div className="col-md-12 p-0">
         <h2 className="text-info lead">
         <h2 className="text-info lead">
           <i className="icon-info pr-2 font-weight-bold" aria-hidden="true"></i>
           <i className="icon-info pr-2 font-weight-bold" aria-hidden="true"></i>
@@ -39,8 +39,7 @@ const NotFoundAlert = (props) => {
 NotFoundAlert.propTypes = {
 NotFoundAlert.propTypes = {
   t: PropTypes.func.isRequired, // i18next
   t: PropTypes.func.isRequired, // i18next
   onPageCreateClicked: PropTypes.func,
   onPageCreateClicked: PropTypes.func,
-  isForbidden: PropTypes.bool.isRequired,
-  isNotCreatable: PropTypes.bool.isRequired,
+  isHidden: PropTypes.bool.isRequired,
 };
 };
 
 
 export default withTranslation()(NotFoundAlert);
 export default withTranslation()(NotFoundAlert);

+ 1 - 1
src/client/js/components/Page/PageManagement.jsx

@@ -132,7 +132,7 @@ const PageManagement = (props) => {
         <button className="dropdown-item" type="button" onClick={openPagePresentationModalHandler}>
         <button className="dropdown-item" type="button" onClick={openPagePresentationModalHandler}>
           <i className="icon-fw"><PresentationIcon /></i> { t('Presentation Mode') }
           <i className="icon-fw"><PresentationIcon /></i> { t('Presentation Mode') }
         </button>
         </button>
-        <button type="button" className="dropdown-item" onClick={() => { exportPageHandler('md') }}>
+        <button className="dropdown-item" type="button" onClick={() => { exportPageHandler('md') }}>
           <i className="icon-fw icon-cloud-download"></i>{t('export_bulk.export_page_markdown')}
           <i className="icon-fw icon-cloud-download"></i>{t('export_bulk.export_page_markdown')}
         </button>
         </button>
         {/* TODO GW-2746 create api to bulk export pages */}
         {/* TODO GW-2746 create api to bulk export pages */}

+ 8 - 1
src/client/js/components/PageTimeline.jsx

@@ -60,9 +60,16 @@ class PageTimeline extends React.Component {
   }
   }
 
 
   render() {
   render() {
+    const { t } = this.props;
     const { pages } = this.state;
     const { pages } = this.state;
+    const { path } = this.props.pageContainer.state;
     if (pages == null || pages.length === 0) {
     if (pages == null || pages.length === 0) {
-      return <React.Fragment></React.Fragment>;
+      return (
+        <div className="mt-2">
+          {/* eslint-disable-next-line react/no-danger */}
+          <p dangerouslySetInnerHTML={{ __html: t('custom_navigation.no_page_list', { path }) }} />
+        </div>
+      );
     }
     }
 
 
     return (
     return (

+ 2 - 0
src/client/js/services/PageContainer.js

@@ -4,6 +4,7 @@ import loggerFactory from '@alias/logger';
 
 
 import * as entities from 'entities';
 import * as entities from 'entities';
 import * as toastr from 'toastr';
 import * as toastr from 'toastr';
+import { isTrashPage } from '@commons/util/path-utils';
 import { toastError } from '../util/apiNotification';
 import { toastError } from '../util/apiNotification';
 
 
 import {
 import {
@@ -58,6 +59,7 @@ export default class PageContainer extends Container {
       sumOfBookmarks: 0,
       sumOfBookmarks: 0,
       createdAt: mainContent.getAttribute('data-page-created-at'),
       createdAt: mainContent.getAttribute('data-page-created-at'),
       updatedAt: mainContent.getAttribute('data-page-updated-at'),
       updatedAt: mainContent.getAttribute('data-page-updated-at'),
+      isTrashPage: isTrashPage(path),
       isForbidden: JSON.parse(mainContent.getAttribute('data-page-is-forbidden')),
       isForbidden: JSON.parse(mainContent.getAttribute('data-page-is-forbidden')),
       isDeleted:  JSON.parse(mainContent.getAttribute('data-page-is-deleted')),
       isDeleted:  JSON.parse(mainContent.getAttribute('data-page-is-deleted')),
       isDeletable:  JSON.parse(mainContent.getAttribute('data-page-is-deletable')),
       isDeletable:  JSON.parse(mainContent.getAttribute('data-page-is-deletable')),

+ 2 - 1
src/client/styles/scss/_admin.scss

@@ -1,6 +1,7 @@
 .admin-page {
 .admin-page {
   .title {
   .title {
-    padding: 0.5rem 15px;
+    padding-top: 1rem;
+    padding-bottom: 1rem;
 
 
     line-height: 1em;
     line-height: 1em;
 
 

+ 4 - 0
src/client/styles/scss/_attachments.scss

@@ -48,3 +48,7 @@
     }
     }
   }
   }
 }
 }
+
+.attachment-userpicture .picture {
+  vertical-align: text-bottom;
+}

+ 0 - 5
src/client/styles/scss/_comment_growi.scss

@@ -32,11 +32,6 @@
     }
     }
   }
   }
 
 
-  .page-comments-row {
-    // offset margin left to apply bg-color
-    margin: 30px -15px 30px -15px;
-  }
-
   .page-comments {
   .page-comments {
     h4 {
     h4 {
       margin-bottom: 1em;
       margin-bottom: 1em;

+ 34 - 2
src/client/styles/scss/_layout.scss

@@ -29,9 +29,41 @@ body {
 }
 }
 
 
 .main {
 .main {
-  padding-right: 15px;
-  padding-left: 15px;
   margin-top: 1rem;
   margin-top: 1rem;
+
+  @include media-breakpoint-up(md) {
+    margin-top: 3rem;
+  }
+}
+
+.top-of-table-contents {
+  line-height: 1.25;
+  border-bottom: 1px solid transparent;
+
+  .user-list-content {
+    direction: rtl;
+
+    .liker-user-count,
+    .seen-user-count {
+      font-size: 12px;
+      font-weight: bolder;
+    }
+  }
+  .cls-1 {
+    isolation: isolate;
+  }
+}
+
+.revision-toc {
+  position: sticky;
+  // growisubnavigation + grw-navbar-boder
+  top: calc(100px + 4px);
+  width: 250px;
+  margin-top: 5px;
+
+  .revision-toc-content {
+    padding: 0;
+  }
 }
 }
 
 
 .grw-fab {
 .grw-fab {

+ 0 - 37
src/client/styles/scss/_layout_growi.scss

@@ -1,37 +0,0 @@
-@import 'layout';
-
-.growi {
-  .content-main {
-    padding: 0;
-  }
-
-  .top-of-table-contents {
-    line-height: 1.25;
-    border-bottom: 1px solid transparent;
-
-    .user-list-content {
-      direction: rtl;
-
-      .liker-user-count,
-      .seen-user-count {
-        font-size: 12px;
-        font-weight: bolder;
-      }
-    }
-    .cls-1 {
-      isolation: isolate;
-    }
-  }
-
-  .revision-toc {
-    position: sticky;
-    // growisubnavigation + grw-navbar-boder
-    top: calc(100px + 4px);
-    width: 250px;
-    margin-top: 5px;
-
-    .revision-toc-content {
-      padding: 0;
-    }
-  }
-}

+ 6 - 0
src/client/styles/scss/_mixins.scss

@@ -27,6 +27,12 @@
     height: calc(100vh - #{$editor-margin-top});
     height: calc(100vh - #{$editor-margin-top});
     margin-top: 0px !important;
     margin-top: 0px !important;
 
 
+    .container-lg {
+      max-width: unset;
+      padding: 0;
+      margin: 0;
+    }
+
     &,
     &,
     .content-main,
     .content-main,
     .tab-content {
     .tab-content {

+ 0 - 7
src/client/styles/scss/_on-edit.scss

@@ -45,13 +45,6 @@ body.on-edit {
     @include expand-editor($editor-margin-top);
     @include expand-editor($editor-margin-top);
   }
   }
 
 
-  // for growi layout
-  .main {
-    .col.grw-page-content-container {
-      padding: 0;
-    }
-  }
-
   // show
   // show
   .d-edit-block {
   .d-edit-block {
     display: block !important;
     display: block !important;

+ 19 - 0
src/client/styles/scss/_override-bootstrap.scss

@@ -9,6 +9,25 @@
     outline: none !important;
     outline: none !important;
   }
   }
 
 
+  .container,
+  .container-sm,
+  .container-md,
+  .container-lg,
+  .container-xl,
+  .container-fluid {
+    // default: 15px
+    // padding-right: 15px;
+    // padding-left: 15px;
+    @include media-breakpoint-down(xs) {
+      padding-right: 10px;
+      padding-left: 10px;
+    }
+    @include media-breakpoint-up(md) {
+      padding-right: 30px;
+      padding-left: 30px;
+    }
+  }
+
   h1 {
   h1 {
     font-size: 36px;
     font-size: 36px;
     line-height: 48px;
     line-height: 48px;

+ 1 - 0
src/client/styles/scss/_page_list.scss

@@ -25,6 +25,7 @@ body .page-list {
     .picture {
     .picture {
       width: 16px;
       width: 16px;
       height: 16px;
       height: 16px;
+      vertical-align: text-bottom;
     }
     }
 
 
     .page-list-meta {
     .page-list-meta {

+ 2 - 1
src/client/styles/scss/_subnav.scss

@@ -1,6 +1,7 @@
 .grw-subnav {
 .grw-subnav {
   min-height: $grw-subnav-min-height;
   min-height: $grw-subnav-min-height;
-  padding: 8px 15px;
+  padding-top: 8px;
+  padding-bottom: 8px;
 
 
   @include media-breakpoint-up(md) {
   @include media-breakpoint-up(md) {
     min-height: $grw-subnav-min-height-md;
     min-height: $grw-subnav-min-height-md;

+ 4 - 1
src/client/styles/scss/molecules/slack-notification.scss

@@ -18,8 +18,11 @@
   }
   }
   // height settings for slack button's responsive design
   // height settings for slack button's responsive design
   // in the input and form-control element
   // in the input and form-control element
-  .grw-form-control-slack-notification {
+  .grw-form-control-slack-notification.form-control {
     height: $input-height-slack;
     height: $input-height-slack;
+    &:focus {
+      box-shadow: none;
+    }
   }
   }
   .grw-input-group-slack-notification {
   .grw-input-group-slack-notification {
     height: $input-height-slack;
     height: $input-height-slack;

+ 0 - 1
src/client/styles/scss/style-app.scss

@@ -37,7 +37,6 @@
 @import 'editor-navbar';
 @import 'editor-navbar';
 @import 'handsontable';
 @import 'handsontable';
 @import 'layout';
 @import 'layout';
-@import 'layout_growi';
 @import 'login';
 @import 'login';
 @import 'me';
 @import 'me';
 @import 'mirror_mode';
 @import 'mirror_mode';

+ 9 - 0
src/client/styles/scss/theme/_apply-colors.scss

@@ -92,10 +92,19 @@ pre:not(.hljs):not(.CodeMirror-line) {
 
 
 .dropdown-item {
 .dropdown-item {
   color: $color-global;
   color: $color-global;
+
+  svg {
+    fill: $color-global;
+  }
+
   &:active,
   &:active,
   &.active {
   &.active {
     color: $color-dropdown-link-active;
     color: $color-dropdown-link-active;
     background-color: $bgcolor-dropdown-link-active;
     background-color: $bgcolor-dropdown-link-active;
+
+    svg {
+      fill: $color-dropdown-link-active;
+    }
   }
   }
   &:hover {
   &:hover {
     background-color: $light;
     background-color: $light;

+ 2 - 2
src/client/styles/scss/theme/_reboot-bootstrap-theme-colors.scss

@@ -22,7 +22,7 @@ $theme-colors: map-merge($theme-colors, $colors);
   &.disabled,
   &.disabled,
   &:disabled {
   &:disabled {
     svg {
     svg {
-      color: color-yiq($background);
+      fill: color-yiq($background);
     }
     }
   }
   }
 
 
@@ -30,7 +30,7 @@ $theme-colors: map-merge($theme-colors, $colors);
   &:not(:disabled):not(.disabled).active,
   &:not(:disabled):not(.disabled).active,
   .show > &.dropdown-toggle {
   .show > &.dropdown-toggle {
     svg {
     svg {
-      color: color-yiq($active-background);
+      fill: color-yiq($active-background);
     }
     }
   }
   }
 }
 }

+ 6 - 7
src/server/routes/page.js

@@ -433,7 +433,6 @@ module.exports = function(crowi, app) {
     const revisionId = req.query.revision;
     const revisionId = req.query.revision;
 
 
     const layoutName = configManager.getConfig('crowi', 'customize:layout');
     const layoutName = configManager.getConfig('crowi', 'customize:layout');
-    const view = `layout-${layoutName}/shared_page`;
 
 
     const shareLink = await ShareLink.findOne({ _id: linkId }).populate('relatedPage');
     const shareLink = await ShareLink.findOne({ _id: linkId }).populate('relatedPage');
 
 
@@ -442,17 +441,17 @@ module.exports = function(crowi, app) {
       return res.render(`layout-${layoutName}/not_found_shared_page`);
       return res.render(`layout-${layoutName}/not_found_shared_page`);
     }
     }
 
 
-    let page = shareLink.relatedPage;
+    const renderVars = {};
+
+    renderVars.sharelink = shareLink;
 
 
     // check if share link is expired
     // check if share link is expired
     if (shareLink.isExpired()) {
     if (shareLink.isExpired()) {
       // page is not found
       // page is not found
-      return res.render(`layout-${layoutName}/expired_shared_page`);
+      return res.render(`layout-${layoutName}/expired_shared_page`, renderVars);
     }
     }
 
 
-    const renderVars = {};
-
-    renderVars.sharelink = shareLink;
+    let page = shareLink.relatedPage;
 
 
     // presentation mode
     // presentation mode
     if (req.query.presentation) {
     if (req.query.presentation) {
@@ -471,7 +470,7 @@ module.exports = function(crowi, app) {
     addRenderVarsForScope(renderVars, page);
     addRenderVarsForScope(renderVars, page);
 
 
     await interceptorManager.process('beforeRenderPage', req, res, renderVars);
     await interceptorManager.process('beforeRenderPage', req, res, renderVars);
-    return res.render(view, renderVars);
+    return res.render(`layout-${layoutName}/shared_page`, renderVars);
   };
   };
 
 
   /**
   /**

+ 1 - 4
src/server/views/admin/app.html

@@ -11,10 +11,7 @@
 
 
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main admin-app row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-app"></div>
-</div>
+  <div id="admin-app"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 3 - 6
src/server/views/admin/customize.html

@@ -17,13 +17,10 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main admin-customize row">
-  {% parent %}
-  <div id="grw-hljs-container-for-demo">
-    {{ cdnHighlightJsStyleTag(getConfig('crowi', 'customize:highlightJsStyle')) }}
-  </div>
-  <div class="col-lg-9" id="admin-customize"></div>
+<div id="grw-hljs-container-for-demo">
+  {{ cdnHighlightJsStyleTag(getConfig('crowi', 'customize:highlightJsStyle')) }}
 </div>
 </div>
+<div id="admin-customize" class="admin-customize"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %} {% endblock content_footer %}
 {% block content_footer %} {% endblock content_footer %}

+ 1 - 5
src/server/views/admin/export.html

@@ -7,11 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main admin-export row">
-  {% parent %}
-  <div id="admin-export-page" class="col-lg-9"></div>
-</div>
-
+<div id="admin-export-page" class="admin-export"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 4
src/server/views/admin/external-accounts.html

@@ -7,10 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-external-account-setting"></div>
-</div>
+<div id="admin-external-account-setting"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 5 - 9
src/server/views/admin/global-notification-detail.html

@@ -7,13 +7,9 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-global-notification-setting"
-      data-global-notification="{{ globalNotification|json }}"></div>
-</div>
+<div id="admin-global-notification-setting"
+    data-global-notification="{{ globalNotification|json }}"></div>
+{% endblock content_main %}
 
 
-  {% endblock content_main %}
-
-  {% block content_footer %}
-  {% endblock content_footer %}
+{% block content_footer %}
+{% endblock content_footer %}

+ 1 - 5
src/server/views/admin/importer.html

@@ -7,11 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main admin-importer row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-importer"></div>
-</div>
-
+<div id="admin-importer" class="admin-importer"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 4
src/server/views/admin/index.html

@@ -7,10 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-home"></div>
-</div>
+<div id="admin-home"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 5
src/server/views/admin/markdown.html

@@ -7,11 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-markdown-setting"></div>
-</div>
-
+<div id="admin-markdown-setting"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 4
src/server/views/admin/notification.html

@@ -7,10 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main admin-notification row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-notification-setting"></div>
-</div>
+<div id="admin-notification-setting" class="admin-notification"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 10
src/server/views/admin/search.html

@@ -7,16 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-    <div
-      class="col-lg-9"
-      id ="admin-full-text-search-management"
-    >
-    </div>
-</div>
-
-
+  <div id ="admin-full-text-search-management"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 4
src/server/views/admin/security.html

@@ -7,10 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main admin-security row">
-  {% parent %}
-  <div class="col-lg-9" id="admin-security-setting"></div>
-</div>
+<div id="admin-security-setting" class="admin-security"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 4 - 8
src/server/views/admin/user-group-detail.html

@@ -7,14 +7,10 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div
-    id="admin-user-group-detail"
-    class="col-lg-9"
-    data-user-group="{{ userGroup|json }}"
-  >
-  </div>
+<div
+  id="admin-user-group-detail"
+  data-user-group="{{ userGroup|json }}"
+>
 </div>
 </div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 

+ 1 - 4
src/server/views/admin/user-groups.html

@@ -7,10 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div id ="admin-user-group-page" class="col-lg-9"></div>
-</div>
+<div id ="admin-user-group-page"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 1 - 8
src/server/views/admin/users.html

@@ -7,14 +7,7 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-<div class="content-main row">
-  {% parent %}
-  <div
-    class="col-lg-9"
-    id ="admin-user-page"
-  >
-  </div>
-</div>
+<div id ="admin-user-page"></div>
 {% endblock content_main %}
 {% endblock content_main %}
 
 
 {% block content_footer %}
 {% block content_footer %}

+ 18 - 7
src/server/views/layout-growi/expired_shared_page.html

@@ -1,13 +1,24 @@
 {% extends './shared_page.html' %}
 {% extends './shared_page.html' %}
 
 
-{% block content_header %}
+{% block html_title %}
+  {{ customizeService.generateCustomTitle('Page is expired') }}
 {% endblock %}
 {% endblock %}
 
 
-{% block content_page %}
-  <div class="col-md-12">
-    <h2 class="text-muted">
-      <i class="icon-ban" aria-hidden="true"></i>
-      Page is expired
-    </h2>
+{% block content_main %}
+  <div class="container-lg">
+
+    <div
+      id="is-shared-page"
+      data-share-link-expired-at="{% if sharelink.expiredAt %}{{ sharelink.expiredAt|datetz('Y/m/d H:i:s')}}{% endif %}"
+      data-share-link-created-at="{{ sharelink.createdAt|datetz('Y/m/d H:i:s')}}"
+    >
+      <div id="share-link-alert"></div>
+
+      <h2 class="text-muted mt-4">
+        <i class="icon-ban" aria-hidden="true"></i>
+        Page is expired
+      </h2>
+    </div>
+
   </div>
   </div>
 {% endblock %}
 {% endblock %}

+ 8 - 5
src/server/views/layout-growi/forbidden.html

@@ -2,15 +2,18 @@
 
 
 
 
 {% block content_main_before %}
 {% block content_main_before %}
-  {% include '../widget/page_alerts.html' %}
+  <div class="container-lg">
+    {% include '../widget/page_alerts.html' %}
+  </div>
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-  <div class="row">
-    <div class="col grw-page-content-container">
-      {% include '../widget/forbidden_content.html' %}
+  <div class="container-lg">
+    <div class="row">
+      <div class="col">
+        {% include '../widget/forbidden_content.html' %}
+      </div>
     </div>
     </div>
-    <div class="col-xl-2 col-lg-3 d-none d-lg-block revision-toc-container"></div>
   </div>
   </div>
 {% endblock %}
 {% endblock %}
 
 

+ 8 - 5
src/server/views/layout-growi/not_creatable.html

@@ -2,16 +2,19 @@
 
 
 
 
 {% block content_main_before %}
 {% block content_main_before %}
-  {% include '../widget/page_alerts.html' %}
+  <div class="container-lg">
+    {% include '../widget/page_alerts.html' %}
+  </div>
 {% endblock %}
 {% endblock %}
 
 
 
 
 {% block content_main %}
 {% block content_main %}
-  <div class="row">
-    <div class="col grw-page-content-container">
-      {% include '../widget/not_creatable_content.html' %}
+  <div class="container-lg">
+    <div class="row">
+      <div class="col">
+        {% include '../widget/not_creatable_content.html' %}
+      </div>
     </div>
     </div>
-    <div class="col-xl-2 col-lg-3 d-none d-lg-block revision-toc-container"></div>
   </div>
   </div>
 {% endblock %}
 {% endblock %}
 
 

+ 8 - 5
src/server/views/layout-growi/not_found.html

@@ -2,16 +2,19 @@
 
 
 
 
 {% block content_main_before %}
 {% block content_main_before %}
-  {% include '../widget/page_alerts.html' %}
+  <div class="container-lg">
+    {% include '../widget/page_alerts.html' %}
+  </div>
 {% endblock %}
 {% endblock %}
 
 
 
 
 {% block content_main %}
 {% block content_main %}
-  <div class="row">
-    <div class="col grw-page-content-container">
-      {% include '../widget/not_found_content.html' %}
+  <div class="container-lg">
+    <div class="row">
+      <div class="col">
+        {% include '../widget/not_found_content.html' %}
+      </div>
     </div>
     </div>
-    <div class="col-xl-2 col-lg-3 d-none d-lg-block revision-toc-container"></div>
   </div>
   </div>
 {% endblock %}
 {% endblock %}
 
 

+ 8 - 5
src/server/views/layout-growi/not_found_shared_page.html

@@ -1,13 +1,16 @@
 {% extends './shared_page.html' %}
 {% extends './shared_page.html' %}
 
 
-{% block content_header %}
+{% block html_title %}
+  {{ customizeService.generateCustomTitle('Page is not found') }}
 {% endblock %}
 {% endblock %}
 
 
-{% block content_page %}
-  <div class="col-md-12">
-    <h2 class="text-muted">
-      <i class="icon-info" aria-hidden="true"></i>
+{% block content_main %}
+  <div class="container-lg">
+
+    <h2 class="text-muted mt-4">
+      <i class="icon-ban" aria-hidden="true"></i>
       Page is not found
       Page is not found
     </h2>
     </h2>
+
   </div>
   </div>
 {% endblock %}
 {% endblock %}

+ 2 - 12
src/server/views/layout-growi/page.html

@@ -6,19 +6,9 @@
 
 
 
 
 {% block content_main %}
 {% block content_main %}
-  <div class="d-flex justify-content-between">
+  <div class="container-lg">
 
 
-    <div class="grw-page-content-container flex-grow-1">
-
-      {% include '../widget/page_content.html' %}
-
-    </div>
-
-    <div class="d-none d-lg-block revision-toc-container">
-      <div id="revision-toc" class="revision-toc mt-3 sps sps--abv" data-sps-offset="123">
-        <div id="revision-toc-content" class="revision-toc-content"></div>
-      </div>
-    </div>
+    {% include '../widget/page_content.html' %}
 
 
   </div>
   </div>
 {% endblock %}
 {% endblock %}

+ 5 - 16
src/server/views/layout-growi/page_list.html

@@ -6,28 +6,17 @@
 
 
 
 
 {% block content_main %}
 {% block content_main %}
-  <div class="d-flex justify-content-between">
-
-    <div class="grw-page-content-container flex-grow-1">
-
-      {% include '../widget/page_content.html' %}
-
-    </div>
-
-    <div class="d-none d-lg-block revision-toc-container">
-      <div id="revision-toc" class="revision-toc mt-3 sps sps--abv" data-sps-offset="123">
-        <div id="revision-toc-content" class="revision-toc-content"></div>
-      </div>
-    </div>
-
+  <div class="container-lg">
+    {% include '../widget/page_content.html' %}
   </div>
   </div>
-
 {% endblock %}
 {% endblock %}
 
 
 
 
 {% block content_main_after %}
 {% block content_main_after %}
   {% if isTrashPage() %}
   {% if isTrashPage() %}
-    <div id="trash-page-list"></div>
+    <div class="container-lg">
+      <div id="trash-page-list"></div>
+    </div>
   {% endif %}
   {% endif %}
   {% if page %}
   {% if page %}
     {% include '../widget/page_attachments.html' %}
     {% include '../widget/page_attachments.html' %}

+ 19 - 28
src/server/views/layout-growi/shared_page.html

@@ -1,11 +1,16 @@
 {% extends 'base/layout.html' %}
 {% extends 'base/layout.html' %}
 
 
-
-{% block content_header %}
-  <h1 class="p-3">{{ page.path | preventXss }}</h1>
+{% block content_header_wrapper %}
+<header class="py-0">
+  {% block content_header %}
+    <div id="grw-subnav-container"></div>
+  {% endblock %}
+</header>
+<div id="grw-subnav-switcher-container" class="d-edit-none"></div>
+<div id="grw-subnav-sticky-trigger" class="sticky-top"></div>
+<div id="grw-fav-sticky-trigger" class="sticky-top"></div>
 {% endblock %}
 {% endblock %}
 
 
-
 {% block content_main_before %}
 {% block content_main_before %}
 {% endblock %}
 {% endblock %}
 {% block search %}
 {% block search %}
@@ -14,36 +19,22 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
-  <div
-    class="d-flex justify-content-between"
-    id="is-shared-page"
-    data-share-link-expired-at="{% if sharelink.expiredAt %}{{ sharelink.expiredAt|datetz('Y/m/d H:i:s')}}{% endif %}"
-    data-share-link-created-at="{{ sharelink.createdAt|datetz('Y/m/d H:i:s')}}"
-  >
-    {% block content_page %}
-      <div class="grw-page-content-container flex-grow-1">
-        <div id="share-link-alert"></div>
+  <div class="container-lg">
 
 
-        {% include '../widget/page_content.html' %}
-        {# force remove #revision-toc from #content_main of parent #}
-        <script>
-          $('#revision-toc').remove();
-        </script>
+    <div
+      id="is-shared-page"
+      data-share-link-expired-at="{% if sharelink.expiredAt %}{{ sharelink.expiredAt|datetz('Y/m/d H:i:s')}}{% endif %}"
+      data-share-link-created-at="{{ sharelink.createdAt|datetz('Y/m/d H:i:s')}}"
+    >
+      <div id="share-link-alert"></div>
 
 
-      </div>
-
-      {# relocate #revision-toc #}
-      <div class="d-none d-lg-block revision-toc-container">
-        <div id="revision-toc" class="revision-toc mt-3 sps sps--abv" data-sps-offset="123">
-          <div id="revision-toc-content" class="revision-toc-content"></div>
-        </div>
-      </div>
-    {% endblock %}
+      {% include '../widget/page_content.html' %}
+      
+    </div>
 
 
   </div>
   </div>
 {% endblock %}
 {% endblock %}
 
 
-
 {% block body_end %}
 {% block body_end %}
   <div id="presentation-layer" class="fullscreen-layer">
   <div id="presentation-layer" class="fullscreen-layer">
     <div id="presentation-container"></div>
     <div id="presentation-container"></div>

+ 21 - 49
src/server/views/layout-growi/user_page.html

@@ -6,43 +6,11 @@
 {% endblock %}
 {% endblock %}
 
 
 {% block content_main %}
 {% block content_main %}
+  <div class="container-lg">
 
 
-  <div class="d-flex justify-content-between">
-    <div class="grw-page-content-container flex-grow-1">
-
-      <div class="user-info" id="user-info">
-      </div>
-
-      {#
-        #   Because this block has content like 'Bookmarks' or 'Recent Created' whose height changes dynamically,
-        #   setting of 'revision-toc' (affix) is hindered.
-        #}
-      <div class="mb-5 user-page-content-container d-edit-none d-print-none">
-      </div>
-
-      {% block content_main_before %}
-        {% parent %}
-      {% endblock %}
-
-      {% include '../widget/page_content.html' %}
-
-      {# force remove #revision-toc from #content_main of parent #}
-      <script>
-        $('#revision-toc').remove();
-      </script>
-
-    </div> {# /.col- #}
-
-    {# relocate #revision-toc #}
-    <div class="d-none d-lg-block revision-toc-container">
-      <div id="revision-toc" class="revision-toc mt-3 sps sps--abv" data-sps-offset="116">
-        <div id="revision-toc-content" class="revision-toc-content"></div>
-      </div>
-    </div> {# /.col- #}
+    {% include '../widget/page_content.html' %}
 
 
   </div>
   </div>
-
-
 {% endblock %}
 {% endblock %}
 
 
 
 
@@ -50,26 +18,30 @@
   {% include 'widget/comments.html' %}
   {% include 'widget/comments.html' %}
 
 
   {% if page %}
   {% if page %}
-    <div class="grw-page-list-m mt-5 pb-5 d-edit-none">
-      <h2 class="grw-page-list-title-m border-bottom pb-2 mb-3" id="bookmarks-list">
-        <i id="user-bookmark-icon"></i>
-        Bookmarks
-      </h2>
-      <div class="page-list" id="user-bookmark-list">
-        <div class="page-list-container">
+    <div class="container-lg">
+
+      <div class="grw-page-list-m mt-5 pb-5 d-edit-none">
+        <h2 class="grw-page-list-title-m border-bottom pb-2 mb-3" id="bookmarks-list">
+          <i id="user-bookmark-icon"></i>
+          Bookmarks
+        </h2>
+        <div class="page-list" id="user-bookmark-list">
+          <div class="page-list-container">
+          </div>
         </div>
         </div>
       </div>
       </div>
-    </div>
 
 
-    <div class="grw-page-list-m mt-5 pb-5 d-edit-none">
-      <h2 class="grw-page-list-title-m border-bottom pb-2 mb-3" id="recently-created-list">
-        <i id="recent-created-icon"></i>
-        Recently Created
-      </h2>
-      <div class="page-list" id="user-created-list">
-        <div class="page-list-container">
+      <div class="grw-page-list-m mt-5 pb-5 d-edit-none">
+        <h2 class="grw-page-list-title-m border-bottom pb-2 mb-3" id="recently-created-list">
+          <i id="recent-created-icon"></i>
+          Recently Created
+        </h2>
+        <div class="page-list" id="user-created-list">
+          <div class="page-list-container">
+          </div>
         </div>
         </div>
       </div>
       </div>
+
     </div>
     </div>
   {% endif %}
   {% endif %}
 
 

+ 10 - 8
src/server/views/layout-growi/widget/comments.html

@@ -1,15 +1,17 @@
-<div class="page-comments-row row d-edit-none d-print-none">
+<div class="page-comments-row mt-5 py-4 d-edit-none d-print-none">
+  <div class="container-lg">
 
 
-  <div class="page-comments col-lg-10 my-5">
+    <div class="page-comments">
 
 
-    <h2 class="border-bottom pb-2 mb-3"><i class="icon-fw icon-bubbles"></i> Comments</h2>
+      <h2 class="border-bottom pb-2 mb-3"><i class="icon-fw icon-bubbles"></i> Comments</h2>
 
 
-    <div class="page-comments-list" id="page-comments-list"></div>
+      <div class="page-comments-list" id="page-comments-list"></div>
 
 
-    {% if page and not page.isDeleted() %}
-    <div id="page-comment-write"></div>
-    {% endif %}
+      {% if page and not page.isDeleted() %}
+      <div id="page-comment-write"></div>
+      {% endif %}
 
 
-  </div>
+    </div>
 
 
+  </div>
 </div>
 </div>

+ 31 - 8
src/server/views/layout/admin.html

@@ -1,17 +1,40 @@
-{% extends '../layout-growi/base/layout.html' %}
-
+{% extends './layout.html' %}
 
 
 {% block html_base_css %}admin-page{% endblock %}
 {% block html_base_css %}admin-page{% endblock %}
 
 
-
 {% block html_head_loading_app %}
 {% block html_head_loading_app %}
 <script src="{{ webpack_asset('js/admin.js') }}" defer></script>
 <script src="{{ webpack_asset('js/admin.js') }}" defer></script>
 {% endblock %}
 {% endblock %}
 
 
-{% block content_main %}
-  <div class="col-lg-3" id="admin-navigation"></div>
-{% endblock content_main %}
+{% block layout_main %}
 
 
-{# disable custom script in admin page #}
-{% block custom_script %}
+{% block content_header_wrapper %}
+<header class="container-fluid py-0">
+  {% block content_header %}
+    <div id="grw-subnav-container"></div>
+  {% endblock %}
+</header>
 {% endblock %}
 {% endblock %}
+
+<div id="main" class="main {% block main_css_class %}{% endblock %}">
+
+  <div class="container-fluid">
+    <div class="row">
+      <div class="col-lg-3" id="admin-navigation"></div>
+      <div class="col-lg-9">
+        {% block content_main_before %}
+        {% endblock %}
+
+        {% block content_main %}
+        {% endblock content_main %}
+
+        {% block content_main_after %}
+        {% endblock %}
+      </div>
+    </div>
+  </div>
+</div><!-- /.main -->
+
+<footer class="footer">
+</footer>
+{% endblock %} {# layout_main #}

+ 7 - 9
src/server/views/widget/page_attachments.html

@@ -1,12 +1,10 @@
-<div class="row page-attachments-row d-edit-none d-print-none">
-  <div class="col-12">
-    <div class="mt-4 mb-4">
-      <div class="page-attachments" id="page-attachment"></div>
+<div class="page-attachments-row mt-5 py-4 d-edit-none d-print-none">
+  <div class="container-lg">
+    <div class="page-attachments" id="page-attachment"></div>
 
 
-      <p class="page-meta">
-        <p>Last revision posted at {{ page.revision.createdAt|datetz('Y-m-d H:i:s') }} by <a href="/user/{{ page.revision.author.username }}"><img src="{{ page.revision.author|picture }}" class="picture picture-sm rounded-circle"> {{ page.revision.author.name }}</a></p>
-        <p>Created at {{ page.createdAt|datetz('Y-m-d H:i:s') }} by <a href="/user/{{ page.creator.username }}"><img src="{{ page.creator|default(page.creator)|picture }}" class="picture picture-sm rounded-circle"> {{ page.creator.name }}</a></p>
-      </p>
-    </div>
+    <p class="page-meta">
+      <p>Last revision posted at {{ page.revision.createdAt|datetz('Y-m-d H:i:s') }} by <a href="/user/{{ page.revision.author.username }}"><img src="{{ page.revision.author|picture }}" class="picture picture-sm rounded-circle"> {{ page.revision.author.name }}</a></p>
+      <p>Created at {{ page.createdAt|datetz('Y-m-d H:i:s') }} by <a href="/user/{{ page.creator.username }}"><img src="{{ page.creator|default(page.creator)|picture }}" class="picture picture-sm rounded-circle"> {{ page.creator.name }}</a></p>
+    </p>
   </div>
   </div>
 </div>
 </div>

+ 18 - 5
src/server/views/widget/page_content.html

@@ -1,5 +1,5 @@
 {% if page %}
 {% if page %}
-<div id="content-main" class="content-main container"
+<div id="content-main" class="content-main d-flex"
   data-path="{{ encodeURI(page.path) }}"
   data-path="{{ encodeURI(page.path) }}"
   data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
   data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
   data-page-id="{% if page %}{{ page._id.toString() }}{% endif %}"
   data-page-id="{% if page %}{{ page._id.toString() }}{% endif %}"
@@ -32,7 +32,7 @@
   data-share-link-id="{% if sharelink %}{{ sharelink._id|json }}{% endif %}"
   data-share-link-id="{% if sharelink %}{{ sharelink._id|json }}{% endif %}"
   >
   >
 {% else %}
 {% else %}
-<div id="content-main" class="content-main"
+<div id="content-main" class="content-main d-flex"
   data-path="{{ encodeURI(path) }}"
   data-path="{{ encodeURI(path) }}"
   data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
   data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
   data-slack-channels="{{ slack|default('') }}"
   data-slack-channels="{{ slack|default('') }}"
@@ -41,12 +41,25 @@
   >
   >
 {% endif %}
 {% endif %}
 
 
+<div class="flex-grow-1">
   {% include 'page_alerts.html' %}
   {% include 'page_alerts.html' %}
 
 
-<div id="display-switcher">
-  <script type="text/template" id="raw-text-original">{{ revision.body.toString() | encodeHTML }}</script>
+  {% if pageUser %}
+    <div class="user-info" id="user-info"></div>
+  {% endif %}
+
+  <div id="display-switcher">
+    <script type="text/template" id="raw-text-original">{{ revision.body.toString() | encodeHTML }}</script>
+  </div>
+  <div id="page-editor-navbar-bottom-container" class="d-none d-edit-block"></div>
+</div>
+
+<div class="d-none d-lg-block revision-toc-container ml-4">
+  <div id="revision-toc" class="revision-toc sps sps--abv" data-sps-offset="123">
+    <div id="revision-toc-content" class="revision-toc-content"></div>
+  </div>
 </div>
 </div>
-<div id="page-editor-navbar-bottom-container" class="d-none d-edit-block"></div>
+
 <div id="grw-page-status-alert-container"></div>
 <div id="grw-page-status-alert-container"></div>
 
 
 </div>
 </div>

+ 1 - 1
src/test/models/shareLink.test.js → src/test/models/share-link.test.js

@@ -98,7 +98,7 @@ describe('ShareLink', () => {
       expect(findOneResult.populate).toHaveBeenCalled();
       expect(findOneResult.populate).toHaveBeenCalled();
       expect(res.render).toHaveBeenCalled();
       expect(res.render).toHaveBeenCalled();
       expect(response.page).toEqual('layout-growi/expired_shared_page');
       expect(response.page).toEqual('layout-growi/expired_shared_page');
-      expect(response.renderVars).toEqual(null);
+      expect(response.renderVars).not.toEqual(null);
     });
     });
 
 
     test('share link is found, and it has the page you can see', async() => {
     test('share link is found, and it has the page you can see', async() => {

+ 0 - 0
src/test/models/updatePost.test.js → src/test/models/update-post.test.js


+ 87 - 64
yarn.lock

@@ -2680,6 +2680,11 @@ asynckit@^0.4.0:
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
   integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
   integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
 
 
+at-least-node@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
+  integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+
 atob@^2.1.1:
 atob@^2.1.1:
   version "2.1.1"
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a"
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a"
@@ -3050,10 +3055,10 @@ bindings@^1.5.0:
   dependencies:
   dependencies:
     file-uri-to-path "1.0.0"
     file-uri-to-path "1.0.0"
 
 
-bl@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.0.tgz#e1a574cdf528e4053019bb800b041c0ac88da493"
-  integrity sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==
+bl@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5"
+  integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==
   dependencies:
   dependencies:
     readable-stream "^2.3.5"
     readable-stream "^2.3.5"
     safe-buffer "^5.1.1"
     safe-buffer "^5.1.1"
@@ -3350,11 +3355,6 @@ bser@^2.0.0:
   dependencies:
   dependencies:
     node-int64 "^0.4.0"
     node-int64 "^0.4.0"
 
 
-bson@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.1.tgz#4330f5e99104c4e751e7351859e2d408279f2f13"
-  integrity sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==
-
 bson@^1.1.4:
 bson@^1.1.4:
   version "1.1.4"
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.4.tgz#f76870d799f15b854dffb7ee32f0a874797f7e89"
   resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.4.tgz#f76870d799f15b854dffb7ee32f0a874797f7e89"
@@ -3818,13 +3818,13 @@ cli-cursor@^2.1.0:
   dependencies:
   dependencies:
     restore-cursor "^2.0.0"
     restore-cursor "^2.0.0"
 
 
-cli-table3@0.5.1:
-  version "0.5.1"
-  resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202"
-  integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==
+cli-table3@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee"
+  integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==
   dependencies:
   dependencies:
     object-assign "^4.1.0"
     object-assign "^4.1.0"
-    string-width "^2.1.1"
+    string-width "^4.2.0"
   optionalDependencies:
   optionalDependencies:
     colors "^1.1.2"
     colors "^1.1.2"
 
 
@@ -4033,11 +4033,6 @@ commander@2.20.0, commander@^2.20.0, commander@^2.7.1:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
   integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
   integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
 
 
-commander@4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.0.tgz#e782b6afe6a0f1b1408be59429919e1305160e3f"
-  integrity sha512-SEa2abMBTZuEjLVYpNrAFoRgxPwG4rXP3+SGY6CM/HZGeDzIA7Pzp+7H3AHDukKEpyy2SoSGGPShKqqfH9T9AQ==
-
 commander@^2.18.0:
 commander@^2.18.0:
   version "2.18.0"
   version "2.18.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
@@ -4065,6 +4060,11 @@ commander@^5.1.0:
   resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
   resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
   integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
   integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
 
 
+commander@^6.1.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75"
+  integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==
+
 commondir@^1.0.1:
 commondir@^1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
   resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -4729,16 +4729,16 @@ date-and-time@^0.10.0:
   resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.10.0.tgz#53825b774167b55fbdf0bbd0f17f19357df7bc70"
   resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.10.0.tgz#53825b774167b55fbdf0bbd0f17f19357df7bc70"
   integrity sha512-IbIzxtvK80JZOVsWF6+NOjunTaoFVYxkAQoyzmflJyuRCJAJebehy48mPiCAedcGp4P7/UO3QYRWa0fe6INftg==
   integrity sha512-IbIzxtvK80JZOVsWF6+NOjunTaoFVYxkAQoyzmflJyuRCJAJebehy48mPiCAedcGp4P7/UO3QYRWa0fe6INftg==
 
 
-date-fns@2.6.0:
-  version "2.6.0"
-  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.6.0.tgz#a5bc82e6a4c3995ae124b0ba1a71aec7b8cbd666"
-  integrity sha512-F55YxqRdEfP/eYQmQjLN798v0AwLjmZ8nMBjdQvNwEE3N/zWVrlkkqT+9seBlPlsbkybG4JmWg3Ee3dIV9BcGQ==
-
 date-fns@^2.0.0:
 date-fns@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0.tgz#52f05c6ae1fe0e395670082c72b690ab781682d0"
   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0.tgz#52f05c6ae1fe0e395670082c72b690ab781682d0"
   integrity sha512-nGZDA64Ktq5uTWV4LEH3qX+foV4AguT5qxwRlJDzJtf57d4xLNwtwrfb7SzKCoikoae8Bvxf0zdaEG/xWssp/w==
   integrity sha512-nGZDA64Ktq5uTWV4LEH3qX+foV4AguT5qxwRlJDzJtf57d4xLNwtwrfb7SzKCoikoae8Bvxf0zdaEG/xWssp/w==
 
 
+date-fns@^2.16.1:
+  version "2.16.1"
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b"
+  integrity sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==
+
 date-format@^2.1.0:
 date-format@^2.1.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
   resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
@@ -6346,7 +6346,7 @@ flushable@^1.0.0:
   resolved "https://registry.yarnpkg.com/flushable/-/flushable-1.0.0.tgz#2fc16837ec85f8d7ec1bd777087b8448e1ca8216"
   resolved "https://registry.yarnpkg.com/flushable/-/flushable-1.0.0.tgz#2fc16837ec85f8d7ec1bd777087b8448e1ca8216"
   integrity sha512-WQr7DsBZfdmXwqWk7yyk9H2R60iHiUpLMvkov6KivafC9d1SzDTjSBsKMa8skT4laaSxus+F4v7WLO6J0zxPkw==
   integrity sha512-WQr7DsBZfdmXwqWk7yyk9H2R60iHiUpLMvkov6KivafC9d1SzDTjSBsKMa8skT4laaSxus+F4v7WLO6J0zxPkw==
 
 
-fn-args@5.0.0:
+fn-args@^5.0.0:
   version "5.0.0"
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/fn-args/-/fn-args-5.0.0.tgz#7a18e105c8fb3bf0a51c30389bf16c9ebe740bb3"
   resolved "https://registry.yarnpkg.com/fn-args/-/fn-args-5.0.0.tgz#7a18e105c8fb3bf0a51c30389bf16c9ebe740bb3"
   integrity sha512-CtbfI3oFFc3nbdIoHycrfbrxiGgxXBXXuyOl49h47JawM1mYrqpiRqnH5CB2mBatdXvHHOUO6a+RiAuuvKt0lw==
   integrity sha512-CtbfI3oFFc3nbdIoHycrfbrxiGgxXBXXuyOl49h47JawM1mYrqpiRqnH5CB2mBatdXvHHOUO6a+RiAuuvKt0lw==
@@ -6467,7 +6467,7 @@ fs-extra@3.0.1:
     jsonfile "^3.0.0"
     jsonfile "^3.0.0"
     universalify "^0.1.0"
     universalify "^0.1.0"
 
 
-fs-extra@8.1.0, fs-extra@^8.1.0:
+fs-extra@^8.1.0:
   version "8.1.0"
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
   integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
   integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
@@ -6476,6 +6476,16 @@ fs-extra@8.1.0, fs-extra@^8.1.0:
     jsonfile "^4.0.0"
     jsonfile "^4.0.0"
     universalify "^0.1.0"
     universalify "^0.1.0"
 
 
+fs-extra@^9.0.1:
+  version "9.0.1"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc"
+  integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==
+  dependencies:
+    at-least-node "^1.0.0"
+    graceful-fs "^4.2.0"
+    jsonfile "^6.0.1"
+    universalify "^1.0.0"
+
 fs-minipass@^2.0.0:
 fs-minipass@^2.0.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
   resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -8586,6 +8596,15 @@ jsonfile@^4.0.0:
   optionalDependencies:
   optionalDependencies:
     graceful-fs "^4.1.6"
     graceful-fs "^4.1.6"
 
 
+jsonfile@^6.0.1:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+  integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+  dependencies:
+    universalify "^2.0.0"
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
 jsonify@~0.0.0:
 jsonify@~0.0.0:
   version "0.0.0"
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@@ -8960,7 +8979,7 @@ lodash.uniq@^4.5.0:
   version "4.5.0"
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
 
 
-lodash@4.17.15, lodash@>=4.17.15, lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.10:
+lodash@>=4.17.15, lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.10:
   version "4.17.15"
   version "4.17.15"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -8973,6 +8992,11 @@ lodash@^4.17.2, lodash@^4.17.4:
   version "4.17.4"
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
 
 
+lodash@^4.17.20:
+  version "4.17.20"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
+  integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+
 lodash@^4.17.5:
 lodash@^4.17.5:
   version "4.17.10"
   version "4.17.10"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
@@ -9414,19 +9438,19 @@ micromatch@^4.0.2:
     braces "^3.0.1"
     braces "^3.0.1"
     picomatch "^2.0.5"
     picomatch "^2.0.5"
 
 
-migrate-mongo@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/migrate-mongo/-/migrate-mongo-7.0.1.tgz#3c3bc524862525ae644d7fc097e458bbbe05aa10"
-  integrity sha512-Z3uytjSw7STfWFn2iqjbQ37h/ghI0xTejWCcWwNyatxwjX2ekPhN283SSf2A50b0lFa2ZHidT8Ti2JkUw+nkhw==
-  dependencies:
-    cli-table3 "0.5.1"
-    commander "4.0.0"
-    date-fns "2.6.0"
-    fn-args "5.0.0"
-    fs-extra "8.1.0"
-    lodash "4.17.15"
-    mongodb "3.3.3"
-    p-each-series "2.1.0"
+migrate-mongo@^8.1.4:
+  version "8.1.4"
+  resolved "https://registry.yarnpkg.com/migrate-mongo/-/migrate-mongo-8.1.4.tgz#700fb921fae0aecc571c6b251486e0fd1fac93e7"
+  integrity sha512-iuJiG86Qzr1w9B5j6jB6akZO0w040DTEWtKdclISaQg7KdovtXGYDmW8hehDsULY5oFGjNtJv/ABsOPlz0c5mw==
+  dependencies:
+    cli-table3 "^0.6.0"
+    commander "^6.1.0"
+    date-fns "^2.16.1"
+    fn-args "^5.0.0"
+    fs-extra "^9.0.1"
+    lodash "^4.17.20"
+    mongodb "^3.6.2"
+    p-each-series "^2.1.0"
 
 
 miller-rabin@^4.0.0:
 miller-rabin@^4.0.0:
   version "4.0.1"
   version "4.0.1"
@@ -9688,23 +9712,12 @@ moment@>=2.26.0:
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
   integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==
   integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==
 
 
-mongodb@3.3.3:
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.3.3.tgz#509cad2225a1c56c65a331ed73a0d5d4ed5cbe67"
-  integrity sha512-MdRnoOjstmnrKJsK8PY0PjP6fyF/SBS4R8coxmhsfEU7tQ46/J6j+aSHF2n4c2/H8B+Hc/Klbfp8vggZfI0mmA==
-  dependencies:
-    bson "^1.1.1"
-    require_optional "^1.0.1"
-    safe-buffer "^5.1.2"
-  optionalDependencies:
-    saslprep "^1.0.0"
-
-mongodb@3.5.8, mongodb@^3.1.0:
-  version "3.5.8"
-  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.5.8.tgz#34550856449b745d145873734bf922c12d6b9caa"
-  integrity sha512-jz7mR58z66JKL8Px4ZY+FXbgB7d0a0hEGCT7kw8iye46/gsqPrOEpZOswwJ2BQlfzsrCLKdsF9UcaUfGVN2HrQ==
+mongodb@3.6.2, mongodb@^3.1.0, mongodb@^3.6.2:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.2.tgz#1154a4ac107bf1375112d83a29c5cf97704e96b6"
+  integrity sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==
   dependencies:
   dependencies:
-    bl "^2.2.0"
+    bl "^2.2.1"
     bson "^1.1.4"
     bson "^1.1.4"
     denque "^1.4.1"
     denque "^1.4.1"
     require_optional "^1.0.1"
     require_optional "^1.0.1"
@@ -9755,20 +9768,20 @@ mongoose-valid8@>=1.6.18:
     lodash ">=4.17.15"
     lodash ">=4.17.15"
     validator ">=13.0.0"
     validator ">=13.0.0"
 
 
-mongoose@5.9.18:
-  version "5.9.18"
-  resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.9.18.tgz#d031ed53b1e60ba4a1491fb5419068acb1f33d00"
-  integrity sha512-agZbIuQcN1gZ12BJn6KesA+bgsvoLVjCwhfPw88hggxX8O24SWK4EJwN35GEZKDej9AHUZKNAPgmdeXCVQxviA==
+mongoose@5.10.11:
+  version "5.10.11"
+  resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.10.11.tgz#4bef4a85d35f38eb45a0af27b276d2bfd2196b5c"
+  integrity sha512-R5BFitKW94/S/Z48w+X+qi/eto66jWBcVEVA8nYVkBoBAPFGq7JSYP/0uso+ZHs+7XjSzTuui+SUllzxIrf9yA==
   dependencies:
   dependencies:
     bson "^1.1.4"
     bson "^1.1.4"
     kareem "2.3.1"
     kareem "2.3.1"
-    mongodb "3.5.8"
+    mongodb "3.6.2"
     mongoose-legacy-pluralize "1.0.2"
     mongoose-legacy-pluralize "1.0.2"
     mpath "0.7.0"
     mpath "0.7.0"
     mquery "3.2.2"
     mquery "3.2.2"
     ms "2.1.2"
     ms "2.1.2"
     regexp-clone "1.0.0"
     regexp-clone "1.0.0"
-    safe-buffer "5.1.2"
+    safe-buffer "5.2.1"
     sift "7.0.1"
     sift "7.0.1"
     sliced "1.0.1"
     sliced "1.0.1"
 
 
@@ -10610,7 +10623,7 @@ p-defer@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
   resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
 
 
-p-each-series@2.1.0, p-each-series@^2.1.0:
+p-each-series@^2.1.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48"
   resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48"
   integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==
   integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==
@@ -12976,7 +12989,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 
 
-safe-buffer@^5.0.1, safe-buffer@^5.1.2:
+safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2:
   version "5.2.1"
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -14992,6 +15005,16 @@ universalify@^0.1.0:
   version "0.1.1"
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
   resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
 
 
+universalify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
+  integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
+
+universalify@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+  integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+
 "unorm@>= 1.0.0":
 "unorm@>= 1.0.0":
   version "1.4.1"
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300"
   resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300"