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

Merge pull request #1083 from weseek/imprv/reactify-admin-paginationWrapper

pagination for usergrouppage
Yuki Takei 6 лет назад
Родитель
Сommit
01d27d4af4

+ 27 - 3
src/client/js/components/Admin/UserGroup/UserGroupPage.jsx

@@ -1,6 +1,7 @@
 import React, { Fragment } from 'react';
 import PropTypes from 'prop-types';
 
+import PaginationWrapper from '../../PaginationWrapper';
 import UserGroupTable from './UserGroupTable';
 import UserGroupCreateForm from './UserGroupCreateForm';
 import UserGroupDeleteModal from './UserGroupDeleteModal';
@@ -19,10 +20,14 @@ class UserGroupPage extends React.Component {
       userGroupRelations: {},
       selectedUserGroup: undefined, // not null but undefined (to use defaultProps in UserGroupDeleteModal)
       isDeleteModalShow: false,
+      activePage: 1,
+      totalUserGroups: 0,
+      pagingLimit: Infinity,
     };
 
     this.xss = window.xss;
 
+    this.handlePage = this.handlePage.bind(this);
     this.showDeleteModal = this.showDeleteModal.bind(this);
     this.hideDeleteModal = this.hideDeleteModal.bind(this);
     this.addUserGroup = this.addUserGroup.bind(this);
@@ -96,23 +101,35 @@ class UserGroupPage extends React.Component {
     }
   }
 
+  async handlePage(selectedPage) {
+    await this.setState({ activePage: selectedPage });
+    await this.syncUserGroupAndRelations();
+  }
+
   async syncUserGroupAndRelations() {
     let userGroups = [];
     let userGroupRelations = {};
+    let totalUserGroups = 0;
+    let pagingLimit = Infinity;
 
     try {
+      const params = { page: this.state.activePage };
       const responses = await Promise.all([
-        this.props.appContainer.apiv3.get('/user-groups'),
-        this.props.appContainer.apiv3.get('/user-group-relations'),
+        this.props.appContainer.apiv3.get('/user-groups', params),
+        this.props.appContainer.apiv3.get('/user-group-relations', params),
       ]);
 
       const [userGroupsRes, userGroupRelationsRes] = responses;
       userGroups = userGroupsRes.data.userGroups;
+      totalUserGroups = userGroupsRes.data.totalUserGroups;
+      pagingLimit = userGroupsRes.data.pagingLimit;
       userGroupRelations = userGroupRelationsRes.data.userGroupRelations;
 
       this.setState({
         userGroups,
         userGroupRelations,
+        totalUserGroups,
+        pagingLimit,
       });
     }
     catch (err) {
@@ -129,10 +146,17 @@ class UserGroupPage extends React.Component {
         />
         <UserGroupTable
           userGroups={this.state.userGroups}
-          userGroupRelations={this.state.userGroupRelations}
           isAclEnabled={this.props.isAclEnabled}
           onDelete={this.showDeleteModal}
+          userGroupRelations={this.state.userGroupRelations}
         />
+        <PaginationWrapper
+          activePage={this.state.activePage}
+          changePage={this.handlePage}
+          totalItemsCount={this.state.totalUserGroups}
+          pagingLimit={this.state.pagingLimit}
+        >
+        </PaginationWrapper>
         <UserGroupDeleteModal
           userGroups={this.state.userGroups}
           deleteUserGroup={this.state.selectedUserGroup}

+ 15 - 3
src/client/js/components/Admin/UserGroup/UserGroupTable.jsx

@@ -13,13 +13,25 @@ class UserGroupTable extends React.Component {
 
     this.xss = window.xss;
 
+    this.state = {
+      userGroups: this.props.userGroups,
+      userGroupRelations: this.props.userGroupRelations,
+    };
+
     this.onDelete = this.onDelete.bind(this);
   }
 
+  componentWillReceiveProps(nextProps) {
+    this.setState({
+      userGroups: nextProps.userGroups,
+      userGroupRelations: nextProps.userGroupRelations,
+    });
+  }
+
   onDelete(e) {
     const { target } = e;
     const groupId = target.getAttribute('data-user-group-id');
-    const group = this.props.userGroups.find((group) => {
+    const group = this.state.userGroups.find((group) => {
       return group._id === groupId;
     });
 
@@ -43,7 +55,7 @@ class UserGroupTable extends React.Component {
             </tr>
           </thead>
           <tbody>
-            {this.props.userGroups.map((group) => {
+            {this.state.userGroups.map((group) => {
               return (
                 <tr key={group._id}>
                   {this.props.isAclEnabled
@@ -56,7 +68,7 @@ class UserGroupTable extends React.Component {
                   }
                   <td>
                     <ul className="list-inline">
-                      {this.props.userGroupRelations[group._id].map((user) => {
+                      {this.state.userGroupRelations[group._id].map((user) => {
                         return <li key={user._id} className="list-inline-item badge badge-primary">{this.xss.process(user.username)}</li>;
                       })}
                     </ul>

+ 23 - 121
src/client/js/components/MyDraftList/MyDraftList.jsx

@@ -3,13 +3,13 @@ import PropTypes from 'prop-types';
 
 import { withTranslation } from 'react-i18next';
 
-import Pagination from 'react-bootstrap/lib/Pagination';
-
 import { createSubscribedElement } from '../UnstatedUtils';
 import AppContainer from '../../services/AppContainer';
 import PageContainer from '../../services/PageContainer';
 import EditorContainer from '../../services/EditorContainer';
 
+import PaginationWrapper from '../PaginationWrapper';
+
 import Draft from './Draft';
 
 class MyDraftList extends React.Component {
@@ -21,14 +21,15 @@ class MyDraftList extends React.Component {
       drafts: [],
       currentDrafts: [],
       activePage: 1,
-      paginationNumbers: {},
+      totalDrafts: 0,
+      pagingLimit: Infinity,
     };
 
+    this.handlePage = this.handlePage.bind(this);
     this.getDraftsFromLocalStorage = this.getDraftsFromLocalStorage.bind(this);
     this.getCurrentDrafts = this.getCurrentDrafts.bind(this);
     this.clearDraft = this.clearDraft.bind(this);
     this.clearAllDrafts = this.clearAllDrafts.bind(this);
-    this.calculatePagination = this.calculatePagination.bind(this);
   }
 
   async componentWillMount() {
@@ -36,6 +37,11 @@ class MyDraftList extends React.Component {
     this.getCurrentDrafts(1);
   }
 
+  async handlePage(selectedPage) {
+    await this.getDraftsFromLocalStorage();
+    await this.getCurrentDrafts(selectedPage);
+  }
+
   async getDraftsFromLocalStorage() {
     const draftsAsObj = this.props.editorContainer.drafts;
 
@@ -53,7 +59,7 @@ class MyDraftList extends React.Component {
       };
     });
 
-    this.setState({ drafts });
+    this.setState({ drafts, totalDrafts: drafts.length });
   }
 
   getCurrentDrafts(selectPageNumber) {
@@ -61,16 +67,16 @@ class MyDraftList extends React.Component {
 
     const limit = appContainer.getConfig().recentCreatedLimit;
 
-    const totalCount = this.state.drafts.length;
+    const totalDrafts = this.state.drafts.length;
     const activePage = selectPageNumber;
-    const paginationNumbers = this.calculatePagination(limit, totalCount, activePage);
 
     const currentDrafts = this.state.drafts.slice((activePage - 1) * limit, activePage * limit);
 
     this.setState({
       currentDrafts,
       activePage,
-      paginationNumbers,
+      totalDrafts,
+      pagingLimit: limit,
     });
   }
 
@@ -112,125 +118,16 @@ class MyDraftList extends React.Component {
       drafts: [],
       currentDrafts: [],
       activePage: 1,
-      paginationNumbers: {},
+      totalDrafts: 0,
+      pagingLimit: Infinity,
     });
   }
 
-  calculatePagination(limit, totalCount, activePage) {
-    // calc totalPageNumber
-    const totalPage = Math.floor(totalCount / limit) + (totalCount % limit === 0 ? 0 : 1);
-
-    let paginationStart = activePage - 2;
-    let maxViewPageNum = activePage + 2;
-    // pagiNation Number area size = 5 , pageNuber calculate in here
-    // activePage Position calculate ex. 4 5 [6] 7 8 (Page8 over is Max), 3 4 5 [6] 7 (Page7 is Max)
-    if (paginationStart < 1) {
-      const diff = 1 - paginationStart;
-      paginationStart += diff;
-      maxViewPageNum = Math.min(totalPage, maxViewPageNum + diff);
-    }
-    if (maxViewPageNum > totalPage) {
-      const diff = maxViewPageNum - totalPage;
-      maxViewPageNum -= diff;
-      paginationStart = Math.max(1, paginationStart - diff);
-    }
-
-    return {
-      totalPage,
-      paginationStart,
-      maxViewPageNum,
-    };
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   * ex.  <<   <   1  2  3  >  >>
-   * this function set << & <
-   */
-  generateFirstPrev(activePage) {
-    const paginationItems = [];
-    if (activePage !== 1) {
-      paginationItems.push(
-        <Pagination.First key="first" onClick={() => { return this.getCurrentDrafts(1) }} />,
-      );
-      paginationItems.push(
-        <Pagination.Prev key="prev" onClick={() => { return this.getCurrentDrafts(this.state.activePage - 1) }} />,
-      );
-    }
-    else {
-      paginationItems.push(
-        <Pagination.First key="first" disabled />,
-      );
-      paginationItems.push(
-        <Pagination.Prev key="prev" disabled />,
-      );
-
-    }
-    return paginationItems;
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   *  ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
-   * this function set  numbers
-   */
-  generatePaginations(activePage, paginationStart, maxViewPageNum) {
-    const paginationItems = [];
-    for (let number = paginationStart; number <= maxViewPageNum; number++) {
-      paginationItems.push(
-        <Pagination.Item key={number} active={number === activePage} onClick={() => { return this.getCurrentDrafts(number) }}>{number}</Pagination.Item>,
-      );
-    }
-    return paginationItems;
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   * ex.  <<   <   1  2  3  >  >>
-   * this function set > & >>
-   */
-  generateNextLast(activePage, totalPage) {
-    const paginationItems = [];
-    if (totalPage !== activePage) {
-      paginationItems.push(
-        <Pagination.Next key="next" onClick={() => { return this.getCurrentDrafts(this.state.activePage + 1) }} />,
-      );
-      paginationItems.push(
-        <Pagination.Last key="last" onClick={() => { return this.getCurrentDrafts(totalPage) }} />,
-      );
-    }
-    else {
-      paginationItems.push(
-        <Pagination.Next key="next" disabled />,
-      );
-      paginationItems.push(
-        <Pagination.Last key="last" disabled />,
-      );
-
-    }
-    return paginationItems;
-
-  }
-
   render() {
     const { t } = this.props;
 
     const draftList = this.generateDraftList(this.state.currentDrafts);
-
-    const paginationItems = [];
-
-    const totalCount = this.state.drafts.length;
-
-    const activePage = this.state.activePage;
-    const totalPage = this.state.paginationNumbers.totalPage;
-    const paginationStart = this.state.paginationNumbers.paginationStart;
-    const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
-    const firstPrevItems = this.generateFirstPrev(activePage);
-    paginationItems.push(firstPrevItems);
-    const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
-    paginationItems.push(paginations);
-    const nextLastItems = this.generateNextLast(activePage, totalPage);
-    paginationItems.push(nextLastItems);
+    const totalCount = this.state.totalDrafts;
 
     return (
       <div className="page-list-container-create">
@@ -254,7 +151,12 @@ class MyDraftList extends React.Component {
             <div className="tab-pane m-t-30 accordion" id="draft-list">
               {draftList}
             </div>
-            <Pagination bsSize="small">{paginationItems}</Pagination>
+            <PaginationWrapper
+              activePage={this.state.activePage}
+              changePage={this.handlePage}
+              totalItemsCount={this.state.totalDrafts}
+              pagingLimit={this.state.pagingLimit}
+            />
           </React.Fragment>
         ) }
 

+ 174 - 0
src/client/js/components/PaginationWrapper.jsx

@@ -0,0 +1,174 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { withTranslation } from 'react-i18next';
+
+import Pagination from 'react-bootstrap/lib/Pagination';
+import { createSubscribedElement } from './UnstatedUtils';
+import AppContainer from '../services/AppContainer';
+
+class PaginationWrapper extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      totalItemsCount: 0,
+      activePage: 1,
+      paginationNumbers: {},
+      limit: Infinity,
+    };
+
+    this.calculatePagination = this.calculatePagination.bind(this);
+  }
+
+  componentWillReceiveProps(nextProps) {
+    this.setState({
+      activePage: nextProps.activePage,
+      totalItemsCount: nextProps.totalItemsCount,
+      limit: nextProps.pagingLimit,
+    }, () => {
+      const activePage = this.state.activePage;
+      const totalCount = this.state.totalItemsCount;
+      const limit = this.state.limit;
+      const paginationNumbers = this.calculatePagination(limit, totalCount, activePage);
+      this.setState({ paginationNumbers });
+    });
+  }
+
+  calculatePagination(limit, totalCount, activePage) {
+    // calc totalPageNumber
+    const totalPage = Math.floor(totalCount / limit) + (totalCount % limit === 0 ? 0 : 1);
+
+    let paginationStart = activePage - 2;
+    let maxViewPageNum = activePage + 2;
+    // pagiNation Number area size = 5 , pageNuber calculate in here
+    // activePage Position calculate ex. 4 5 [6] 7 8 (Page8 over is Max), 3 4 5 [6] 7 (Page7 is Max)
+    if (paginationStart < 1) {
+      const diff = 1 - paginationStart;
+      paginationStart += diff;
+      maxViewPageNum = Math.min(totalPage, maxViewPageNum + diff);
+    }
+    if (maxViewPageNum > totalPage) {
+      const diff = maxViewPageNum - totalPage;
+      maxViewPageNum -= diff;
+      paginationStart = Math.max(1, paginationStart - diff);
+    }
+
+    return {
+      totalPage,
+      paginationStart,
+      maxViewPageNum,
+    };
+  }
+
+  /**
+    * generate Elements of Pagination First Prev
+    * ex.  <<   <   1  2  3  >  >>
+    * this function set << & <
+    */
+  generateFirstPrev(activePage) {
+    const paginationItems = [];
+    if (activePage !== 1) {
+      paginationItems.push(
+        <Pagination.First key="first" onClick={() => { return this.props.changePage(1) }} />,
+      );
+      paginationItems.push(
+        <Pagination.Prev key="prev" onClick={() => { return this.props.changePage(activePage - 1) }} />,
+      );
+    }
+    else {
+      paginationItems.push(
+        <Pagination.First key="first" disabled />,
+      );
+      paginationItems.push(
+        <Pagination.Prev key="prev" disabled />,
+      );
+
+    }
+    return paginationItems;
+  }
+
+  /**
+   * generate Elements of Pagination First Prev
+   *  ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
+   * this function set  numbers
+   */
+  generatePaginations(activePage, paginationStart, maxViewPageNum) {
+    const paginationItems = [];
+    for (let number = paginationStart; number <= maxViewPageNum; number++) {
+      paginationItems.push(
+        <Pagination.Item key={number} active={number === activePage} onClick={() => { return this.props.changePage(number) }}>{number}</Pagination.Item>,
+      );
+    }
+    return paginationItems;
+  }
+
+  /**
+   * generate Elements of Pagination First Prev
+   * ex.  <<   <   1  2  3  >  >>
+   * this function set > & >>
+   */
+  generateNextLast(activePage, totalPage) {
+    const paginationItems = [];
+    if (totalPage !== activePage) {
+      paginationItems.push(
+        <Pagination.Next key="next" onClick={() => { return this.props.changePage(activePage + 1) }} />,
+      );
+      paginationItems.push(
+        <Pagination.Last key="last" onClick={() => { return this.props.changePage(totalPage) }} />,
+      );
+    }
+    else {
+      paginationItems.push(
+        <Pagination.Next key="next" disabled />,
+      );
+      paginationItems.push(
+        <Pagination.Last key="last" disabled />,
+      );
+
+    }
+    return paginationItems;
+
+  }
+
+  render() {
+    const paginationItems = [];
+
+    const activePage = this.state.activePage;
+    const totalPage = this.state.paginationNumbers.totalPage;
+    const paginationStart = this.state.paginationNumbers.paginationStart;
+    const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
+    const firstPrevItems = this.generateFirstPrev(activePage);
+    paginationItems.push(firstPrevItems);
+    const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
+    paginationItems.push(paginations);
+    const nextLastItems = this.generateNextLast(activePage, totalPage);
+    paginationItems.push(nextLastItems);
+
+    return (
+      <React.Fragment>
+        <div>
+          <Pagination bsSize="small">{paginationItems}</Pagination>
+        </div>
+      </React.Fragment>
+    );
+  }
+
+
+}
+
+const PaginationWrappered = (props) => {
+  return createSubscribedElement(PaginationWrapper, props, [AppContainer]);
+};
+
+PaginationWrapper.propTypes = {
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+
+  activePage: PropTypes.number.isRequired,
+  changePage: PropTypes.func.isRequired,
+  totalItemsCount: PropTypes.number.isRequired,
+  pagingLimit: PropTypes.number.isRequired,
+};
+
+export default withTranslation()(PaginationWrappered);

+ 19 - 118
src/client/js/components/RecentCreated/RecentCreated.jsx

@@ -1,12 +1,12 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
-import Pagination from 'react-bootstrap/lib/Pagination';
-
 import { createSubscribedElement } from '../UnstatedUtils';
 import AppContainer from '../../services/AppContainer';
 import PageContainer from '../../services/PageContainer';
 
+import PaginationWrapper from '../PaginationWrapper';
+
 import Page from '../PageList/Page';
 
 class RecentCreated extends React.Component {
@@ -17,9 +17,11 @@ class RecentCreated extends React.Component {
     this.state = {
       pages: [],
       activePage: 1,
-      paginationNumbers: {},
+      totalPages: 0,
+      pagingLimit: Infinity,
     };
-    this.calculatePagination = this.calculatePagination.bind(this);
+
+    this.handlePage = this.handlePage.bind(this);
   }
 
 
@@ -27,6 +29,10 @@ class RecentCreated extends React.Component {
     this.getRecentCreatedList(1);
   }
 
+  async handlePage(selectedPage) {
+    await this.getRecentCreatedList(selectedPage);
+  }
+
   getRecentCreatedList(selectPageNumber) {
     const { appContainer, pageContainer } = this.props;
     const { pageId } = pageContainer.state;
@@ -40,45 +46,18 @@ class RecentCreated extends React.Component {
       page_id: pageId, user: userId, limit, offset,
     })
       .then((res) => {
-        const totalCount = res.totalCount;
+        const totalPages = res.totalCount;
         const pages = res.pages;
         const activePage = selectPageNumber;
-        // pagiNation calculate function call
-        const paginationNumbers = this.calculatePagination(limit, totalCount, activePage);
         this.setState({
           pages,
           activePage,
-          paginationNumbers,
+          totalPages,
+          pagingLimit: limit,
         });
       });
   }
 
-  calculatePagination(limit, totalCount, activePage) {
-    // calc totalPageNumber
-    const totalPage = Math.floor(totalCount / limit) + (totalCount % limit === 0 ? 0 : 1);
-
-    let paginationStart = activePage - 2;
-    let maxViewPageNum = activePage + 2;
-    // pagiNation Number area size = 5 , pageNuber calculate in here
-    // activePage Position calculate ex. 4 5 [6] 7 8 (Page8 over is Max), 3 4 5 [6] 7 (Page7 is Max)
-    if (paginationStart < 1) {
-      const diff = 1 - paginationStart;
-      paginationStart += diff;
-      maxViewPageNum = Math.min(totalPage, maxViewPageNum + diff);
-    }
-    if (maxViewPageNum > totalPage) {
-      const diff = maxViewPageNum - totalPage;
-      maxViewPageNum -= diff;
-      paginationStart = Math.max(1, paginationStart - diff);
-    }
-
-    return {
-      totalPage,
-      paginationStart,
-      maxViewPageNum,
-    };
-  }
-
   /**
    * generate Elements of Page
    *
@@ -92,98 +71,20 @@ class RecentCreated extends React.Component {
 
   }
 
-  /**
-   * generate Elements of Pagination First Prev
-   * ex.  <<   <   1  2  3  >  >>
-   * this function set << & <
-   */
-  generateFirstPrev(activePage) {
-    const paginationItems = [];
-    if (activePage !== 1) {
-      paginationItems.push(
-        <Pagination.First key="first" onClick={() => { return this.getRecentCreatedList(1) }} />,
-      );
-      paginationItems.push(
-        <Pagination.Prev key="prev" onClick={() => { return this.getRecentCreatedList(this.state.activePage - 1) }} />,
-      );
-    }
-    else {
-      paginationItems.push(
-        <Pagination.First key="first" disabled />,
-      );
-      paginationItems.push(
-        <Pagination.Prev key="prev" disabled />,
-      );
-
-    }
-    return paginationItems;
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   *  ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
-   * this function set  numbers
-   */
-  generatePaginations(activePage, paginationStart, maxViewPageNum) {
-    const paginationItems = [];
-    for (let number = paginationStart; number <= maxViewPageNum; number++) {
-      paginationItems.push(
-        <Pagination.Item key={number} active={number === activePage} onClick={() => { return this.getRecentCreatedList(number) }}>{number}</Pagination.Item>,
-      );
-    }
-    return paginationItems;
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   * ex.  <<   <   1  2  3  >  >>
-   * this function set > & >>
-   */
-  generateNextLast(activePage, totalPage) {
-    const paginationItems = [];
-    if (totalPage !== activePage) {
-      paginationItems.push(
-        <Pagination.Next key="next" onClick={() => { return this.getRecentCreatedList(this.state.activePage + 1) }} />,
-      );
-      paginationItems.push(
-        <Pagination.Last key="last" onClick={() => { return this.getRecentCreatedList(totalPage) }} />,
-      );
-    }
-    else {
-      paginationItems.push(
-        <Pagination.Next key="next" disabled />,
-      );
-      paginationItems.push(
-        <Pagination.Last key="last" disabled />,
-      );
-
-    }
-    return paginationItems;
-
-  }
-
   render() {
     const pageList = this.generatePageList(this.state.pages);
 
-    const paginationItems = [];
-
-    const activePage = this.state.activePage;
-    const totalPage = this.state.paginationNumbers.totalPage;
-    const paginationStart = this.state.paginationNumbers.paginationStart;
-    const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
-    const firstPrevItems = this.generateFirstPrev(activePage);
-    paginationItems.push(firstPrevItems);
-    const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
-    paginationItems.push(paginations);
-    const nextLastItems = this.generateNextLast(activePage, totalPage);
-    paginationItems.push(nextLastItems);
-
     return (
       <div className="page-list-container-create">
         <ul className="page-list-ul page-list-ul-flat">
           {pageList}
         </ul>
-        <Pagination bsSize="small">{paginationItems}</Pagination>
+        <PaginationWrapper
+          activePage={this.state.activePage}
+          changePage={this.handlePage}
+          totalItemsCount={this.state.totalPages}
+          pagingLimit={this.state.pagingLimit}
+        />
       </div>
     );
   }

+ 19 - 117
src/client/js/components/TagsList.jsx

@@ -2,7 +2,8 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 import { withTranslation } from 'react-i18next';
-import Pagination from 'react-bootstrap/lib/Pagination';
+
+import PaginationWrapper from './PaginationWrapper';
 
 class TagsList extends React.Component {
 
@@ -12,59 +13,38 @@ class TagsList extends React.Component {
     this.state = {
       tagData: [],
       activePage: 1,
-      paginationNumbers: {},
+      totalTags: 0,
+      pagingLimit: 10,
     };
 
-    this.calculatePagination = this.calculatePagination.bind(this);
+    this.handlePage = this.handlePage.bind(this);
+    this.getTagList = this.getTagList.bind(this);
   }
 
   async componentWillMount() {
     await this.getTagList(1);
   }
 
+  async handlePage(selectedPage) {
+    await this.getTagList(selectedPage);
+  }
+
   async getTagList(selectPageNumber) {
-    const limit = 10;
+    const limit = this.state.pagingLimit;
     const offset = (selectPageNumber - 1) * limit;
     const res = await this.props.crowi.apiGet('/tags.list', { limit, offset });
 
-    const totalCount = res.totalCount;
+    const totalTags = res.totalCount;
     const tagData = res.data;
     const activePage = selectPageNumber;
-    const paginationNumbers = this.calculatePagination(limit, totalCount, activePage);
 
     this.setState({
       tagData,
       activePage,
-      paginationNumbers,
+      totalTags,
     });
   }
 
-  calculatePagination(limit, totalCount, activePage) {
-    // calc totalPageNumber
-    const totalPage = Math.floor(totalCount / limit) + (totalCount % limit === 0 ? 0 : 1);
-
-    let paginationStart = activePage - 2;
-    let maxViewPageNum = activePage + 2;
-    // pagination Number area size = 5 , pageNumber calculate in here
-    // activePage Position calculate ex. 4 5 [6] 7 8 (Page8 over is Max), 3 4 5 [6] 7 (Page7 is Max)
-    if (paginationStart < 1) {
-      const diff = 1 - paginationStart;
-      paginationStart += diff;
-      maxViewPageNum = Math.min(totalPage, maxViewPageNum + diff);
-    }
-    if (maxViewPageNum > totalPage) {
-      const diff = maxViewPageNum - totalPage;
-      maxViewPageNum -= diff;
-      paginationStart = Math.max(1, paginationStart - diff);
-    }
-
-    return {
-      totalPage,
-      paginationStart,
-      maxViewPageNum,
-    };
-  }
-
   /**
    * generate Elements of Tag
    *
@@ -82,93 +62,10 @@ class TagsList extends React.Component {
     });
   }
 
-  /**
-   * generate Elements of Pagination First Prev
-   * ex.  <<   <   1  2  3  >  >>
-   * this function set << & <
-   */
-  generateFirstPrev(activePage) {
-    const paginationItems = [];
-    if (activePage !== 1) {
-      paginationItems.push(
-        <Pagination.First key="first" onClick={() => { return this.getTagList(1) }} />,
-      );
-      paginationItems.push(
-        <Pagination.Prev key="prev" onClick={() => { return this.getTagList(this.state.activePage - 1) }} />,
-      );
-    }
-    else {
-      paginationItems.push(
-        <Pagination.First key="first" disabled />,
-      );
-      paginationItems.push(
-        <Pagination.Prev key="prev" disabled />,
-      );
-
-    }
-    return paginationItems;
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   *  ex. << < 4 5 6 7 8 > >>, << < 1 2 3 4 > >>
-   * this function set  numbers
-   */
-  generatePaginations(activePage, paginationStart, maxViewPageNum) {
-    const paginationItems = [];
-    for (let number = paginationStart; number <= maxViewPageNum; number++) {
-      paginationItems.push(
-        <Pagination.Item key={number} active={number === activePage} onClick={() => { return this.getTagList(number) }}>{number}</Pagination.Item>,
-      );
-    }
-    return paginationItems;
-  }
-
-  /**
-   * generate Elements of Pagination First Prev
-   * ex.  <<   <   1  2  3  >  >>
-   * this function set > & >>
-   */
-  generateNextLast(activePage, totalPage) {
-    const paginationItems = [];
-    if (totalPage !== activePage) {
-      paginationItems.push(
-        <Pagination.Next key="next" onClick={() => { return this.getTagList(this.state.activePage + 1) }} />,
-      );
-      paginationItems.push(
-        <Pagination.Last key="last" onClick={() => { return this.getTagList(totalPage) }} />,
-      );
-    }
-    else {
-      paginationItems.push(
-        <Pagination.Next key="next" disabled />,
-      );
-      paginationItems.push(
-        <Pagination.Last key="last" disabled />,
-      );
-
-    }
-    return paginationItems;
-  }
-
   render() {
     const { t } = this.props;
     const messageForNoTag = this.state.tagData.length ? null : <h3>{ t('You have no tag, You can set tags on pages') }</h3>;
 
-    const paginationItems = [];
-
-    const activePage = this.state.activePage;
-    const totalPage = this.state.paginationNumbers.totalPage;
-    const paginationStart = this.state.paginationNumbers.paginationStart;
-    const maxViewPageNum = this.state.paginationNumbers.maxViewPageNum;
-    const firstPrevItems = this.generateFirstPrev(activePage);
-    paginationItems.push(firstPrevItems);
-    const paginations = this.generatePaginations(activePage, paginationStart, maxViewPageNum);
-    paginationItems.push(paginations);
-    const nextLastItems = this.generateNextLast(activePage, totalPage);
-    paginationItems.push(nextLastItems);
-    const pagination = this.state.tagData.length ? <Pagination>{paginationItems}</Pagination> : null;
-
     return (
       <div className="text-center">
         <div className="tag-list">
@@ -178,7 +75,12 @@ class TagsList extends React.Component {
           {messageForNoTag}
         </div>
         <div className="tag-list-pagination">
-          {pagination}
+          <PaginationWrapper
+            activePage={this.state.activePage}
+            changePage={this.handlePage}
+            totalItemsCount={this.state.totalTags}
+            pagingLimit={this.state.pagingLimit}
+          />
         </div>
       </div>
     );

+ 4 - 0
src/server/models/user-group.js

@@ -108,6 +108,10 @@ class UserGroup {
     return deletedGroup;
   }
 
+  static countUserGroups() {
+    return this.estimatedDocumentCount();
+  }
+
   // グループ生成(名前が要る)
   static createGroupByName(name) {
     return this.create({ name });

+ 4 - 2
src/server/routes/apiv3/user-group.js

@@ -50,8 +50,10 @@ module.exports = (crowi) => {
   router.get('/', loginRequired(), adminRequired, async(req, res) => {
     // TODO: filter with querystring
     try {
-      const userGroups = await UserGroup.find();
-      return res.apiv3({ userGroups });
+      const page = parseInt(req.query.page) || 1;
+      const result = await UserGroup.findUserGroupsWithPagination({ page });
+      const { docs: userGroups, total: totalUserGroups, limit: pagingLimit } = result;
+      return res.apiv3({ userGroups, totalUserGroups, pagingLimit });
     }
     catch (err) {
       const msg = 'Error occurred in fetching user group list';