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

Merge branch 'feat/77525-80785-implement-select-all' into feat/77525-81100-check-if-selected-pages-has-page

# Conflicts:
#	packages/app/src/components/SearchPage.jsx
#	packages/app/src/components/SearchPage/SearchResultListItem.tsx
SULLEY\ryo-h 4 лет назад
Родитель
Сommit
9f962e7b78

+ 23 - 1
packages/app/src/components/SearchPage.jsx

@@ -1,4 +1,4 @@
-// This is the root component for #search-page
+// This is the root component for #search-page
 
 import React from 'react';
 import PropTypes from 'prop-types';
@@ -13,6 +13,8 @@ import SearchResultContent from './SearchPage/SearchResultContent';
 import SearchResultList from './SearchPage/SearchResultList';
 import SearchControl from './SearchPage/SearchControl';
 
+import { CheckboxType } from '../interfaces/search';
+
 export const specificPathNames = {
   user: '/user',
   trash: '/trash',
@@ -37,6 +39,7 @@ class SearchPage extends React.Component {
       pagingLimit: 10, // change to an appropriate limit number
       excludeUsersHome: true,
       excludeTrash: true,
+      checkboxState: CheckboxType.NONE_CHECKED,
     };
 
     this.changeURL = this.changeURL.bind(this);
@@ -182,6 +185,22 @@ class SearchPage extends React.Component {
     });
   }
 
+  getCheckboxType = (selectedPagesCount) => {
+    switch (selectedPagesCount) {
+      case 0:
+        return CheckboxType.NONE_CHECKED;
+      case this.state.searchedPages.length:
+        return CheckboxType.ALL_CHECKED;
+      default:
+        return CheckboxType.INDETERMINATE;
+    }
+  }
+
+  updateCheckboxState = () => {
+    const currentCheckboxState = this.getCheckboxType(this.state.selectedPages.size);
+    this.setState({ checkboxState: currentCheckboxState });
+  }
+
   toggleCheckBox = (page) => {
     if (this.state.selectedPages.has(page)) {
       this.state.selectedPages.delete(page);
@@ -189,6 +208,7 @@ class SearchPage extends React.Component {
     else {
       this.state.selectedPages.add(page);
     }
+    this.updateCheckboxState();
   }
 
   toggleAllCheckBox = () => {
@@ -203,6 +223,7 @@ class SearchPage extends React.Component {
     });
     // Force a render to tell React that the State has been changed by the Set class method
     this.forceUpdate();
+    this.updateCheckboxState();
   };
 
   renderSearchResultContent = () => {
@@ -241,6 +262,7 @@ class SearchPage extends React.Component {
         onExcludeUsersHome={this.onExcludeUsersHome}
         onExcludeTrash={this.onExcludeTrash}
         onClickInvoked={this.toggleAllCheckBox}
+        checkboxState={this.state.checkboxState}
       >
       </SearchControl>
     );

+ 6 - 15
packages/app/src/components/SearchPage/DeleteSelectedPageGroup.tsx

@@ -8,7 +8,7 @@ const logger = loggerFactory('growi:searchResultList');
 type Props = {
   checkboxState: CheckboxType,
   onClickInvoked?: () => void,
-  onCheckInvoked?: (nextCheckboxState:string) => void,
+  onCheckInvoked?: () => void,
 }
 
 const DeleteSelectedPageGroup:FC<Props> = (props:Props) => {
@@ -17,30 +17,21 @@ const DeleteSelectedPageGroup:FC<Props> = (props:Props) => {
     checkboxState, onClickInvoked, onCheckInvoked,
   } = props;
 
-  const changeCheckboxStateHandler = () => {
-    let nextCheckboxState!: string;
-    switch (checkboxState) {
-      case CheckboxType.ALL_CHECKED:
-        nextCheckboxState = CheckboxType.NONE_CHECKED;
-        break;
-      case CheckboxType.INDETERMINATE || CheckboxType.NONE_CHECKED:
-        nextCheckboxState = CheckboxType.ALL_CHECKED;
-        break;
-    }
-
+  const onCheckAllPages = () => {
     if (onCheckInvoked == null) { logger.error('onCheckInvoked is null') }
-    else { onCheckInvoked(nextCheckboxState) }
+    else { onCheckInvoked() }
   };
 
-
   return (
     <>
+      {/** todo: implement the design for CheckboxType = INDETERMINATE */}
+      {/** refs: https://estoc.weseek.co.jp/redmine/issues/81246  */}
       <input
         id="check-all-pages"
         type="checkbox"
         name="check-all-pages"
         className="custom-control custom-checkbox ml-1 align-self-center"
-        onChange={changeCheckboxStateHandler}
+        onClick={onCheckAllPages}
         checked={checkboxState !== CheckboxType.NONE_CHECKED}
       />
       <button

+ 4 - 10
packages/app/src/components/SearchPage/SearchControl.tsx

@@ -1,4 +1,4 @@
-import React, { FC, useState } from 'react';
+import React, { FC } from 'react';
 import { useTranslation } from 'react-i18next';
 import SearchPageForm from './SearchPageForm';
 import AppContainer from '../../client/services/AppContainer';
@@ -11,6 +11,7 @@ const logger = loggerFactory('growi:searchResultList');
 
 type Props = {
   searchingKeyword: string,
+  checkboxState: CheckboxType,
   appContainer: AppContainer,
   onSearchInvoked: (data : any[]) => boolean,
   onExcludeUsersHome?: () => void,
@@ -20,7 +21,6 @@ type Props = {
 
 const SearchControl: FC <Props> = (props: Props) => {
 
-  const [checkboxState, setCheckboxState] = useState(CheckboxType.NONE_CHECKED);
   // Temporaly workaround for lint error
   // later needs to be fixed: SearchControl to typescript componet
   const SearchPageFormTypeAny : any = SearchPageForm;
@@ -44,12 +44,6 @@ const SearchControl: FC <Props> = (props: Props) => {
     // https://estoc.weseek.co.jp/redmine/issues/77525
   };
 
-  const onCheckAllPagesInvoked = (nextCheckboxState:CheckboxType) => {
-    setCheckboxState(nextCheckboxState);
-    if (props.onClickInvoked == null) { logger.error('onClickInvoked is null') }
-    else { props.onClickInvoked() }
-  };
-
   return (
     <div className="">
       <div className="search-page-input sps sps--abv">
@@ -63,9 +57,9 @@ const SearchControl: FC <Props> = (props: Props) => {
       <div className="d-flex my-4">
         {/* Todo: design will be fixed in #80324. Function will be implemented in #77525 */}
         <DeleteSelectedPageGroup
-          checkboxState={checkboxState} // Todo: change the left value to appropriate value
+          checkboxState={props.checkboxState}
           onClickInvoked={onDeleteSelectedPageHandler}
-          onCheckInvoked={onCheckAllPagesInvoked}
+          onCheckInvoked={props.onClickInvoked}
         />
         <div className="d-flex align-items-center border rounded border-gray px-2 py-1 mr-2 ml-auto">
           <label className="my-0 mr-2" htmlFor="flexCheckDefault">

+ 0 - 57
packages/app/src/components/SearchPage/SearchResultList.jsx

@@ -1,57 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import SearchResultListItem from './SearchResultListItem';
-import PaginationWrapper from '../PaginationWrapper';
-
-class SearchResultList extends React.Component {
-
-  render() {
-    const { focusedPage } = this.props;
-    const focusedPageId = focusedPage != null && focusedPage.id != null ? focusedPage.id : '';
-    return (
-      <>
-        {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
-          return (
-            <SearchResultListItem
-              key={page._id}
-              page={page}
-              onClickInvoked={this.props.onClickInvoked}
-              onChangedInvoked={this.props.onChangedInvoked}
-              isSelected={page._id === focusedPageId || false}
-              noLink
-            />
-          );
-        })}
-        {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>
-        )}
-      </>
-    );
-  }
-
-}
-
-SearchResultList.propTypes = {
-  pages: PropTypes.array.isRequired,
-  deletionMode: PropTypes.bool.isRequired,
-  focusedPage: PropTypes.object,
-  selectedPages: PropTypes.array.isRequired,
-  searchResultCount: PropTypes.number,
-  activePage: PropTypes.number.isRequired,
-  pagingLimit: PropTypes.number,
-  onClickInvoked: PropTypes.func,
-  onChangedInvoked: PropTypes.func,
-  onPagingNumberChanged: PropTypes.func,
-};
-
-export default SearchResultList;

+ 1 - 1
packages/app/src/components/SearchPage/SearchResultList.tsx

@@ -37,7 +37,7 @@ const SearchResultList: FC<Props> = (props:Props) => {
             key={page._id}
             page={page}
             onClickInvoked={props.onClickInvoked}
-            onChangedInvoked={props.onChangedInvoked}
+            onClickCheckboxInvoked={props.onChangedInvoked}
             isSelected={page._id === focusedPageId || false}
             isChecked={isChecked}
           />

+ 5 - 5
packages/app/src/components/SearchPage/SearchResultListItem.tsx

@@ -1,4 +1,4 @@
-import React, { FC } from 'react';
+import React, { FC } from 'react';
 
 import Clamp from 'react-multiline-clamp';
 
@@ -70,7 +70,7 @@ type Props = {
   page: ISearchedPage,
   isSelected: boolean,
   isChecked: boolean,
-  onChangedInvoked?: (page: ISearchedPage) => void,
+  onClickCheckboxInvoked?: (page: ISearchedPage) => void,
   onClickInvoked?: (pageId: string) => void,
 }
 
@@ -78,7 +78,7 @@ const SearchResultListItem: FC<Props> = (props:Props) => {
 
   const {
     // todo: refactoring variable name to clear what changed
-    page, isSelected, onClickInvoked, onChangedInvoked, isChecked,
+    page, isSelected, onClickInvoked, onClickCheckboxInvoked, isChecked,
   } = props;
 
   // Add prefix 'id_' in pageId, because scrollspy of bootstrap doesn't work when the first letter of id attr of target component is numeral.
@@ -111,8 +111,8 @@ const SearchResultListItem: FC<Props> = (props:Props) => {
               id="flexCheckDefault"
               onClick={() => {
                 try {
-                  if (onChangedInvoked == null) { throw new Error('onChangedInvoked is null') }
-                  onChangedInvoked(page);
+                  if (onClickCheckboxInvoked == null) { throw new Error('onClickCheckboxInvoked is null') }
+                  onClickCheckboxInvoked(page);
                 }
                 catch (error) {
                   logger.error(error);