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

Merge branch 'master' into feat/3176-grid-edit-modal-for-master-merge

itizawa 5 лет назад
Родитель
Сommit
e74721b9fb
29 измененных файлов с 145 добавлено и 129 удалено
  1. 7 12
      .devcontainer/docker-compose.yml
  2. 4 2
      src/client/js/app.jsx
  3. 1 1
      src/client/js/components/Admin/Security/ShareLinkSetting.jsx
  4. 1 0
      src/client/js/components/Admin/UserGroup/UserGroupPage.jsx
  5. 1 0
      src/client/js/components/Admin/UserGroupDetail/UserGroupPageList.jsx
  6. 1 1
      src/client/js/components/Admin/UserManagement.jsx
  7. 1 1
      src/client/js/components/Admin/Users/UserMenu.jsx
  8. 54 0
      src/client/js/components/ForbiddenPage.jsx
  9. 0 1
      src/client/js/components/MyDraftList/MyDraftList.jsx
  10. 3 5
      src/client/js/components/Navbar/GrowiSubNavigation.jsx
  11. 23 26
      src/client/js/components/Page/RenderTagLabels.jsx
  12. 0 5
      src/client/js/components/Page/RevisionPathControls.jsx
  13. 3 0
      src/client/js/components/Page/TagLabels.jsx
  14. 1 1
      src/client/js/components/PageAttachment.jsx
  15. 1 1
      src/client/js/components/PageList.jsx
  16. 4 1
      src/client/js/components/PaginationWrapper.jsx
  17. 6 0
      src/client/js/legacy/crowi.js
  18. 10 11
      src/client/js/services/PageContainer.js
  19. 1 1
      src/client/js/services/PageHistoryContainer.js
  20. 1 1
      src/client/styles/scss/_admin.scss
  21. 8 6
      src/client/styles/scss/_wiki.scss
  22. 1 0
      src/client/styles/scss/theme/_apply-colors.scss
  23. 2 1
      src/client/styles/scss/theme/antarctic.scss
  24. 1 1
      src/server/models/page.js
  25. 1 1
      src/server/routes/apiv3/attachment.js
  26. 1 1
      src/server/routes/index.js
  27. 8 2
      src/server/views/layout-growi/forbidden.html
  28. 0 46
      src/server/views/widget/forbidden_content.html
  29. 0 1
      src/server/views/widget/page_content.html

+ 7 - 12
.devcontainer/docker-compose.yml

@@ -22,19 +22,12 @@ services:
       - 3001:3001 # for browser-sync
 
     volumes:
-      - ..:/workspace/growi:cached
-      - /workspace/growi/node_modules
-      - ../../growi-docker-compose:/workspace/growi-docker-compose:cached
-      - ../../node_modules:/workspace/node_modules:cached
+      - ..:/workspace/growi:delegated
+      - node_modules:/workspace/growi/node_modules
+      - ../../growi-docker-compose:/workspace/growi-docker-compose:delegated
+      - ../../node_modules:/workspace/node_modules:delegated
 
-
-    # Overrides default command so things don't shut down after the process ends.
-    command: sleep infinity
-
-    links:
-      - mongo
-      - elasticsearch
-      - hackmd
+    tty: true
 
   mongo:
     image: mongo:4.4
@@ -86,3 +79,5 @@ services:
       - 3010:3000
     volumes:
       - /files/sqlite
+volumes:
+  node_modules:

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

@@ -21,6 +21,7 @@ import TrashPageList from './components/TrashPageList';
 import TrashPageAlert from './components/Page/TrashPageAlert';
 import NotFoundPage from './components/NotFoundPage';
 import NotFoundAlert from './components/Page/NotFoundAlert';
+import ForbiddenPage from './components/ForbiddenPage';
 import PageStatusAlert from './components/PageStatusAlert';
 import RecentCreated from './components/RecentCreated/RecentCreated';
 import RecentlyCreatedIcon from './components/Icons/RecentlyCreatedIcon';
@@ -86,13 +87,14 @@ Object.assign(componentMappings, {
   'trash-page-list': <TrashPageList />,
 
   'not-found-page': <NotFoundPage />,
-
   'not-found-alert': <NotFoundAlert
     onPageCreateClicked={navigationContainer.setEditorMode}
     isGuestUserMode={appContainer.isGuestUser}
-    isHidden={pageContainer.state.isForbidden || pageContainer.state.isNotCreatable || pageContainer.state.isTrashPage}
+    isHidden={pageContainer.state.isNotCreatable || pageContainer.state.isTrashPage}
   />,
 
+  'forbidden-page': <ForbiddenPage />,
+
   'page-timeline': <PageTimeline />,
 
   'personal-setting': <PersonalSettings crowi={personalContainer} />,

+ 1 - 1
src/client/js/components/Admin/Security/ShareLinkSetting.jsx

@@ -24,7 +24,7 @@ const Pager = (props) => {
       changePage={props.handlePage}
       totalItemsCount={props.totalLinks}
       pagingLimit={props.limit}
-      align="right"
+      align="center"
       size="sm"
     />
   );

+ 1 - 0
src/client/js/components/Admin/UserGroup/UserGroupPage.jsx

@@ -159,6 +159,7 @@ class UserGroupPage extends React.Component {
             changePage={this.handlePage}
             totalItemsCount={this.state.totalUserGroups}
             pagingLimit={this.state.pagingLimit}
+            align="center"
             size="sm"
           />
         )}

+ 1 - 0
src/client/js/components/Admin/UserGroupDetail/UserGroupPageList.jsx

@@ -64,6 +64,7 @@ class UserGroupPageList extends React.Component {
             changePage={this.handlePageChange}
             totalItemsCount={this.state.total}
             pagingLimit={this.state.pagingLimit}
+            align="center"
             size="sm"
           />
         )}

+ 1 - 1
src/client/js/components/Admin/UserManagement.jsx

@@ -120,7 +120,7 @@ class UserManagement extends React.Component {
           changePage={this.handlePage}
           totalItemsCount={adminUsersContainer.state.totalUsers}
           pagingLimit={adminUsersContainer.state.pagingLimit}
-          align="right"
+          align="center"
           size="sm"
         />
       </div>

+ 1 - 1
src/client/js/components/Admin/Users/UserMenu.jsx

@@ -80,7 +80,7 @@ class UserMenu extends React.Component {
 
     return (
       <Fragment>
-        <div className="btn-group admin-user-menu" role="group">
+        <div className="btn-group admin-user-menu position-absolute" role="group">
           <button id="userMenu" type="button" className="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown">
             <i className="icon-settings"></i>
           </button>

+ 54 - 0
src/client/js/components/ForbiddenPage.jsx

@@ -0,0 +1,54 @@
+import React, { useMemo } from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+import PageListIcon from './Icons/PageListIcon';
+import CustomNavigation from './CustomNavigation';
+import PageList from './PageList';
+
+
+const ForbiddenPage = (props) => {
+  const { t } = props;
+
+  const navTabMapping = useMemo(() => {
+    return {
+      pagelist: {
+        Icon: PageListIcon,
+        Content: PageList,
+        i18n: t('page_list'),
+        index: 0,
+      },
+    };
+  }, [t]);
+
+  return (
+    <>
+      <div className="row not-found-message-row mb-4">
+        <div className="col-lg-12">
+          <h2 className="text-muted">
+            <i className="icon-ban mr-2" aria-hidden="true" />
+            Forbidden
+          </h2>
+        </div>
+      </div>
+
+
+      <div className="row row-alerts d-edit-none">
+        <div className="col-sm-12">
+          <p className="alert alert-primary py-3 px-4">
+            <i className="icon-fw icon-lock" aria-hidden="true" />
+            {t('Browsing of this page is restricted')}
+          </p>
+        </div>
+      </div>
+      <div className="mt-5">
+        <CustomNavigation navTabMapping={navTabMapping} />
+      </div>
+    </>
+  );
+};
+
+ForbiddenPage.propTypes = {
+  t: PropTypes.func.isRequired,
+};
+
+export default withTranslation()(ForbiddenPage);

+ 0 - 1
src/client/js/components/MyDraftList/MyDraftList.jsx

@@ -22,7 +22,6 @@ class MyDraftList extends React.Component {
       currentDrafts: [],
       activePage: 1,
       totalDrafts: 0,
-      // [TODO: rename pageLimitationM to pageLimitationL]
       pagingLimit: Infinity,
     };
 

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

@@ -26,7 +26,7 @@ import PageManagement from '../Page/PageManagement';
 
 const PagePathNav = ({
   // eslint-disable-next-line react/prop-types
-  pageId, pagePath, isPageForbidden, isEditorMode,
+  pageId, pagePath, isEditorMode,
 }) => {
 
   const dPagePath = new DevidedPagePath(pagePath, false, true);
@@ -56,7 +56,6 @@ const PagePathNav = ({
           <RevisionPathControls
             pageId={pageId}
             pagePath={pagePath}
-            isPageForbidden={isPageForbidden}
           />
         </div>
       </span>
@@ -91,8 +90,7 @@ const GrowiSubNavigation = (props) => {
   } = props;
   const { isDrawerMode, editorMode } = navigationContainer.state;
   const {
-    pageId, path, createdAt, creator, updatedAt, revisionAuthor,
-    isPageExist, isForbidden: isPageForbidden,
+    pageId, path, createdAt, creator, updatedAt, revisionAuthor, isPageExist,
   } = pageContainer.state;
 
   const { isGuestUser } = appContainer;
@@ -121,7 +119,7 @@ const GrowiSubNavigation = (props) => {
               <TagLabels editorMode={editorMode} />
             </div>
           ) }
-          <PagePathNav pageId={pageId} pagePath={path} isPageForbidden={isPageForbidden} isEditorMode={isEditorMode} />
+          <PagePathNav pageId={pageId} pagePath={path} isEditorMode={isEditorMode} />
         </div>
       </div>
 

+ 23 - 26
src/client/js/components/Page/RenderTagLabels.jsx

@@ -2,12 +2,12 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-import PageContainer from '../../services/PageContainer';
+import { UncontrolledTooltip } from 'reactstrap';
 
-function RenderTagLabels(props) {
-  const { t, tags, pageContainer } = props;
-  const { pageId } = pageContainer;
+const RenderTagLabels = React.memo((props) => {
+  const {
+    t, tags, pageId, isGuestUser,
+  } = props;
 
   function openEditorHandler() {
     if (props.openEditorModal == null) {
@@ -35,35 +35,32 @@ function RenderTagLabels(props) {
     <>
       {tagElements}
 
-      <a className={`btn btn-link btn-edit-tags p-0 text-muted ${isTagsEmpty ? 'no-tags' : ''}`} onClick={openEditorHandler}>
-        { isTagsEmpty
-          ? (
-            <>{ t('Add tags for this page') }<i className="ml-1 icon-plus"></i></>
-          )
-          : (
-            <i className="icon-plus"></i>
-          )
-        }
-      </a>
+      <div id="edit-tags-btn-wrapper-for-tooltip">
+        <a
+          className={`btn btn-link btn-edit-tags p-0 text-muted ${isTagsEmpty && 'no-tags'} ${isGuestUser && 'disabled'}`}
+          onClick={openEditorHandler}
+        >
+          { isTagsEmpty && <>{ t('Add tags for this page') }</>}
+          <i className="ml-1 icon-plus"></i>
+        </a>
+      </div>
+      {isGuestUser && (
+        <UncontrolledTooltip placement="top" target="edit-tags-btn-wrapper-for-tooltip" fade={false}>
+          {t('Not available for guest')}
+        </UncontrolledTooltip>
+      )}
     </>
   );
 
-}
-
-/**
- * Wrapper component for using unstated
- */
-const RenderTagLabelsWrapper = withUnstatedContainers(RenderTagLabels, [PageContainer]);
-
+});
 
 RenderTagLabels.propTypes = {
   t: PropTypes.func.isRequired, // i18next
 
   tags: PropTypes.array,
   openEditorModal: PropTypes.func,
-
-  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
-
+  isGuestUser: PropTypes.bool.isRequired,
+  pageId: PropTypes.string.isRequired,
 };
 
-export default withTranslation()(RenderTagLabelsWrapper);
+export default withTranslation()(RenderTagLabels);

+ 0 - 5
src/client/js/components/Page/RevisionPathControls.jsx

@@ -29,11 +29,6 @@ RevisionPathControls.propTypes = {
 
   pagePath: PropTypes.string.isRequired,
   pageId: PropTypes.string,
-  isPageForbidden: PropTypes.bool,
-};
-
-RevisionPathControls.defaultProps = {
-  isPageForbidden: false,
 };
 
 export default withTranslation()(RevisionPathControls);

+ 3 - 0
src/client/js/components/Page/TagLabels.jsx

@@ -74,6 +74,7 @@ class TagLabels extends React.Component {
 
   render() {
     const tags = this.getTagData();
+    const { appContainer, pageContainer } = this.props;
 
     return (
       <>
@@ -84,6 +85,8 @@ class TagLabels extends React.Component {
             <RenderTagLabels
               tags={tags}
               openEditorModal={this.openEditorModal}
+              pageId={pageContainer.state.pageId}
+              isGuestUser={appContainer.isGuestUser}
             />
           </Suspense>
         </form>

+ 1 - 1
src/client/js/components/PageAttachment.jsx

@@ -18,7 +18,7 @@ class PageAttachment extends React.Component {
     this.state = {
       activePage: 1,
       totalAttachments: 0,
-      limit: null,
+      limit: Infinity,
       attachments: [],
       inUse: {},
       attachmentToDelete: null,

+ 1 - 1
src/client/js/components/PageList.jsx

@@ -19,7 +19,7 @@ const PageList = (props) => {
 
   const [activePage, setActivePage] = useState(1);
   const [totalPages, setTotalPages] = useState(0);
-  const [limit, setLimit] = useState(null);
+  const [limit, setLimit] = useState(Infinity);
 
   function setPageNumber(selectedPageNumber) {
     setActivePage(selectedPageNumber);

+ 4 - 1
src/client/js/components/PaginationWrapper.jsx

@@ -21,8 +21,11 @@ const PaginationWrapper = React.memo((props) => {
    * various numbers used to generate pagination dom
    */
   const paginationNumbers = useMemo(() => {
+    // avoid using null
+    const limit = pagingLimit || Infinity;
+
     // calc totalPageNumber
-    const totalPage = Math.floor(totalItemsCount / pagingLimit) + (totalItemsCount % pagingLimit === 0 ? 0 : 1);
+    const totalPage = Math.floor(totalItemsCount / limit) + (totalItemsCount % limit === 0 ? 0 : 1);
 
     let paginationStart = activePage - 2;
     let maxViewPageNum = activePage + 2;

+ 6 - 0
src/client/js/legacy/crowi.js

@@ -157,6 +157,12 @@ Crowi.highlightSelectedSection = function(hash) {
 window.addEventListener('load', (e) => {
   const { appContainer } = window;
   const pageContainer = appContainer.getContainer('PageContainer');
+
+  // Do nothing if the page does not exist
+  // ex.) admin page,login page
+  if (pageContainer == null) {
+    return null;
+  }
   const { isAbleToOpenPageEditor } = pageContainer;
 
   // hash on page

+ 10 - 11
src/client/js/services/PageContainer.js

@@ -63,7 +63,6 @@ export default class PageContainer extends Container {
 
       isUserPage: JSON.parse(mainContent.getAttribute('data-page-user')) != null,
       isTrashPage: isTrashPage(path),
-      isForbidden: JSON.parse(mainContent.getAttribute('data-page-is-forbidden')),
       isDeleted: JSON.parse(mainContent.getAttribute('data-page-is-deleted')),
       isDeletable: JSON.parse(mainContent.getAttribute('data-page-is-deletable')),
       isNotCreatable: JSON.parse(mainContent.getAttribute('data-page-is-not-creatable')),
@@ -149,10 +148,10 @@ export default class PageContainer extends Container {
 
 
   get isAbleToOpenPageEditor() {
-    const { isPageForbidden, isNotCreatable, isTrashPage } = this.state;
+    const { isNotCreatable, isTrashPage } = this.state;
     const { isGuestUser } = this.appContainer;
 
-    return (!isPageForbidden && !isNotCreatable && !isTrashPage && !isGuestUser);
+    return (!isNotCreatable && !isTrashPage && !isGuestUser);
   }
 
   /**
@@ -170,10 +169,10 @@ export default class PageContainer extends Container {
    * whether to display tag labels
    */
   get isAbleToShowTagLabel() {
-    const { isPageForbidden, isUserPage } = this.state;
+    const { isUserPage } = this.state;
     const { isSharedUser } = this.appContainer;
 
-    return (!isPageForbidden && !isUserPage && !isSharedUser);
+    return (!isUserPage && !isSharedUser);
   }
 
   /**
@@ -181,10 +180,10 @@ export default class PageContainer extends Container {
    * ex.) duplicate, rename
    */
   get isAbleToShowPageManagement() {
-    const { isPageForbidden, isPageExist, isPageInTrash } = this.state;
+    const { isPageExist, isPageInTrash } = this.state;
     const { isSharedUser } = this.appContainer;
 
-    return (!isPageForbidden && isPageExist && !isPageInTrash && !isSharedUser);
+    return (isPageExist && !isPageInTrash && !isSharedUser);
   }
 
   /**
@@ -192,10 +191,10 @@ export default class PageContainer extends Container {
    * ex.) view, edit, hackmd
    */
   get isAbleToShowThreeStrandedButton() {
-    const { isPageForbidden, isNotCreatable, isPageInTrash } = this.state;
+    const { isNotCreatable, isPageInTrash } = this.state;
     const { isSharedUser, isGuestUser } = this.appContainer;
 
-    return (!isPageForbidden && !isNotCreatable && !isPageInTrash && !isSharedUser && !isGuestUser);
+    return (!isNotCreatable && !isPageInTrash && !isSharedUser && !isGuestUser);
   }
 
   /**
@@ -203,9 +202,9 @@ export default class PageContainer extends Container {
    * ex.) view, edit, hackmd
    */
   get isAbleToShowPageAuthors() {
-    const { isPageForbidden, isPageExist, isUserPage } = this.state;
+    const { isPageExist, isUserPage } = this.state;
 
-    return (!isPageForbidden && isPageExist && !isUserPage);
+    return (isPageExist && !isUserPage);
   }
 
   /**

+ 1 - 1
src/client/js/services/PageHistoryContainer.js

@@ -28,7 +28,7 @@ export default class PageHistoryContainer extends Container {
 
       totalPages: 0,
       activePage: 1,
-      pagingLimit: null,
+      pagingLimit: Infinity,
     };
 
     this.retrieveRevisions = this.retrieveRevisions.bind(this);

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

@@ -52,7 +52,7 @@
     }
 
     .auth-mechanism-configurations {
-      min-height: 300px;
+      min-height: 80vh;
     }
   }
 

+ 8 - 6
src/client/styles/scss/_wiki.scss

@@ -12,11 +12,6 @@ div.body {
 
   font-size: 15px;
 
-  // override line-height except hljs and child of it.
-  :not(pre*) {
-    line-height: 1.8em;
-  }
-
   h1,
   h2,
   h3,
@@ -90,6 +85,10 @@ div.body {
     li {
       margin: 5px 0;
       line-height: 1.8em;
+
+      pre {
+        line-height: $line-height-base;
+      }
     }
 
     ul,
@@ -207,7 +206,10 @@ div.body {
       margin: 10px 0;
 
       li {
-        line-height: 1.1em;
+        line-height: $line-height-base;
+        pre {
+          line-height: $line-height-base;
+        }
       }
     }
 

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

@@ -329,6 +329,7 @@ ul.pagination {
 .grw-custom-nav {
   .nav-item {
     .nav-link {
+      -webkit-appearance: none;
       color: $color-link;
       svg {
         fill: $color-link;

+ 2 - 1
src/client/styles/scss/theme/antarctic.scss

@@ -98,7 +98,8 @@ html[dark] {
   $color-editor-icons: $color-global;
 
   // Border colors
-  $border-color-theme: $gray-300; // former: `$navbar-border: $gray-300;`
+  $border-color-theme: $gray-400;
+  $border-color-global: $gray-400;
   $bordercolor-inline-code: #ccc8c8; // optional
 
   // Dropdown colors

+ 1 - 1
src/server/models/page.js

@@ -403,7 +403,7 @@ module.exports = function(crowi) {
       throw new Error('User data is not valid');
     }
 
-    const added = this.seenUsers.addToSet(userData);
+    const added = this.seenUsers.addToSet(userData._id);
     const saved = await this.save();
 
     debug('seenUsers updated!', added);

+ 1 - 1
src/server/routes/apiv3/attachment.js

@@ -17,7 +17,7 @@ const ErrorV3 = require('../../models/vo/error-apiv3');
 
 module.exports = (crowi) => {
   const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
-  const loginRequired = require('../../middlewares/login-required')(crowi);
+  const loginRequired = require('../../middlewares/login-required')(crowi, true);
   const Page = crowi.model('Page');
   const User = crowi.model('User');
   const Attachment = crowi.model('Attachment');

+ 1 - 1
src/server/routes/index.js

@@ -151,7 +151,7 @@ module.exports = function(crowi, app) {
   app.get('/tags'                     , loginRequired, tag.showPage);
   app.get('/_api/tags.list'           , accessTokenParser, loginRequired, tag.api.list);
   app.get('/_api/tags.search'         , accessTokenParser, loginRequired, tag.api.search);
-  app.post('/_api/tags.update'        , accessTokenParser, loginRequired, tag.api.update);
+  app.post('/_api/tags.update'        , accessTokenParser, loginRequiredStrictly, tag.api.update);
   app.get('/_api/comments.get'        , accessTokenParser , loginRequired , comment.api.get);
   app.post('/_api/comments.add'       , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , csrf, comment.api.add);
   app.post('/_api/comments.update'    , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , csrf, comment.api.update);

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

@@ -8,9 +8,15 @@
 {% endblock %}
 
 {% block content_main %}
-  <div class="container-lg">
-    {% include '../widget/forbidden_content.html' %}
+  <div
+    id="content-main"
+    class="content-main page-list"
+    data-path="{{ encodeURI(path) }}"
+    data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
+    data-page-is-not-creatable="true"
+    >
   </div>
+  <div class="container-lg" id="forbidden-page"></div>
 {% endblock %}
 
 {% block body_end %}

+ 0 - 46
src/server/views/widget/forbidden_content.html

@@ -1,46 +0,0 @@
-<div class="row not-found-message-row mb-4">
-  <div class="col-lg-12">
-    <h2 class="text-muted">
-      <i class="icon-ban" aria-hidden="true"></i>
-      Forbidden
-    </h2>
-  </div>
-</div>
-
-<div id="content-main" class="content-main page-list"
-  data-path="{{ encodeURI(path) }}"
-  data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-  data-page-is-forbidden="true"
-  data-page-is-not-creatable="true"
-  >
-
-  <div class="row row-alerts d-edit-none">
-    <div class="col-sm-12">
-        <p class="alert alert-primary py-3 px-4">
-          <i class="icon-fw icon-lock" aria-hidden="true"></i> Browsing of this page is restricted
-        </p>
-    </div>
-  </div>
-
-  <ul class="nav nav-tabs d-print-none" role="tablist">
-    <li class="nav-item grw-nav-main-left-tab">
-      <a class="nav-link active">
-        <i class="icon-notebook"></i> List
-      </a>
-    </li>
-  </ul>
-
-  <div class="tab-content">
-    {# list view #}
-    <div class="pt-2 active tab-pane page-list-container">
-      {% if pages.length == 0 %}
-        <div class="mt-2">
-          There are no pages under <strong>{{ path | preventXss }}</strong>.
-        </div>
-      {% endif  %}
-
-      {% include '../widget/page_list.html' with { pages: pages, pager: pager, viewConfig: viewConfig } %}
-    </div>
-
-  </div>
-</div>

+ 0 - 1
src/server/views/widget/page_content.html

@@ -14,7 +14,6 @@
   data-page-grant-group-name="{{ grantedGroupName }}"
   data-page-is-liked="{% if user %}{{ page.isLiked(user) }}{% else %}false{% endif %}"
   data-page-is-seen="{% if page and page.isSeenUser(user) %}1{% else %}0{% endif %}"
-  data-page-is-forbidden="false"
   data-page-is-deleted="{% if page.isDeleted() %}true{% else %}false{% endif %}"
   data-page-is-deletable="{% if isDeletablePage() %}true{% else %}false{% endif %}"
   data-page-is-not-creatable="false"