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

Merge pull request #2910 from weseek/feat/add-paging-for-contents-in-pageAccessoriesModal

Feat/add paging for contents in page accessories modal
Sizma yosimaz 5 лет назад
Родитель
Сommit
401de27261

+ 3 - 3
resource/locales/en_US/admin/admin.json

@@ -112,10 +112,10 @@
       "list_num_desc_s": "Set number of list per page such as 'Pagelist', 'Timeline', 'Page History' and 'Share Link' pages",
 
       "list_num_m": "Number of list displayed on article pages included other contents",
-      "list_num_desc_m": "Set number of list per page such as 'Bookmarks', 'Recently created' and 'Drafts'",
+      "list_num_desc_m": "Set number of list per page such as 'Bookmarks' and 'Recently created' pages",
 
-      "list_num_l": "Number of list displayed on 'Search' and 'Draft' pages",
-      "list_num_desc_l": "Set number of list per page such as 'Search' and 'Draft' pages",
+      "list_num_l": "Number of list displayed on 'Search' pages",
+      "list_num_desc_l": "Set number of list per page such as 'Search' pages",
 
       "list_num_xl": "Number of list displayed on article pages",
       "list_num_desc_xl": "Set number of list per page such as 'Not found' and 'Trash' pages",

+ 2 - 2
resource/locales/ja_JP/admin/admin.json

@@ -114,8 +114,8 @@
       "list_num_m": "ユーザーページに表示されるリスト数",
       "list_num_desc_m": "ユーザーページにおける <Bookmarks> <Recently Created>での、1ページあたりの表示数を設定します。",
 
-      "list_num_l": "検索ページやDraftページに表示されるリスト数",
-      "list_num_desc_l": "<Search> <My Drafts> での、1ページあたりの表示数を設定します。",
+      "list_num_l": "検索ページに表示されるリスト数",
+      "list_num_desc_l": "<Search>での、1ページあたりの表示数を設定します。",
 
       "list_num_xl": "Not FoundページやTrashページに表示されるリスト数",
       "list_num_desc_xl": "記事エリアにおける<Not Found> <Trash>での、1ページあたりの表示数を設定します。",

+ 3 - 3
resource/locales/zh_CN/admin/admin.json

@@ -124,10 +124,10 @@
       "list_num_desc_s": "Set number of list per page such as 'Pagelist', 'Timeline', 'Page History' and 'Share Link' pages",
 
       "list_num_m": "Number of list displayed on article pages included other contents",
-      "list_num_desc_m": "Set number of list per page such as 'Bookmarks', 'Recently created' and 'Drafts'",
+      "list_num_desc_m": "Set number of list per page such as 'Bookmarks' and 'Recently created' pages",
 
-      "list_num_l": "Number of list displayed on 'Search' and 'Draft' pages",
-      "list_num_desc_l": "Set number of list per page such as 'Search' and 'Draft' pages",
+      "list_num_l": "Number of list displayed on 'Search' pages",
+      "list_num_desc_l": "Set number of list per page such as 'Search' pages",
 
       "list_num_xl": "Number of list displayed on article pages",
       "list_num_desc_xl": "Set number of list per page such as 'Not found' and 'Trash' pages",

+ 2 - 7
src/client/js/components/MyBookmarkList/MyBookmarkList.jsx

@@ -23,7 +23,7 @@ class MyBookmarkList extends React.Component {
       pages: [],
       activePage: 1,
       totalPages: 0,
-      pagingLimit: Infinity,
+      pagingLimit: null,
     };
 
     this.handlePage = this.handlePage.bind(this);
@@ -39,16 +39,11 @@ class MyBookmarkList extends React.Component {
 
   async getMyBookmarkList(selectPageNumber) {
     const { appContainer } = this.props;
-
     const userId = appContainer.currentUserId;
-    /* TODO #2 change variable name in database keys */
-    /* TODO #3 write migration */
-    const limit = appContainer.getConfig().pageLimitationM;
     const page = selectPageNumber;
-    const params = { page, limit };
 
     try {
-      const { data } = await this.props.appContainer.apiv3.get(`/bookmarks/${userId}`, params);
+      const { data } = await this.props.appContainer.apiv3.get(`/bookmarks/${userId}`, { page });
       if (data.paginationResult == null) {
         throw new Error('data must conclude \'paginateResult\' property.');
       }

+ 3 - 3
src/client/js/components/MyDraftList/MyDraftList.jsx

@@ -22,6 +22,7 @@ class MyDraftList extends React.Component {
       currentDrafts: [],
       activePage: 1,
       totalDrafts: 0,
+      // [TODO: rename pageLimitationM to pageLimitationL]
       pagingLimit: Infinity,
     };
 
@@ -67,9 +68,8 @@ class MyDraftList extends React.Component {
   }
 
   getCurrentDrafts(selectPageNumber) {
-    const { appContainer } = this.props;
-    // [TODO: rename pageLimitationM to pageLimitationL]
-    const limit = appContainer.getConfig().pageLimitationM;
+    // TODO implement temporarily paging number only this component (this paging size is pageLimitationL).
+    const limit = this.state.pagingLimit;
 
     const totalDrafts = this.state.drafts.length;
     const activePage = selectPageNumber;

+ 7 - 12
src/client/js/components/PageAttachment.jsx

@@ -14,11 +14,11 @@ class PageAttachment extends React.Component {
 
   constructor(props) {
     super(props);
-    // TODO add paging size (limit) for modal
+
     this.state = {
       activePage: 1,
-      limit: 10,
       totalAttachments: 0,
+      limit: null,
       attachments: [],
       inUse: {},
       attachmentToDelete: null,
@@ -34,27 +34,24 @@ class PageAttachment extends React.Component {
 
   async handlePage(selectedPage) {
     const { pageId } = this.props.pageContainer.state;
-    const { limit } = this.state;
-    const offset = (selectedPage - 1) * limit;
-    const activePage = selectedPage;
+    const page = selectedPage;
 
     if (!pageId) { return }
 
-    const res = await this.props.appContainer.apiv3Get('/attachment/list', {
-      pageId, limit, offset,
-    });
+    const res = await this.props.appContainer.apiv3Get('/attachment/list', { pageId, page });
     const attachments = res.data.paginateResult.docs;
     const totalAttachments = res.data.paginateResult.totalDocs;
+    const pagingLimit = res.data.paginateResult.limit;
 
     const inUse = {};
 
     for (const attachment of attachments) {
       inUse[attachment._id] = this.checkIfFileInUse(attachment);
     }
-
     this.setState({
-      activePage,
+      activePage: selectedPage,
       totalAttachments,
+      limit: pagingLimit,
       attachments,
       inUse,
     });
@@ -114,11 +111,9 @@ class PageAttachment extends React.Component {
 
 
   render() {
-
     const { t } = this.props;
     if (this.state.attachments.length === 0) {
       return t('No_attachments_yet');
-
     }
 
     let deleteAttachmentModal = '';

+ 11 - 10
src/client/js/components/PageHistory.jsx

@@ -14,9 +14,12 @@ import PaginationWrapper from './PaginationWrapper';
 
 const logger = loggerFactory('growi:PageHistory');
 
-// TODO add paging size (limit) for modal
 function PageHistory(props) {
   const { pageHistoryContainer } = props;
+  const { getPreviousRevision, onDiffOpenClicked } = pageHistoryContainer;
+  const {
+    activePage, totalPages, pagingLimit, revisions, diffOpened,
+  } = pageHistoryContainer.state;
 
   const handlePage = useCallback(async(selectedPage) => {
     try {
@@ -50,27 +53,25 @@ function PageHistory(props) {
     });
   }
 
-
   function pager() {
     return (
       <PaginationWrapper
-        activePage={pageHistoryContainer.state.activePage}
+        activePage={activePage}
         changePage={handlePage}
-        totalItemsCount={pageHistoryContainer.state.totalPages}
-        pagingLimit={pageHistoryContainer.state.pagingLimit}
+        totalItemsCount={totalPages}
+        pagingLimit={pagingLimit}
         align="center"
       />
     );
   }
 
-
   return (
     <div>
       <PageRevisionList
-        revisions={pageHistoryContainer.state.revisions}
-        diffOpened={pageHistoryContainer.state.diffOpened}
-        getPreviousRevision={pageHistoryContainer.getPreviousRevision}
-        onDiffOpenClicked={pageHistoryContainer.onDiffOpenClicked}
+        revisions={revisions}
+        diffOpened={diffOpened}
+        getPreviousRevision={getPreviousRevision}
+        onDiffOpenClicked={onDiffOpenClicked}
       />
       {pager()}
     </div>

+ 4 - 6
src/client/js/components/PageList.jsx

@@ -18,23 +18,21 @@ const PageList = (props) => {
 
   const [activePage, setActivePage] = useState(1);
   const [totalPages, setTotalPages] = useState(0);
-  const [limit, setLimit] = useState(appContainer.getConfig().recentCreatedLimit);
-  const [offset, setOffset] = useState(0);
+  const [limit, setLimit] = useState(null);
 
   function setPageNumber(selectedPageNumber) {
     setActivePage(selectedPageNumber);
-    setOffset((selectedPageNumber - 1) * limit);
   }
 
   const updatePageList = useCallback(async() => {
-    const res = await appContainer.apiv3Get('/pages/list', { path, limit, offset });
+    const page = activePage;
+    const res = await appContainer.apiv3Get('/pages/list', { path, page });
 
     setPages(res.data.pages);
     setIsLoading(true);
     setTotalPages(res.data.totalCount);
     setLimit(res.data.limit);
-    setOffset(res.data.offset);
-  }, [appContainer, path, limit, offset]);
+  }, [appContainer, path, activePage]);
 
   useEffect(() => {
     updatePageList();

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

@@ -16,12 +16,10 @@ class PageTimeline extends React.Component {
   constructor(props) {
     super(props);
 
-    const { appContainer } = this.props;
-    // TODO add paging size (limit) for modal
     this.state = {
       activePage: 1,
       totalPageItems: 0,
-      limit: appContainer.getConfig().recentCreatedLimit,
+      limit: null,
 
       // TODO: remove after when timeline is implemented with React and inject data with props
       pages: this.props.pages,
@@ -34,17 +32,17 @@ class PageTimeline extends React.Component {
   async handlePage(selectedPage) {
     const { appContainer, pageContainer } = this.props;
     const { path } = pageContainer.state;
-    const { limit } = this.state;
-    const offset = (selectedPage - 1) * limit;
-    const activePage = selectedPage;
+    const page = selectedPage;
 
-    const res = await appContainer.apiv3Get('/pages/list', { path, limit, offset });
+    const res = await appContainer.apiv3Get('/pages/list', { path, page });
     const totalPageItems = res.data.totalCount;
     const pages = res.data.pages;
+    const pagingLimit = res.data.limit;
     this.setState({
-      activePage,
+      activePage: selectedPage,
       totalPageItems,
       pages,
+      limit: pagingLimit,
     });
   }
 

+ 5 - 3
src/client/js/components/PaginationWrapper.jsx

@@ -14,10 +14,10 @@ class PaginationWrapper extends React.Component {
     super(props);
 
     this.state = {
-      totalItemsCount: 0,
       activePage: 1,
+      totalItemsCount: 0,
       paginationNumbers: {},
-      limit: Infinity,
+      limit: this.props.pagingLimit || Infinity,
     };
 
     this.calculatePagination = this.calculatePagination.bind(this);
@@ -189,11 +189,13 @@ PaginationWrapper.propTypes = {
   activePage: PropTypes.number.isRequired,
   changePage: PropTypes.func.isRequired,
   totalItemsCount: PropTypes.number.isRequired,
-  pagingLimit: PropTypes.number.isRequired,
+  pagingLimit: PropTypes.number,
   align: PropTypes.string,
 };
 PaginationWrapper.defaultProps = {
   align: 'left',
+  pagingLimit: PropTypes.number,
+
 };
 
 export default withTranslation()(PaginationWrappered);

+ 6 - 8
src/client/js/components/RecentCreated/RecentCreated.jsx

@@ -17,7 +17,7 @@ class RecentCreated extends React.Component {
       pages: [],
       activePage: 1,
       totalPages: 0,
-      pagingLimit: Infinity,
+      pagingLimit: null,
     };
 
     this.handlePage = this.handlePage.bind(this);
@@ -32,20 +32,18 @@ class RecentCreated extends React.Component {
     await this.getRecentCreatedList(selectedPage);
   }
 
-  async getRecentCreatedList(selectPageNumber) {
+  async getRecentCreatedList(selectedPage) {
     const { appContainer, userId } = this.props;
-
+    const page = selectedPage;
     // const userId = appContainer.currentUserId;
-    const limit = appContainer.getConfig().pageLimitationM;
-    const offset = (selectPageNumber - 1) * limit;
 
     // pagesList get and pagination calculate
-    const res = await appContainer.apiv3Get(`/users/${userId}/recent`, { offset, limit });
-    const { totalCount, pages } = res.data;
+    const res = await appContainer.apiv3Get(`/users/${userId}/recent`, { page });
+    const { totalCount, pages, limit } = res.data;
 
     this.setState({
       pages,
-      activePage: selectPageNumber,
+      activePage: selectedPage,
       totalPages: totalCount,
       pagingLimit: limit,
     });

+ 6 - 4
src/client/js/services/PageHistoryContainer.js

@@ -17,7 +17,6 @@ export default class PageHistoryContainer extends Container {
 
     this.appContainer = appContainer;
     this.pageContainer = pageContainer;
-
     this.dummyRevisions = 0;
 
     this.state = {
@@ -29,7 +28,7 @@ export default class PageHistoryContainer extends Container {
 
       totalPages: 0,
       activePage: 1,
-      pagingLimit: Infinity,
+      pagingLimit: null,
     };
 
     this.retrieveRevisions = this.retrieveRevisions.bind(this);
@@ -51,13 +50,16 @@ export default class PageHistoryContainer extends Container {
    */
   async retrieveRevisions(selectedPage) {
     const { pageId, shareLinkId } = this.pageContainer.state;
+    const page = selectedPage;
+
     if (!pageId) {
       return;
     }
 
-    const res = await this.appContainer.apiv3Get('/revisions/list', { pageId, shareLinkId, selectedPage });
+    const res = await this.appContainer.apiv3Get('/revisions/list', {
+      pageId, shareLinkId, page,
+    });
     const rev = res.data.docs;
-
     // set Pagination state
     this.setState({
       activePage: selectedPage,

+ 7 - 5
src/server/routes/apiv3/attachment.js

@@ -23,12 +23,10 @@ module.exports = (crowi) => {
   const Attachment = crowi.model('Attachment');
   const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
 
-
   const validator = {
     retrieveAttachments: [
       query('pageId').isMongoId().withMessage('pageId is required'),
-      query('limit').isInt({ min: 1 }),
-      query('offset').isInt({ min: 0 }),
+      query('limit').if(value => value != null).isInt({ max: 100 }).withMessage('You should set less than 100 or not to set limit.'),
     ],
   };
   /**
@@ -50,8 +48,10 @@ module.exports = (crowi) => {
    *              type: string
    */
   router.get('/list', accessTokenParser, loginRequired, validator.retrieveAttachments, apiV3FormValidator, async(req, res) => {
-    const offset = +req.query.offset || 0;
-    const limit = +req.query.limit || 30;
+
+    const limit = req.query.limit || await crowi.configManager.getConfig('crowi', 'customize:showPageLimitationS') || 10;
+    const page = req.query.page;
+    const offset = (page - 1) * limit;
 
     try {
       const pageId = req.query.pageId;
@@ -62,6 +62,8 @@ module.exports = (crowi) => {
         return res.apiv3Err(new ErrorV3(msg, 'attachment-list-failed'), 403);
       }
 
+      // directly get paging-size from db. not to delivery from client side.
+
       const paginateResult = await Attachment.paginate(
         { page: pageId },
         {

+ 4 - 1
src/server/routes/apiv3/bookmarks.js

@@ -145,11 +145,14 @@ module.exports = (crowi) => {
    */
   validator.myBookmarkList = [
     query('page').isInt({ min: 1 }),
+    query('limit').if(value => value != null).isInt({ max: 300 }).withMessage('You should set less than 300 or not to set limit.'),
   ];
 
   router.get('/:userId', accessTokenParser, loginRequired, validator.myBookmarkList, apiV3FormValidator, async(req, res) => {
     const { userId } = req.params;
-    const { page, limit } = req.query;
+    const page = req.query.page;
+    const limit = parseInt(req.query.limit) || await crowi.configManager.getConfig('crowi', 'customize:showPageLimitationM') || 30;
+
     if (userId == null) {
       return res.apiv3Err('User id is not found or forbidden', 400);
     }

+ 2 - 0
src/server/routes/apiv3/customize-setting.js

@@ -37,6 +37,8 @@ const ErrorV3 = require('../../models/vo/error-apiv3');
  *            type: boolean
  *          isEnabledAttachTitleHeader:
  *            type: boolean
+ *          pageLimitationS:
+ *            type: number
  *          pageLimitationM:
  *            type: number
  *          isEnabledStaleNotification:

+ 14 - 6
src/server/routes/apiv3/pages.js

@@ -1,12 +1,10 @@
 const loggerFactory = require('@alias/logger');
 
 const logger = loggerFactory('growi:routes:apiv3:pages'); // eslint-disable-line no-unused-vars
-
 const express = require('express');
 
-
 const router = express.Router();
-
+const { query } = require('express-validator');
 
 /**
  * @swagger
@@ -18,9 +16,13 @@ module.exports = (crowi) => {
   const loginRequired = require('../../middlewares/login-required')(crowi, true);
   const adminRequired = require('../../middlewares/admin-required')(crowi);
   const csrf = require('../../middlewares/csrf')(crowi);
+  const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
+
 
   const Page = crowi.model('Page');
 
+  const validator = {};
+
   /**
    * @swagger
    *
@@ -84,10 +86,16 @@ module.exports = (crowi) => {
     }
   });
 
-  router.get('/list', accessTokenParser, loginRequired, async(req, res) => {
+  validator.displayList = [
+    query('limit').if(value => value != null).isInt({ max: 100 }).withMessage('You should set less than 100 or not to set limit.'),
+  ];
+
+  router.get('/list', accessTokenParser, loginRequired, validator.displayList, apiV3FormValidator, async(req, res) => {
+    const limit = parseInt(req.query.limit) || await crowi.configManager.getConfig('crowi', 'customize:showPageLimitationS') || 10;
     const { path } = req.query;
-    const limit = +req.query.limit || 30;
-    const offset = +req.query.offset || 0;
+    const page = req.query.page;
+    const offset = (page - 1) * limit;
+
     const queryOptions = { offset, limit };
 
     try {

+ 6 - 5
src/server/routes/apiv3/revisions.js

@@ -9,8 +9,6 @@ const ErrorV3 = require('../../models/vo/error-apiv3');
 
 const router = express.Router();
 
-const PAGE_ITEMS = 30;
-
 /**
  * @swagger
  *  tags:
@@ -71,7 +69,9 @@ module.exports = (crowi) => {
   const validator = {
     retrieveRevisions: [
       query('pageId').isMongoId().withMessage('pageId is required'),
-      query('selectedPage').isInt({ min: 0 }).withMessage('selectedPage must be int'),
+      query('page').isInt({ min: 0 }).withMessage('page must be int'),
+      query('limit').if(value => value != null).isInt({ max: 100 }).withMessage('You should set less than 100 or not to set limit.'),
+
     ],
     retrieveRevisionById: [
       query('pageId').isMongoId().withMessage('pageId is required'),
@@ -99,9 +99,10 @@ module.exports = (crowi) => {
    */
   router.get('/list', certifySharedPage, accessTokenParser, loginRequired, validator.retrieveRevisions, apiV3FormValidator, async(req, res) => {
     const pageId = req.query.pageId;
+    const limit = req.query.limit || await crowi.configManager.getConfig('crowi', 'customize:showPageLimitationS') || 10;
     const { isSharedPage } = req;
 
-    const selectedPage = parseInt(req.query.selectedPage) || 1;
+    const selectedPage = parseInt(req.query.page) || 1;
 
     // check whether accessible
     if (!isSharedPage && !(await Page.isAccessiblePageByViewer(pageId, req.user))) {
@@ -115,7 +116,7 @@ module.exports = (crowi) => {
         { path: page.path },
         {
           page: selectedPage,
-          limit: PAGE_ITEMS,
+          limit,
           sort: { createdAt: -1 },
           populate: {
             path: 'author',

+ 8 - 3
src/server/routes/apiv3/users.js

@@ -105,6 +105,10 @@ module.exports = (crowi) => {
     query('page').isInt({ min: 1 }),
   ];
 
+  validator.recentCreatedByUser = [
+    query('limit').if(value => value != null).isInt({ max: 300 }).withMessage('You should set less than 300 or not to set limit.'),
+  ];
+
   /**
    * @swagger
    *
@@ -224,7 +228,7 @@ module.exports = (crowi) => {
    *                    paginateResult:
    *                      $ref: '#/components/schemas/PaginateResult'
    */
-  router.get('/:id/recent', accessTokenParser, loginRequired, async(req, res) => {
+  router.get('/:id/recent', accessTokenParser, loginRequired, validator.recentCreatedByUser, apiV3FormValidator, async(req, res) => {
     const { id } = req.params;
 
     let user;
@@ -242,8 +246,9 @@ module.exports = (crowi) => {
       return res.apiv3Err(new ErrorV3('find-user-is-not-found'));
     }
 
-    const limit = parseInt(req.query.limit) || 50;
-    const offset = parseInt(req.query.offset) || 0;
+    const limit = parseInt(req.query.limit) || await crowi.configManager.getConfig('crowi', 'customize:showPageLimitationM') || 30;
+    const page = req.query.page;
+    const offset = (page - 1) * limit;
     const queryOptions = { offset, limit };
 
     try {