فهرست منبع

Merge pull request #4719 from weseek/feat/77545-81664-display-filter-option

Feat/77545 81664 display filter option
ryo-h 4 سال پیش
والد
کامیت
df18f988d5

+ 2 - 1
packages/app/resource/locales/en_US/translation.json

@@ -576,7 +576,8 @@
     "deletion_modal_header": "Delete page",
     "delete_completely": "Delete completely",
     "include_certain_path" : "Include {{pathToInclude}} path ",
-    "delete_all_selected_page" : "Delete All"
+    "delete_all_selected_page" : "Delete All",
+    "search_again" : "Search again"
   },
   "security_setting": {
     "Guest Users Access": "Guest users access",

+ 3 - 2
packages/app/resource/locales/ja_JP/translation.json

@@ -64,7 +64,7 @@
   "Include Attachment File": "添付ファイルも含める",
   "Include Comment": "コメントも含める",
   "Include Subordinated Page": "配下ページも含める",
-  "Include Subordinated Target Page": "{{target}} 下含む",
+  "Include Subordinated Target Page": "{{target}} 下含む",
   "All Subordinated Page": "全ての配下ページ",
   "Specify Hierarchy": "階層の深さを指定",
   "Submitted the request to create the archive": "アーカイブ作成のリクエストを正常に送信しました",
@@ -576,7 +576,8 @@
     "deletion_modal_header": "以下のページを削除",
     "delete_completely": "完全に削除する",
     "include_certain_path": "{{pathToInclude}}下を含む ",
-    "delete_all_selected_page" : "一括削除"
+    "delete_all_selected_page" : "一括削除",
+    "search_again" : "再検索"
   },
   "security_setting": {
     "Guest Users Access": "ゲストユーザーのアクセス",

+ 2 - 1
packages/app/resource/locales/zh_CN/translation.json

@@ -849,7 +849,8 @@
 		"deletion_modal_header": "删除页",
 		"delete_completely": "完全删除",
     "include_certain_path": "包含 {{pathToInclude}} 路径 ",
-    "delete_all_selected_page": "删除所有"
+    "delete_all_selected_page": "删除所有",
+    "search_again" : "再次搜索"
 	},
 	"to_cloud_settings": "進入 GROWI.cloud 的管理界面",
 	"login": {

+ 12 - 12
packages/app/src/components/SearchPage.jsx

@@ -35,8 +35,8 @@ class SearchPage extends React.Component {
       searchResultCount: 0,
       activePage: 1,
       pagingLimit: 10, // change to an appropriate limit number
-      excludeUsersHome: true,
-      excludeTrash: true,
+      excludeUserPages: true,
+      excludeTrashPages: true,
     };
 
     this.changeURL = this.changeURL.bind(this);
@@ -44,8 +44,8 @@ class SearchPage extends React.Component {
     this.searchHandler = this.searchHandler.bind(this);
     this.selectPage = this.selectPage.bind(this);
     this.toggleCheckBox = this.toggleCheckBox.bind(this);
-    this.onExcludeUsersHome = this.onExcludeUsersHome.bind(this);
-    this.onExcludeTrash = this.onExcludeTrash.bind(this);
+    this.switchExcludeUserPagesHandler = this.switchExcludeUserPagesHandler.bind(this);
+    this.switchExcludeTrashPagesHandler = this.switchExcludeTrashPagesHandler.bind(this);
     this.onPagingNumberChanged = this.onPagingNumberChanged.bind(this);
   }
 
@@ -68,12 +68,12 @@ class SearchPage extends React.Component {
     return query;
   }
 
-  onExcludeUsersHome() {
-    this.setState({ excludeUsersHome: !this.state.excludeUsersHome });
+  switchExcludeUserPagesHandler() {
+    this.setState({ excludeUserPages: !this.state.excludeUserPages });
   }
 
-  onExcludeTrash() {
-    this.setState({ excludeTrash: !this.state.excludeTrash });
+  switchExcludeTrashPagesHandler() {
+    this.setState({ excludeTrashPages: !this.state.excludeTrashPages });
   }
 
   changeURL(keyword, refreshHash) {
@@ -91,10 +91,10 @@ class SearchPage extends React.Component {
     let query = keyword;
 
     // pages included in specific path are not retrived when prefix is added
-    if (this.state.excludeTrash) {
+    if (this.state.excludeTrashPages) {
       query = `${query} -prefix:${specificPathNames.trash}`;
     }
-    if (this.state.excludeUsersHome) {
+    if (this.state.excludeUserPages) {
       query = `${query} -prefix:${specificPathNames.user}`;
     }
 
@@ -224,8 +224,8 @@ class SearchPage extends React.Component {
         searchingKeyword={this.state.searchingKeyword}
         appContainer={this.props.appContainer}
         onSearchInvoked={this.searchHandler}
-        onExcludeUsersHome={this.onExcludeUsersHome}
-        onExcludeTrash={this.onExcludeTrash}
+        onExcludeUserPagesSwitched={this.switchExcludeUserPagesHandler}
+        onExcludeTrashPagesSwitched={this.switchExcludeTrashPagesHandler}
       >
       </SearchControl>
     );

+ 45 - 12
packages/app/src/components/SearchPage/SearchControl.tsx

@@ -1,33 +1,36 @@
-import React, { FC } from 'react';
+import React, { FC, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import SearchPageForm from './SearchPageForm';
 import AppContainer from '../../client/services/AppContainer';
 import DeleteSelectedPageGroup from './DeleteSelectedPageGroup';
+import SearchOptionModal from './SearchOptionModal';
 import { CheckboxType } from '../../interfaces/search';
 
 type Props = {
   searchingKeyword: string,
   appContainer: AppContainer,
   onSearchInvoked: (data : any[]) => boolean,
-  onExcludeUsersHome?: () => void,
-  onExcludeTrash?: () => void,
+  onExcludeUserPagesSwitched?: () => void,
+  onExcludeTrashPagesSwitched?: () => void,
 }
 
 const SearchControl: FC <Props> = (props: Props) => {
+
+  const [isFileterOptionModalShown, setIsFileterOptionModalShown] = useState(false);
   // Temporaly workaround for lint error
   // later needs to be fixed: SearchControl to typescript componet
   const SearchPageFormTypeAny : any = SearchPageForm;
   const { t } = useTranslation('');
 
-  const onExcludeUsersHome = () => {
-    if (props.onExcludeUsersHome != null) {
-      props.onExcludeUsersHome();
+  const switchExcludeUserPagesHandler = () => {
+    if (props.onExcludeUserPagesSwitched != null) {
+      props.onExcludeUserPagesSwitched();
     }
   };
 
-  const onExcludeTrash = () => {
-    if (props.onExcludeTrash != null) {
-      props.onExcludeTrash();
+  const switchExcludeTrashPagesHandler = () => {
+    if (props.onExcludeTrashPagesSwitched != null) {
+      props.onExcludeTrashPagesSwitched();
     }
   };
 
@@ -46,6 +49,25 @@ const SearchControl: FC <Props> = (props: Props) => {
     // ref: https://getbootstrap.com/docs/4.5/components/forms/#checkboxes
   };
 
+  const openSearchOptionModalHandler = () => {
+    setIsFileterOptionModalShown(true);
+  };
+
+  const closeSearchOptionModalHandler = () => {
+    setIsFileterOptionModalShown(false);
+  };
+
+  const rednerSearchOptionModal = () => {
+    return (
+      <SearchOptionModal
+        isOpen={isFileterOptionModalShown || false}
+        onClose={closeSearchOptionModalHandler}
+        onExcludeUserPagesSwitched={switchExcludeUserPagesHandler}
+        onExcludeTrashPagesSwitched={switchExcludeTrashPagesHandler}
+      />
+    );
+  };
+
   return (
     <>
       <div className="search-page-nav d-flex py-3 align-items-center">
@@ -71,14 +93,24 @@ const SearchControl: FC <Props> = (props: Props) => {
             onCheckInvoked={onCheckAllPagesInvoked}
           />
         </div>
-        <div className="d-flex align-items-center mr-3">
+        {/** filter option */}
+        <div className="d-lg-none mr-4">
+          <button
+            type="button"
+            className="btn"
+            onClick={openSearchOptionModalHandler}
+          >
+            <i className="icon-equalizer"></i>
+          </button>
+        </div>
+        <div className="d-none d-lg-flex align-items-center mr-3">
           <div className="border border-gray mr-3">
             <label className="px-3 py-2 mb-0 d-flex align-items-center" htmlFor="flexCheckDefault">
               <input
                 className="mr-2"
                 type="checkbox"
                 id="flexCheckDefault"
-                onClick={() => onExcludeUsersHome()}
+                onClick={switchExcludeUserPagesHandler}
               />
               {t('Include Subordinated Target Page', { target: '/user' })}
             </label>
@@ -89,13 +121,14 @@ const SearchControl: FC <Props> = (props: Props) => {
                 className="mr-2"
                 type="checkbox"
                 id="flexCheckChecked"
-                onClick={() => onExcludeTrash()}
+                onClick={switchExcludeTrashPagesHandler}
               />
               {t('Include Subordinated Target Page', { target: '/trash' })}
             </label>
           </div>
         </div>
       </div>
+      {rednerSearchOptionModal()}
     </>
   );
 };

+ 78 - 0
packages/app/src/components/SearchPage/SearchOptionModal.tsx

@@ -0,0 +1,78 @@
+import React, { FC } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import {
+  Modal, ModalHeader, ModalBody, ModalFooter,
+} from 'reactstrap';
+
+
+type Props = {
+  isOpen: boolean,
+  onClose?: () => void,
+  onExcludeUserPagesSwitched?: () => void,
+  onExcludeTrashPagesSwitched?: () => void,
+  // todo: implement this method
+  // refs: https://redmine.weseek.co.jp/issues/81845
+  onClickFilteringSearchResultButton?: () => void,
+}
+
+// todo: implement filtering search result
+// refs: https://redmine.weseek.co.jp/issues/81845
+const SearchOptionModal: FC<Props> = (props: Props) => {
+
+  const { t } = useTranslation('');
+
+  const onClose = () => {
+    if (props.onClose != null) {
+      props.onClose();
+    }
+  };
+
+  return (
+    <Modal size="lg" isOpen={props.isOpen} toggle={onClose} autoFocus={false}>
+      <ModalHeader tag="h4" toggle={onClose} className="bg-primary text-light">
+        Search Option
+      </ModalHeader>
+      <ModalBody>
+        <div className="d-flex p-3">
+          <div className="border border-gray mr-3">
+            <label className="px-3 py-2 mb-0 d-flex align-items-center">
+              {/** todo: get checked state from parent component */}
+              {/** // refs: https://redmine.weseek.co.jp/issues/81845 */}
+              <input
+                className="mr-2"
+                type="checkbox"
+                onClick={props.onExcludeUserPagesSwitched}
+              />
+              {t('Include Subordinated Target Page', { target: '/user' })}
+            </label>
+          </div>
+          <div className="border border-gray">
+            <label className="px-3 py-2 mb-0 d-flex align-items-center">
+              {/** todo: get checked state from parent component */}
+              {/** // refs: https://redmine.weseek.co.jp/issues/81845 */}
+              <input
+                className="mr-2"
+                type="checkbox"
+                onClick={props.onExcludeTrashPagesSwitched}
+              />
+              {t('Include Subordinated Target Page', { target: '/trash' })}
+            </label>
+          </div>
+        </div>
+      </ModalBody>
+      <ModalFooter>
+        <button
+          type="button"
+          className="btn btn-secondary"
+          // todo: implement this method
+          // refs: https://redmine.weseek.co.jp/issues/81845
+          onClick={props.onClickFilteringSearchResultButton}
+        >{t('search_result.search_again')}
+        </button>
+      </ModalFooter>
+    </Modal>
+  );
+};
+
+export default SearchOptionModal;