Yuki Takei 4 лет назад
Родитель
Сommit
7ad8c8fb1b

+ 17 - 16
packages/app/src/components/SearchPage/SearchControl.tsx

@@ -1,4 +1,6 @@
-import React, { FC, useCallback, useState } from 'react';
+import React, {
+  FC, useCallback, useEffect, useState,
+} from 'react';
 import { useTranslation } from 'react-i18next';
 
 import { CheckboxType, SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
@@ -15,10 +17,10 @@ type Props = {
   initialSearchConditions?: Partial<ISearchConditions>,
   onClickDeleteAllButton?: () => void
   onClickSelectAllCheckbox?: (nextSelectAllCheckboxType: CheckboxType) => void,
-  onSearchInvoked?: (keyword: string, configurations: Partial<ISearchConfigurations>) => void,
+  onSearchInvoked: (keyword: string, configurations: Partial<ISearchConfigurations>) => void,
 }
 
-const SearchControl: FC <Props> = (props: Props) => {
+const SearchControl: FC <Props> = React.memo((props: Props) => {
 
   const {
     disableSelectAllbutton,
@@ -29,8 +31,8 @@ const SearchControl: FC <Props> = (props: Props) => {
   const [keyword, setKeyword] = useState(initialSearchConditions?.keyword ?? '');
   const [sort, setSort] = useState<SORT_AXIS>(initialSearchConditions?.sort ?? SORT_AXIS.RELATION_SCORE);
   const [order, setOrder] = useState<SORT_ORDER>(initialSearchConditions?.order ?? SORT_ORDER.DESC);
-  const [includeUserPages, setIncludeUserPages] = useState(true);
-  const [includeTrashPages, setIncludeTrashPages] = useState(true);
+  const [includeUserPages, setIncludeUserPages] = useState(initialSearchConditions?.includeUserPages ?? false);
+  const [includeTrashPages, setIncludeTrashPages] = useState(initialSearchConditions?.includeTrashPages ?? false);
   const [isFileterOptionModalShown, setIsFileterOptionModalShown] = useState(false);
 
   const { t } = useTranslation('');
@@ -43,25 +45,22 @@ const SearchControl: FC <Props> = (props: Props) => {
     onSearchInvoked(keyword, {
       sort, order, includeUserPages, includeTrashPages,
     });
-  }, [includeTrashPages, includeUserPages, keyword, onSearchInvoked, order, sort]);
+  }, [keyword, sort, order, includeTrashPages, includeUserPages, onSearchInvoked]);
 
-  const searchFormChangedHandler = useCallback((keyword: string) => {
-    setKeyword(keyword);
-
-    // invoke search
-    invokeSearch();
-  }, [invokeSearch]);
+  const searchFormChangedHandler = useCallback(({ keyword }) => {
+    setKeyword(keyword as string);
+  }, []);
 
   const changeSortHandler = useCallback((nextSort: SORT_AXIS, nextOrder: SORT_ORDER) => {
     setSort(nextSort);
     setOrder(nextOrder);
+  }, []);
 
-    // invoke search
+  const clickSearchBySearchOptionModalHandler = useCallback(() => {
     invokeSearch();
   }, [invokeSearch]);
 
-  const clickSearchBySearchOptionModalHandler = useCallback(() => {
-    // invoke search
+  useEffect(() => {
     invokeSearch();
   }, [invokeSearch]);
 
@@ -121,6 +120,7 @@ const SearchControl: FC <Props> = (props: Props) => {
                   className="mr-2"
                   type="checkbox"
                   id="flexCheckDefault"
+                  defaultChecked={includeUserPages}
                   onChange={e => setIncludeUserPages(e.target.checked)}
                 />
                 {t('Include Subordinated Target Page', { target: '/user' })}
@@ -134,6 +134,7 @@ const SearchControl: FC <Props> = (props: Props) => {
                   className="mr-2"
                   type="checkbox"
                   id="flexCheckChecked"
+                  defaultChecked={includeTrashPages}
                   onChange={e => setIncludeTrashPages(e.target.checked)}
                 />
                 {t('Include Subordinated Target Page', { target: '/trash' })}
@@ -155,7 +156,7 @@ const SearchControl: FC <Props> = (props: Props) => {
 
     </div>
   );
-};
+});
 
 
 export default SearchControl;

+ 59 - 38
packages/app/src/components/SearchPage2.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 
 import AppContainer from '~/client/services/AppContainer';
@@ -15,6 +15,10 @@ import SearchPageBase from './SearchPage2/SearchPageBase';
 const INITIAL_PAGIONG_SIZE = 20;
 
 
+/**
+ * SearchResultListHead
+ */
+
 type SearchResultListHeadProps = {
   searchResult: IFormattedSearchResult,
   searchingKeyword: string,
@@ -62,11 +66,15 @@ const SearchResultListHead = (props: SearchResultListHeadProps): JSX.Element =>
   );
 };
 
+
+/**
+ * SearchPage
+ */
+
 type Props = {
   appContainer: AppContainer,
 }
 
-
 export const SearchPage = (props: Props): JSX.Element => {
 
   const {
@@ -74,23 +82,37 @@ export const SearchPage = (props: Props): JSX.Element => {
   } = props;
 
   const [keyword, setKeyword] = useState<string>('sand');
-  const [searchConfigurations, setSearchConfigurations] = useState<ISearchConfigurations>({
+  const [configurationsByControl, setConfigurationsByControl] = useState<Partial<ISearchConfigurations>>({
+  });
+  const [configurationsByPagination, setConfigurationsByPagination] = useState<Partial<ISearchConfigurations>>({
     limit: INITIAL_PAGIONG_SIZE,
   });
   const [selectedPagesCount, setSelectedPagesCount] = useState(0);
 
-  const { data, conditions } = useSWRxFullTextSearch(keyword, searchConfigurations);
+  const { data, conditions } = useSWRxFullTextSearch(keyword, {
+    limit: INITIAL_PAGIONG_SIZE,
+    ...configurationsByControl,
+    ...configurationsByPagination,
+  });
 
   const searchInvokedHandler = useCallback((_keyword: string, newConfigurations: Partial<ISearchConfigurations>) => {
     setKeyword(_keyword);
-    setSearchConfigurations({
-      ...searchConfigurations,
-      ...newConfigurations,
-    });
-  }, [searchConfigurations]);
+    setConfigurationsByControl(newConfigurations);
+  }, []);
 
   const pagingNumberChangedHandler = useCallback((activePage: number) => {
-    // TODO implement
+    const currentLimit = configurationsByPagination.limit ?? INITIAL_PAGIONG_SIZE;
+    setConfigurationsByPagination({
+      ...configurationsByPagination,
+      offset: (activePage - 1) * currentLimit,
+    });
+  }, [configurationsByPagination]);
+
+  const initialSearchConditions: Partial<ISearchConditions> = useMemo(() => {
+    return {
+      keyword: 'sand', // TODO get keyword from GET params
+      limit: INITIAL_PAGIONG_SIZE,
+    };
   }, []);
 
   return (
@@ -99,52 +121,51 @@ export const SearchPage = (props: Props): JSX.Element => {
       pages={data?.data}
       onSelectedPagesByCheckboxesChanged={setSelectedPagesCount}
       // Components
-      SearchControl={() => {
-        let disableSelectAllbutton = true;
-        let selectAllCheckboxType = CheckboxType.NONE_CHECKED;
-
-        // determine checkbox state
-        if (data != null && data.data.length > 0) {
-          disableSelectAllbutton = false;
-
-          if (selectedPagesCount > 0) {
-            selectAllCheckboxType = data.data.length === selectedPagesCount
-              ? CheckboxType.ALL_CHECKED
-              : CheckboxType.INDETERMINATE;
-          }
-        }
+      SearchControl={useCallback(() => {
+        // let disableSelectAllbutton = true;
+        // let selectAllCheckboxType = CheckboxType.NONE_CHECKED;
+
+        // // determine checkbox state
+        // if (data != null && data.data.length > 0) {
+        //   disableSelectAllbutton = false;
 
-        const initialSearchConditions: Partial<ISearchConditions> = data === null
-          ? { keyword: 'sand' } // TODO get keyword from GET params
-          : { ...conditions };
+        //   if (selectedPagesCount > 0) {
+        //     selectAllCheckboxType = data.data.length === selectedPagesCount
+        //       ? CheckboxType.ALL_CHECKED
+        //       : CheckboxType.INDETERMINATE;
+        //   }
+        // }
 
         return (
           <SearchControl
-            selectAllCheckboxType={selectAllCheckboxType}
-            disableSelectAllbutton={disableSelectAllbutton}
+            // selectAllCheckboxType={selectAllCheckboxType}
+            selectAllCheckboxType={CheckboxType.NONE_CHECKED}
+            // disableSelectAllbutton={disableSelectAllbutton}
             initialSearchConditions={initialSearchConditions}
             onClickDeleteAllButton={() => null /* TODO implement */}
             onClickSelectAllCheckbox={() => null /* TODO implement */}
             onSearchInvoked={searchInvokedHandler}
           />
         );
-      }}
-      SearchResultListHead={() => {
+      }, [initialSearchConditions, searchInvokedHandler])}
+      SearchResultListHead={useCallback(() => {
         if (data == null) {
           return <></>;
         }
 
+        const { keyword, offset, limit } = conditions;
+
         return (
           <SearchResultListHead
             searchResult={data}
-            searchingKeyword={conditions.keyword}
-            offset={conditions.offset}
-            pagingSize={conditions.limit}
+            searchingKeyword={keyword}
+            offset={offset}
+            pagingSize={limit}
             onPagingSizeChanged={() => {}}
           />
         );
-      }}
-      SearchPager={() => {
+      }, [conditions, data])}
+      SearchPager={useCallback(() => {
         // when pager is not needed
         if (data == null || data.meta.hitsCount === data.meta.total) {
           return <></>;
@@ -157,11 +178,11 @@ export const SearchPage = (props: Props): JSX.Element => {
           <PaginationWrapper
             activePage={Math.floor(offset / limit) + 1}
             totalItemsCount={total}
-            pagingLimit={searchConfigurations?.limit}
+            pagingLimit={configurationsByPagination?.limit}
             changePage={pagingNumberChangedHandler}
           />
         );
-      }}
+      }, [conditions, configurationsByPagination?.limit, data, pagingNumberChangedHandler])}
     />
   );
 };

+ 30 - 27
packages/app/src/components/SearchPage2/SearchPageBase.tsx

@@ -1,4 +1,6 @@
-import React, { FC, useEffect, useState } from 'react';
+import React, {
+  FC, useEffect, useState,
+} from 'react';
 import AppContainer from '~/client/services/AppContainer';
 import { IPageWithMeta } from '~/interfaces/page';
 import { IPageSearchMeta } from '~/interfaces/search';
@@ -58,24 +60,24 @@ const SearchPageBase: FC<Props> = (props: Props) => {
 
   const isLoading = pages == null;
 
-
   return (
     <div className="content-main">
       <div className="search-result d-flex" id="search-result">
 
-        { isLoading && (
-          <div className="mw-0 flex-grow-1 flex-basis-0 m-5 text-muted text-center">
-            <i className="fa fa-2x fa-spinner fa-pulse mr-1"></i>
-          </div>
-        ) }
+        <div className="mw-0 flex-grow-1 flex-basis-0 border boder-gray search-result-list" id="search-result-list">
 
-        { !isLoading && (
-          <>
-            <div className="mw-0 flex-grow-1 flex-basis-0 border boder-gray search-result-list" id="search-result-list">
+          <SearchControl></SearchControl>
 
-              <SearchControl></SearchControl>
+          <div className="search-result-list-scroll">
+
+            { isLoading && (
+              <div className="mw-0 flex-grow-1 flex-basis-0 m-5 text-muted text-center">
+                <i className="fa fa-2x fa-spinner fa-pulse mr-1"></i>
+              </div>
+            ) }
 
-              <div className="search-result-list-scroll">
+            { !isLoading && (
+              <>
                 <div className="my-3 px-md-4">
                   <SearchResultListHead />
                 </div>
@@ -90,22 +92,23 @@ const SearchPageBase: FC<Props> = (props: Props) => {
                 <div className="my-4 d-flex justify-content-center">
                   <SearchPager />
                 </div>
-              </div>
+              </>
+            ) }
+
+          </div>
 
-            </div>
-
-            <div className="mw-0 flex-grow-1 flex-basis-0 d-none d-lg-block search-result-content">
-              { selectedPageWithMeta != null && (
-                <SearchResultContent
-                  appContainer={appContainer}
-                  pageWithMeta={selectedPageWithMeta}
-                  highlightKeywords={highlightKeywords}
-                  showPageControlDropdown={isGuestUser}
-                />
-              )}
-            </div>
-          </>
-        ) }
+        </div>
+
+        <div className="mw-0 flex-grow-1 flex-basis-0 d-none d-lg-block search-result-content">
+          { selectedPageWithMeta != null && (
+            <SearchResultContent
+              appContainer={appContainer}
+              pageWithMeta={selectedPageWithMeta}
+              highlightKeywords={highlightKeywords}
+              showPageControlDropdown={isGuestUser}
+            />
+          )}
+        </div>
 
       </div>
     </div>