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

Dirty hack for ericgio/react-bootstrap-typeahead/issues/492

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

+ 1 - 1
packages/app/src/components/Navbar/GlobalSearch.tsx

@@ -40,7 +40,7 @@ const GlobalSearch: FC<Props> = (props: Props) => {
 
     // navigate to page
     if (page != null) {
-      window.location.href = page._id;
+      window.location.href = `/${page._id}`;
     }
   }, []);
 

+ 14 - 1
packages/app/src/components/PageCreateModal.jsx

@@ -1,8 +1,9 @@
 
 import React, {
-  useEffect, useState, useMemo,
+  useEffect, useState, useMemo, useCallback,
 } from 'react';
 import PropTypes from 'prop-types';
+import assert from 'assert';
 
 import { Modal, ModalHeader, ModalBody } from 'reactstrap';
 import { debounce } from 'throttle-debounce';
@@ -131,6 +132,17 @@ const PageCreateModal = (props) => {
     redirectToEditor(pageNameInput);
   }
 
+  const ppacChangeHandler = useCallback((data) => {
+    assert(data.length > 0);
+
+    const page = data[0].data; // should be single page selected
+
+    // navigate to page
+    if (page != null) {
+      window.location.href = `/${page._id}`;
+    }
+  }, []);
+
   function ppacInputChangeHandler(value) {
     setPageNameInput(value);
   }
@@ -211,6 +223,7 @@ const PageCreateModal = (props) => {
                   <PagePathAutoComplete
                     initializedPath={pageNameInput}
                     addTrailingSlash
+                    onChange={ppacChangeHandler}
                     onSubmit={ppacSubmitHandler}
                     onInputChange={ppacInputChangeHandler}
                     autoFocus

+ 13 - 0
packages/app/src/components/PageDuplicateModal.tsx

@@ -1,6 +1,7 @@
 import React, {
   useState, useEffect, useCallback, useMemo,
 } from 'react';
+import assert from 'assert';
 
 import {
   Modal, ModalHeader, ModalBody, ModalFooter,
@@ -82,6 +83,17 @@ const PageDuplicateModal = (): JSX.Element => {
     }
   }, [pageNameInput, subordinatedPages, checkExistPathsDebounce, page]);
 
+  const ppacChangeHandler = useCallback((data) => {
+    assert(data.length > 0);
+
+    const page = data[0].data; // should be single page selected
+
+    // navigate to page
+    if (page != null) {
+      window.location.href = `/${page._id}`;
+    }
+  }, []);
+
   /**
    * change pageNameInput for PagePathAutoComplete
    * @param {string} value
@@ -182,6 +194,7 @@ const PageDuplicateModal = (): JSX.Element => {
                 ? (
                   <PagePathAutoComplete
                     initializedPath={path}
+                    onChange={ppacChangeHandler}
                     onSubmit={duplicate}
                     onInputChange={ppacInputChangeHandler}
                     autoFocus

+ 3 - 22
packages/app/src/components/PagePathAutoComplete.jsx

@@ -8,27 +8,9 @@ import SearchTypeahead from './SearchTypeahead';
 const PagePathAutoComplete = (props) => {
 
   const {
-    addTrailingSlash, onSubmit, onInputChange, initializedPath,
+    addTrailingSlash, initializedPath,
   } = props;
 
-  function inputChangeHandler(pages) {
-    if (onInputChange == null) {
-      return;
-    }
-    const page = pages[0]; // should be single page selected
-
-    if (page != null) {
-      onInputChange(page.path);
-    }
-  }
-
-  function submitHandler() {
-    if (onSubmit == null) {
-      return;
-    }
-    onSubmit();
-  }
-
   function getKeywordOnInit(path) {
     if (path == null) {
       return;
@@ -40,9 +22,7 @@ const PagePathAutoComplete = (props) => {
 
   return (
     <SearchTypeahead
-      onSubmit={submitHandler}
-      onChange={inputChangeHandler}
-      onInputChange={props.onInputChange}
+      {...props}
       inputProps={{ name: 'new_path' }}
       placeholder="Input page path"
       keywordOnInit={getKeywordOnInit(initializedPath)}
@@ -56,6 +36,7 @@ PagePathAutoComplete.propTypes = {
   initializedPath:  PropTypes.string,
   addTrailingSlash: PropTypes.bool,
 
+  onChange:         PropTypes.func,
   onSubmit:         PropTypes.func,
   onInputChange:    PropTypes.func,
   autoFocus:        PropTypes.bool,

+ 30 - 2
packages/app/src/components/SearchTypeahead.tsx

@@ -47,11 +47,12 @@ type TypeaheadInstance = {
   clear: () => void,
   focus: () => void,
   toggleMenu: () => void,
+  state: { selected: IPageWithMeta<IPageSearchMeta>[] }
 }
 
 const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Props, ref) => {
   const {
-    onSearchError, onSearch, onInputChange, onSubmit,
+    onSearchError, onSearch, onInputChange, onChange, onSubmit,
     inputProps, keywordOnInit, disableIncrementalSearch, helpElement,
     onBlur, onFocus,
   } = props;
@@ -116,13 +117,39 @@ const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Pro
     }
   }, [onInputChange]);
 
+  /* -------------------------------------------------------------------------------------------------------
+   *
+   * Dirty hack for https://github.com/ericgio/react-bootstrap-typeahead/issues/492 -- 2022.03.22 Yuki Takei
+   *
+   * 1. Schedule to submit with delay when Enter key downed
+   * 2. Fire onChange and cancel the schedule to submit if change event occured
+   * 3. Fire onSubmit if the schedule is not canceled
+   *
+   */
+  const DELAY_FOR_SUBMISSION = 100;
+  const timeoutIdRef = useRef<NodeJS.Timeout>();
+
+  const changeHandler = useCallback((selectedItems: IPageWithMeta<IPageSearchMeta>[]) => {
+    if (onChange != null && selectedItems.length > 0) {
+      // cancel schedule to submit
+      if (timeoutIdRef.current != null) {
+        clearTimeout(timeoutIdRef.current);
+      }
+      onChange(selectedItems);
+    }
+  }, [onChange]);
+
   const keyDownHandler = useCallback((event: KeyboardEvent) => {
     if (event.keyCode === 13) { // Enter key
       if (onSubmit != null && input != null && input.length > 0) {
-        onSubmit(input);
+        // schedule to submit with 100ms delay
+        timeoutIdRef.current = setTimeout(() => onSubmit(input), DELAY_FOR_SUBMISSION);
       }
     }
   }, [input, onSubmit]);
+  /*
+   * -------------------------------------------------------------------------------------------------------
+   */
 
   useEffect(() => {
     if (onSearchError != null && searchError != null) {
@@ -193,6 +220,7 @@ const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Pro
         open={isOpenAlways || undefined}
         renderMenu={renderMenu}
         autoFocus={props.autoFocus}
+        onChange={changeHandler}
         onSearch={searchHandler}
         onInputChange={inputChangeHandler}
         onKeyDown={keyDownHandler}