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

Merge pull request #4546 from weseek/feat/77551-79903-change-page-by-pagination

Feat/77551 79903 change page by pagination
Yuki Takei 4 лет назад
Родитель
Сommit
b5a17a8380

+ 6 - 6
packages/app/src/components/PaginationWrapper.jsx

@@ -63,10 +63,10 @@ const PaginationWrapper = React.memo((props) => {
     if (activePage !== 1) {
     if (activePage !== 1) {
       paginationItems.push(
       paginationItems.push(
         <PaginationItem key="painationItemFirst">
         <PaginationItem key="painationItemFirst">
-          <PaginationLink first onClick={() => { return changePage(1) }} />
+          <PaginationLink first onClick={() => { return changePage != null && changePage(1) }} />
         </PaginationItem>,
         </PaginationItem>,
         <PaginationItem key="painationItemPrevious">
         <PaginationItem key="painationItemPrevious">
-          <PaginationLink previous onClick={() => { return changePage(activePage - 1) }} />
+          <PaginationLink previous onClick={() => { return changePage != null && changePage(activePage - 1) }} />
         </PaginationItem>,
         </PaginationItem>,
       );
       );
     }
     }
@@ -93,7 +93,7 @@ const PaginationWrapper = React.memo((props) => {
     for (let number = paginationStart; number <= maxViewPageNum; number++) {
     for (let number = paginationStart; number <= maxViewPageNum; number++) {
       paginationItems.push(
       paginationItems.push(
         <PaginationItem key={`paginationItem-${number}`} active={number === activePage}>
         <PaginationItem key={`paginationItem-${number}`} active={number === activePage}>
-          <PaginationLink onClick={() => { return changePage(number) }}>
+          <PaginationLink onClick={() => { return changePage != null && changePage(number) }}>
             {number}
             {number}
           </PaginationLink>
           </PaginationLink>
         </PaginationItem>,
         </PaginationItem>,
@@ -112,10 +112,10 @@ const PaginationWrapper = React.memo((props) => {
     if (totalPage !== activePage) {
     if (totalPage !== activePage) {
       paginationItems.push(
       paginationItems.push(
         <PaginationItem key="painationItemNext">
         <PaginationItem key="painationItemNext">
-          <PaginationLink next onClick={() => { return changePage(activePage + 1) }} />
+          <PaginationLink next onClick={() => { return changePage != null && changePage(activePage + 1) }} />
         </PaginationItem>,
         </PaginationItem>,
         <PaginationItem key="painationItemLast">
         <PaginationItem key="painationItemLast">
-          <PaginationLink last onClick={() => { return changePage(totalPage) }} />
+          <PaginationLink last onClick={() => { return changePage != null && changePage(totalPage) }} />
         </PaginationItem>,
         </PaginationItem>,
       );
       );
     }
     }
@@ -159,7 +159,7 @@ const PaginationWrapper = React.memo((props) => {
 
 
 PaginationWrapper.propTypes = {
 PaginationWrapper.propTypes = {
   activePage: PropTypes.number.isRequired,
   activePage: PropTypes.number.isRequired,
-  changePage: PropTypes.func.isRequired,
+  changePage: PropTypes.func,
   totalItemsCount: PropTypes.number.isRequired,
   totalItemsCount: PropTypes.number.isRequired,
   pagingLimit: PropTypes.number,
   pagingLimit: PropTypes.number,
   align: PropTypes.string,
   align: PropTypes.string,

+ 64 - 27
packages/app/src/components/SearchPage.jsx

@@ -33,16 +33,20 @@ class SearchPage extends React.Component {
       selectedPage: {},
       selectedPage: {},
       selectedPages: new Set(),
       selectedPages: new Set(),
       searchResultCount: 0,
       searchResultCount: 0,
+      activePage: 1,
+      pagingLimit: 3, // change to an appropriate limit number
       excludeUsersHome: true,
       excludeUsersHome: true,
       excludeTrash: true,
       excludeTrash: true,
     };
     };
 
 
     this.changeURL = this.changeURL.bind(this);
     this.changeURL = this.changeURL.bind(this);
     this.search = this.search.bind(this);
     this.search = this.search.bind(this);
+    this.searchHandler = this.searchHandler.bind(this);
     this.selectPage = this.selectPage.bind(this);
     this.selectPage = this.selectPage.bind(this);
     this.toggleCheckBox = this.toggleCheckBox.bind(this);
     this.toggleCheckBox = this.toggleCheckBox.bind(this);
     this.onExcludeUsersHome = this.onExcludeUsersHome.bind(this);
     this.onExcludeUsersHome = this.onExcludeUsersHome.bind(this);
     this.onExcludeTrash = this.onExcludeTrash.bind(this);
     this.onExcludeTrash = this.onExcludeTrash.bind(this);
+    this.onPagingNumberChanged = this.onPagingNumberChanged.bind(this);
   }
   }
 
 
   componentDidMount() {
   componentDidMount() {
@@ -97,13 +101,34 @@ class SearchPage extends React.Component {
     return query;
     return query;
   }
   }
 
 
-  search(data) {
+  /**
+   * this method is called when user changes paging number
+   */
+  async onPagingNumberChanged(activePage) {
+    // this.setState does not change the state immediately and following calls of this.search outside of this.setState will have old activePage state.
+    // To prevent above, pass this.search as a callback function to make sure this.search will have the latest activePage state.
+    this.setState({ activePage }, () => this.search({ keyword: this.state.searchedKeyword }));
+  }
+
+  /**
+   * this method is called when user searches by pressing Enter or using searchbox
+   */
+  async searchHandler(data) {
+    // this.setState does not change the state immediately and following calls of this.search outside of this.setState will have old activePage state.
+    // To prevent above, pass this.search as a callback function to make sure this.search will have the latest activePage state.
+    this.setState({ activePage: 1 }, () => this.search(data));
+  }
+
+  async search(data) {
     const keyword = data.keyword;
     const keyword = data.keyword;
     if (keyword === '') {
     if (keyword === '') {
       this.setState({
       this.setState({
         searchingKeyword: '',
         searchingKeyword: '',
+        searchedKeyword: '',
         searchedPages: [],
         searchedPages: [],
         searchResultMeta: {},
         searchResultMeta: {},
+        searchResultCount: 0,
+        activePage: 1,
       });
       });
 
 
       return true;
       return true;
@@ -112,30 +137,40 @@ class SearchPage extends React.Component {
     this.setState({
     this.setState({
       searchingKeyword: keyword,
       searchingKeyword: keyword,
     });
     });
-    this.props.appContainer.apiGet('/search', { q: this.createSearchQuery(keyword) })
-      .then((res) => {
-        this.changeURL(keyword);
-        if (res.data.length > 0) {
-          this.setState({
-            searchedKeyword: keyword,
-            searchedPages: res.data,
-            searchResultMeta: res.meta,
-            searchResultCount: res.totalCount,
-            selectedPage: res.data[0],
-          });
-        }
-        else {
-          this.setState({
-            searchedKeyword: keyword,
-            searchedPages: [],
-            searchResultMeta: {},
-            selectedPage: {},
-          });
-        }
-      })
-      .catch((err) => {
-        toastError(err);
+    const pagingLimit = this.state.pagingLimit;
+    const offset = (this.state.activePage * pagingLimit) - pagingLimit;
+    try {
+      const res = await this.props.appContainer.apiGet('/search', {
+        q: this.createSearchQuery(keyword),
+        limit: pagingLimit,
+        offset,
       });
       });
+      this.changeURL(keyword);
+      if (res.data.length > 0) {
+        this.setState({
+          searchedKeyword: keyword,
+          searchedPages: res.data,
+          searchResultMeta: res.meta,
+          searchResultCount: res.meta.total,
+          selectedPage: res.data[0],
+          // reset active page if keyword changes, otherwise set the current state
+          activePage: this.state.searchedKeyword === keyword ? this.state.activePage : 1,
+        });
+      }
+      else {
+        this.setState({
+          searchedKeyword: keyword,
+          searchedPages: [],
+          searchResultMeta: {},
+          searchResultCount: 0,
+          selectedPage: {},
+          activePage: 1,
+        });
+      }
+    }
+    catch (err) {
+      toastError(err);
+    }
   }
   }
 
 
   selectPage= (pageId) => {
   selectPage= (pageId) => {
@@ -175,10 +210,12 @@ class SearchPage extends React.Component {
         selectedPage={this.state.selectedPage}
         selectedPage={this.state.selectedPage}
         selectedPages={this.state.selectedPages}
         selectedPages={this.state.selectedPages}
         searchResultCount={this.state.searchResultCount}
         searchResultCount={this.state.searchResultCount}
+        activePage={this.state.activePage}
+        pagingLimit={this.state.pagingLimit}
         onClickInvoked={this.selectPage}
         onClickInvoked={this.selectPage}
         onChangedInvoked={this.toggleCheckBox}
         onChangedInvoked={this.toggleCheckBox}
-      >
-      </SearchResultList>
+        onPagingNumberChanged={this.onPagingNumberChanged}
+      />
     );
     );
   }
   }
 
 
@@ -187,7 +224,7 @@ class SearchPage extends React.Component {
       <SearchControl
       <SearchControl
         searchingKeyword={this.state.searchingKeyword}
         searchingKeyword={this.state.searchingKeyword}
         appContainer={this.props.appContainer}
         appContainer={this.props.appContainer}
-        onSearchInvoked={this.search}
+        onSearchInvoked={this.searchHandler}
         onExcludeUsersHome={this.onExcludeUsersHome}
         onExcludeUsersHome={this.onExcludeUsersHome}
         onExcludeTrash={this.onExcludeTrash}
         onExcludeTrash={this.onExcludeTrash}
       >
       >

+ 16 - 13
packages/app/src/components/SearchPage/SearchResultList.jsx

@@ -9,9 +9,9 @@ class SearchResultList extends React.Component {
     return (
     return (
       <>
       <>
         {this.props.pages.map((page) => {
         {this.props.pages.map((page) => {
-          // TODO : send cetain length of body (revisionBody) from elastisearch by adding some settings to the query and
-          //         when keyword is not in page content, display revisionBody.
-          // TASK : https://estoc.weseek.co.jp/redmine/issues/79606
+        // TODO : send cetain length of body (revisionBody) from elastisearch by adding some settings to the query and
+        //         when keyword is not in page content, display revisionBody.
+        // TASK : https://estoc.weseek.co.jp/redmine/issues/79606
           return (
           return (
             <SearchResultListItem
             <SearchResultListItem
               page={page}
               page={page}
@@ -20,16 +20,16 @@ class SearchResultList extends React.Component {
             />
             />
           );
           );
         })}
         })}
-        <div className="my-4 mx-auto">
-          <PaginationWrapper
-            activePage={1}
-            changePage={() => { console.log('page chagned') }} // Todo: replace this with a function to change state vars
-            // a total number of pages retrieved from elasticsearch on the current search condition
-            totalItemsCount={this.props.searchResultCount}
-            // a number of pages to show in one page
-            pagingLimit={5} // Todo: replace this with a state that dynamically changes its value
-          />
-        </div>
+        {this.props.searchResultCount != null && this.props.searchResultCount > 0 && (
+          <div className="my-4 mx-auto">
+            <PaginationWrapper
+              activePage={this.props.activePage}
+              changePage={this.props.onPagingNumberChanged}
+              totalItemsCount={this.props.searchResultCount || 0}
+              pagingLimit={this.props.pagingLimit}
+            />
+          </div>
+        )}
       </>
       </>
     );
     );
   }
   }
@@ -41,8 +41,11 @@ SearchResultList.propTypes = {
   deletionMode: PropTypes.bool.isRequired,
   deletionMode: PropTypes.bool.isRequired,
   selectedPages: PropTypes.array.isRequired,
   selectedPages: PropTypes.array.isRequired,
   searchResultCount: PropTypes.number,
   searchResultCount: PropTypes.number,
+  activePage: PropTypes.number.isRequired,
+  pagingLimit: PropTypes.number,
   onClickInvoked: PropTypes.func,
   onClickInvoked: PropTypes.func,
   onChangeInvoked: PropTypes.func,
   onChangeInvoked: PropTypes.func,
+  onPagingNumberChanged: PropTypes.func,
 };
 };
 
 
 export default SearchResultList;
 export default SearchResultList;