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

Merge pull request #6420 from weseek/feat/render-search-result-page

feat: Render search result page
Yuki Takei 3 лет назад
Родитель
Сommit
b7332decf0

+ 2 - 2
packages/app/src/components/Navbar/GrowiSubNavigation.tsx

@@ -19,7 +19,7 @@ import AuthorInfoStyles from './AuthorInfo.module.scss';
 import styles from './GrowiSubNavigation.module.scss';
 import styles from './GrowiSubNavigation.module.scss';
 
 
 
 
-type Props = {
+export type GrowiSubNavigationProps = {
   page: Partial<IPageHasId>,
   page: Partial<IPageHasId>,
 
 
   showDrawerToggler?: boolean,
   showDrawerToggler?: boolean,
@@ -37,7 +37,7 @@ type Props = {
   additionalClasses?: string[],
   additionalClasses?: string[],
 }
 }
 
 
-export const GrowiSubNavigation = (props: Props): JSX.Element => {
+export const GrowiSubNavigation = (props: GrowiSubNavigationProps): JSX.Element => {
 
 
   const TagLabels = dynamic(() => import('../Page/TagLabels'), {
   const TagLabels = dynamic(() => import('../Page/TagLabels'), {
     ssr: false,
     ssr: false,

+ 1 - 12
packages/app/src/components/PrivateLegacyPages.tsx

@@ -8,7 +8,6 @@ import {
 } from 'reactstrap';
 } from 'reactstrap';
 
 
 import { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all';
 import { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all';
-import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { V5ConversionErrCode } from '~/interfaces/errors/v5-conversion-error';
 import { V5ConversionErrCode } from '~/interfaces/errors/v5-conversion-error';
@@ -190,21 +189,12 @@ ConvertByPathModal.displayName = 'ConvertByPathModal';
  * LegacyPage
  * LegacyPage
  */
  */
 
 
-type Props = {
-  appContainer: AppContainer,
-}
-
-const PrivateLegacyPages = (props: Props): JSX.Element => {
+const PrivateLegacyPages = (): JSX.Element => {
   const { t } = useTranslation();
   const { t } = useTranslation();
   const { data: currentUser } = useCurrentUser();
   const { data: currentUser } = useCurrentUser();
 
 
   const isAdmin = currentUser?.admin;
   const isAdmin = currentUser?.admin;
 
 
-  const {
-    appContainer,
-  } = props;
-
-
   const [keyword, setKeyword] = useState<string>(initQ);
   const [keyword, setKeyword] = useState<string>(initQ);
   const [offset, setOffset] = useState<number>(0);
   const [offset, setOffset] = useState<number>(0);
   const [limit, setLimit] = useState<number>(INITIAL_PAGING_SIZE);
   const [limit, setLimit] = useState<number>(INITIAL_PAGING_SIZE);
@@ -442,7 +432,6 @@ const PrivateLegacyPages = (props: Props): JSX.Element => {
     <>
     <>
       <SearchPageBase
       <SearchPageBase
         ref={searchPageBaseRef}
         ref={searchPageBaseRef}
-        appContainer={appContainer}
         pages={data?.data}
         pages={data?.data}
         onSelectedPagesByCheckboxesChanged={selectedPagesByCheckboxesChangedHandler}
         onSelectedPagesByCheckboxesChanged={selectedPagesByCheckboxesChangedHandler}
         forceHideMenuItems={[MenuItemType.BOOKMARK, MenuItemType.RENAME, MenuItemType.DUPLICATE, MenuItemType.REVERT, MenuItemType.PATH_RECOVERY]}
         forceHideMenuItems={[MenuItemType.BOOKMARK, MenuItemType.RENAME, MenuItemType.DUPLICATE, MenuItemType.REVERT, MenuItemType.PATH_RECOVERY]}

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

@@ -2,13 +2,12 @@ import React, {
   useCallback, useEffect, useMemo, useRef, useState,
   useCallback, useEffect, useMemo, useRef, useState,
 } from 'react';
 } from 'react';
 
 
-import { parse as parseQuerystring } from 'querystring';
 
 
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
+import { useRouter } from 'next/router';
 
 
 
 
 import { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all';
 import { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all';
-import AppContainer from '~/client/services/AppContainer';
 import { IFormattedSearchResult } from '~/interfaces/search';
 import { IFormattedSearchResult } from '~/interfaces/search';
 import { useIsSearchServiceReachable } from '~/stores/context';
 import { useIsSearchServiceReachable } from '~/stores/context';
 import { ISearchConditions, ISearchConfigurations, useSWRxSearch } from '~/stores/search';
 import { ISearchConditions, ISearchConfigurations, useSWRxSearch } from '~/stores/search';
@@ -88,29 +87,13 @@ const SearchResultListHead = React.memo((props: SearchResultListHeadProps): JSX.
 SearchResultListHead.displayName = 'SearchResultListHead';
 SearchResultListHead.displayName = 'SearchResultListHead';
 
 
 
 
-/**
- * SearchPage
- */
-
-const getParsedUrlQuery = () => {
-  const search = window.location.search || '?';
-  return parseQuerystring(search.slice(1)); // remove heading '?' and parse
-};
-
-type Props = {
-  appContainer: AppContainer,
-}
-
-export const SearchPage = (props: Props): JSX.Element => {
+export const SearchPage = (): JSX.Element => {
   const { t } = useTranslation();
   const { t } = useTranslation();
-
-  const {
-    appContainer,
-  } = props;
+  const router = useRouter();
 
 
   // parse URL Query
   // parse URL Query
-  const parsedQueries = getParsedUrlQuery().q;
-  const initQ = (Array.isArray(parsedQueries) ? parsedQueries.join(' ') : parsedQueries) ?? '';
+  const queries = router.query.q;
+  const initQ = (Array.isArray(queries) ? queries.join(' ') : queries) ?? '';
 
 
   const [keyword, setKeyword] = useState<string>(initQ);
   const [keyword, setKeyword] = useState<string>(initQ);
   const [offset, setOffset] = useState<number>(0);
   const [offset, setOffset] = useState<number>(0);
@@ -272,7 +255,6 @@ export const SearchPage = (props: Props): JSX.Element => {
   return (
   return (
     <SearchPageBase
     <SearchPageBase
       ref={searchPageBaseRef}
       ref={searchPageBaseRef}
-      appContainer={appContainer}
       pages={data?.data}
       pages={data?.data}
       searchingKeyword={keyword}
       searchingKeyword={keyword}
       onSelectedPagesByCheckboxesChanged={selectedPagesByCheckboxesChangedHandler}
       onSelectedPagesByCheckboxesChanged={selectedPagesByCheckboxesChangedHandler}

+ 10 - 9
packages/app/src/components/SearchPage/SearchResultContent.tsx

@@ -3,6 +3,7 @@ import React, {
 } from 'react';
 } from 'react';
 
 
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
+import dynamic from 'next/dynamic';
 import { DropdownItem } from 'reactstrap';
 import { DropdownItem } from 'reactstrap';
 
 
 import { exportAsMarkdown } from '~/client/services/page-operation';
 import { exportAsMarkdown } from '~/client/services/page-operation';
@@ -19,13 +20,9 @@ import { useSearchResultOptions } from '~/stores/renderer';
 import { useFullTextSearchTermManager } from '~/stores/search';
 import { useFullTextSearchTermManager } from '~/stores/search';
 
 
 
 
-import AppContainer from '../../client/services/AppContainer';
-import { AdditionalMenuItemsRendererProps, ForceHideMenuItems, MenuItemType } from '../Common/Dropdown/PageItemControl';
-import { GrowiSubNavigation } from '../Navbar/GrowiSubNavigation';
-import { SubNavButtons } from '../Navbar/SubNavButtons';
-import RevisionLoader from '../Page/RevisionLoader';
-import { PageComment } from '../PageComment';
-import PageContentFooter from '../PageContentFooter';
+import { AdditionalMenuItemsRendererProps, ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
+import { GrowiSubNavigationProps } from '../Navbar/GrowiSubNavigation';
+import { SubNavButtonsProps } from '../Navbar/SubNavButtons';
 
 
 
 
 type AdditionalMenuItemsProps = AdditionalMenuItemsRendererProps & {
 type AdditionalMenuItemsProps = AdditionalMenuItemsRendererProps & {
@@ -54,7 +51,6 @@ const SCROLL_OFFSET_TOP = 175; // approximate height of (navigation + subnavigat
 const MUTATION_OBSERVER_CONFIG = { childList: true, subtree: true };
 const MUTATION_OBSERVER_CONFIG = { childList: true, subtree: true };
 
 
 type Props ={
 type Props ={
-  appContainer: AppContainer,
   pageWithMeta : IPageWithSearchMeta,
   pageWithMeta : IPageWithSearchMeta,
   highlightKeywords?: string[],
   highlightKeywords?: string[],
   showPageControlDropdown?: boolean,
   showPageControlDropdown?: boolean,
@@ -81,6 +77,12 @@ const generateObserverCallback = (doScroll: ()=>void) => {
 };
 };
 
 
 export const SearchResultContent: FC<Props> = (props: Props) => {
 export const SearchResultContent: FC<Props> = (props: Props) => {
+  const GrowiSubNavigation = dynamic<GrowiSubNavigationProps>(() => import('../Navbar/GrowiSubNavigation').then(mod => mod.GrowiSubNavigation), { ssr: false });
+  const SubNavButtons = dynamic<SubNavButtonsProps>(() => import('../Navbar/SubNavButtons').then(mod => mod.SubNavButtons), { ssr: false });
+  const RevisionLoader = dynamic(() => import('../Page/RevisionLoader'), { ssr: false });
+  const PageComment = dynamic(() => import('../PageComment').then(mod => mod.PageComment), { ssr: false });
+  const PageContentFooter = dynamic(() => import('../PageContentFooter'), { ssr: false });
+
   const scrollElementRef = useRef(null);
   const scrollElementRef = useRef(null);
 
 
   // for mutation
   // for mutation
@@ -106,7 +108,6 @@ export const SearchResultContent: FC<Props> = (props: Props) => {
   // *******************************  end  *******************************
   // *******************************  end  *******************************
 
 
   const {
   const {
-    appContainer,
     pageWithMeta,
     pageWithMeta,
     highlightKeywords,
     highlightKeywords,
     showPageControlDropdown,
     showPageControlDropdown,

+ 2 - 6
packages/app/src/components/SearchPage2/SearchPageBase.tsx

@@ -3,9 +3,9 @@ import React, {
 } from 'react';
 } from 'react';
 
 
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
+import dynamic from 'next/dynamic';
 
 
 import { ISelectableAll } from '~/client/interfaces/selectable-all';
 import { ISelectableAll } from '~/client/interfaces/selectable-all';
-import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess } from '~/client/util/apiNotification';
 import { toastSuccess } from '~/client/util/apiNotification';
 import { IFormattedSearchResult, IPageWithSearchMeta } from '~/interfaces/search';
 import { IFormattedSearchResult, IPageWithSearchMeta } from '~/interfaces/search';
 import { OnDeletedFunction } from '~/interfaces/ui';
 import { OnDeletedFunction } from '~/interfaces/ui';
@@ -14,7 +14,6 @@ import { usePageDeleteModal } from '~/stores/modal';
 import { usePageTreeTermManager } from '~/stores/page-listing';
 import { usePageTreeTermManager } from '~/stores/page-listing';
 
 
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
-import { SearchResultContent } from '../SearchPage/SearchResultContent';
 import { SearchResultList } from '../SearchPage/SearchResultList';
 import { SearchResultList } from '../SearchPage/SearchResultList';
 
 
 
 
@@ -28,8 +27,6 @@ export interface IReturnSelectedPageIds {
 
 
 
 
 type Props = {
 type Props = {
-  appContainer: AppContainer,
-
   pages?: IPageWithSearchMeta[],
   pages?: IPageWithSearchMeta[],
   searchingKeyword?: string,
   searchingKeyword?: string,
 
 
@@ -43,8 +40,8 @@ type Props = {
 }
 }
 
 
 const SearchPageBaseSubstance: ForwardRefRenderFunction<ISelectableAll & IReturnSelectedPageIds, Props> = (props:Props, ref) => {
 const SearchPageBaseSubstance: ForwardRefRenderFunction<ISelectableAll & IReturnSelectedPageIds, Props> = (props:Props, ref) => {
+  const SearchResultContent = dynamic(import('../SearchPage/SearchResultContent').then(mod => mod.SearchResultContent), { ssr: false });
   const {
   const {
-    appContainer,
     pages,
     pages,
     searchingKeyword,
     searchingKeyword,
     forceHideMenuItems,
     forceHideMenuItems,
@@ -203,7 +200,6 @@ const SearchPageBaseSubstance: ForwardRefRenderFunction<ISelectableAll & IReturn
         <div className="mw-0 flex-grow-1 flex-basis-0 d-none d-lg-block search-result-content">
         <div className="mw-0 flex-grow-1 flex-basis-0 d-none d-lg-block search-result-content">
           { selectedPageWithMeta != null && (
           { selectedPageWithMeta != null && (
             <SearchResultContent
             <SearchResultContent
-              appContainer={appContainer}
               pageWithMeta={selectedPageWithMeta}
               pageWithMeta={selectedPageWithMeta}
               highlightKeywords={highlightKeywords}
               highlightKeywords={highlightKeywords}
               showPageControlDropdown={!isGuestUser}
               showPageControlDropdown={!isGuestUser}

+ 15 - 13
packages/app/src/pages/_search.page.tsx

@@ -23,6 +23,8 @@ import {
 } from '~/stores/ui';
 } from '~/stores/ui';
 import { useXss } from '~/stores/xss';
 import { useXss } from '~/stores/xss';
 
 
+import { SearchPage } from '../components/SearchPage';
+
 import {
 import {
   CommonProps, getNextI18NextConfig, getServerSideCommonProps, useCustomTitle,
   CommonProps, getNextI18NextConfig, getServerSideCommonProps, useCustomTitle,
 } from './utils/commons';
 } from './utils/commons';
@@ -44,7 +46,7 @@ type Props = CommonProps & {
 
 
 };
 };
 
 
-const SearchPage: NextPage<Props> = (props: Props) => {
+const SearchResultPage: NextPage<Props> = (props: Props) => {
   const { userUISettings } = props;
   const { userUISettings } = props;
 
 
   // commons
   // commons
@@ -87,20 +89,20 @@ const SearchPage: NextPage<Props> = (props: Props) => {
         {renderScriptTagByName('highlight-addons')}
         {renderScriptTagByName('highlight-addons')}
         */}
         */}
       </Head>
       </Head>
-      <BasicLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')}>
-
-        <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
-        <div id="main" className="main search-page mt-0">
+      <div className="on-search">
+        <BasicLayout title={useCustomTitle(props, 'GROWI')} className={classNames.join(' ')}>
 
 
-          <div id="search-page">
-            Search Result Page
-            {/* render SearchPage component here */}
-          </div>
+          <div id="grw-fav-sticky-trigger" className="sticky-top"></div>
+          <div id="main" className="main search-page mt-0">
 
 
-        </div>
-        <PutbackPageModal />
-      </BasicLayout>
+            <div id="search-page">
+              <SearchPage />
+            </div>
 
 
+          </div>
+          <PutbackPageModal />
+        </BasicLayout>
+      </div>
     </>
     </>
   );
   );
 };
 };
@@ -184,4 +186,4 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
   };
   };
 };
 };
 
 
-export default SearchPage;
+export default SearchResultPage;

+ 1 - 1
packages/app/src/styles/_search.scss

@@ -124,7 +124,7 @@
 
 
 
 
 // style to apply when displaying search page
 // style to apply when displaying search page
-.growi.on-search {
+.on-search {
   // set sidebar height shown in search page
   // set sidebar height shown in search page
   $search-page-sidebar-height: calc(100vh - ($grw-navbar-height + $grw-navbar-border-width));
   $search-page-sidebar-height: calc(100vh - ($grw-navbar-height + $grw-navbar-border-width));
 
 

+ 1 - 1
packages/app/src/styles/style-next.scss

@@ -63,7 +63,7 @@
 // @import 'page-presentation';
 // @import 'page-presentation';
 // @import 'page-history';
 // @import 'page-history';
 // @import 'recent-changes';
 // @import 'recent-changes';
-// @import 'search';
+@import 'search';
 // @import 'shortcuts';
 // @import 'shortcuts';
 // @import 'sidebar';
 // @import 'sidebar';
 // @import 'sidebar-wiki';
 // @import 'sidebar-wiki';