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

Merge branch 'support/apply-nextjs-2' of https://github.com/weseek/growi into support/apply-nextjs-loginPage

Shunm634-source 3 лет назад
Родитель
Сommit
bb3bd48eb1

+ 3 - 1
packages/app/package.json

@@ -179,7 +179,8 @@
   },
   "// comments for defDependencies": {
     "@handsontable/react": "v3 requires handsontable >= 7.0.0.",
-    "handsontable": "v7.0.0 or above is no loger MIT lisence."
+    "handsontable": "v7.0.0 or above is no loger MIT lisence.",
+    "ts-node": "v10 occurs 'SyntaxError: Cannot use import statement outside a module' when using migrate-mongo"
   },
   "devDependencies": {
     "@alienfast/i18next-loader": "^1.1.4",
@@ -244,6 +245,7 @@
     "swr": "^1.3.0",
     "throttle-debounce": "^3.0.1",
     "toastr": "^2.1.2",
+    "ts-node": "^9.1.1",
     "ts-node-dev": "^2.0.0",
     "tsc-alias": "^1.2.9",
     "unstated": "^2.1.1",

+ 3 - 5
packages/app/src/components/Page/DisplaySwitcher.tsx

@@ -7,7 +7,7 @@ import { TabContent, TabPane } from 'reactstrap';
 
 import { smoothScrollIntoView } from '~/client/util/smooth-scroll';
 import {
-  useCurrentPagePath, useIsSharedUser, useIsEditable, useIsUserPage, usePageUser, useShareLinkId, useIsNotFound, useIsNotCreatable,
+  useCurrentPagePath, useIsSharedUser, useIsEditable, useIsUserPage, usePageUser, useShareLinkId, useIsNotFound,
 } from '~/stores/context';
 import { useDescendantsPageListModal } from '~/stores/modal';
 import { useSWRxCurrentPage } from '~/stores/page';
@@ -15,7 +15,7 @@ import { EditorMode, useEditorMode } from '~/stores/ui';
 
 import CountBadge from '../Common/CountBadge';
 import PageListIcon from '../Icons/PageListIcon';
-import { NotCreatablePage } from '../NotCreatablePage';
+import NotFoundPage from '../NotFoundPage';
 import { Page } from '../Page';
 // import PageEditor from '../PageEditor';
 // import PageEditorByHackmd from '../PageEditorByHackmd';
@@ -48,7 +48,6 @@ const DisplaySwitcher = (): JSX.Element => {
   const { data: isEditable } = useIsEditable();
   const { data: pageUser } = usePageUser();
   const { data: isNotFound } = useIsNotFound();
-  const { data: isNotCreatable } = useIsNotCreatable();
   const { data: currentPage } = useSWRxCurrentPage(shareLinkId ?? undefined);
 
   const { data: editorMode } = useEditorMode();
@@ -69,8 +68,7 @@ const DisplaySwitcher = (): JSX.Element => {
             <div className="flex-grow-1 flex-basis-0 mw-0">
               { isUserPage && <UserInfo pageUser={pageUser} />}
               { !isNotFound && <Page /> }
-              { isNotFound && !isNotCreatable && <NotFoundPage /> }
-              { isNotFound && isNotCreatable && <NotCreatablePage /> }
+              { isNotFound && <NotFoundPage /> }
             </div>
 
             { !isNotFound && !currentPage?.isEmpty && (

+ 5 - 4
packages/app/src/migrations/20211129125654-initialize-private-legacy-pages-named-query.js

@@ -13,10 +13,11 @@ module.exports = {
     mongoose.connect(getMongoUri(), mongoOptions);
 
     try {
-      await NamedQuery.insertMany({
-        name: SearchDelegatorName.PRIVATE_LEGACY_PAGES,
-        delegatorName: SearchDelegatorName.PRIVATE_LEGACY_PAGES,
-      });
+      await NamedQuery.updateOne(
+        { name: SearchDelegatorName.PRIVATE_LEGACY_PAGES },
+        { delegatorName: SearchDelegatorName.PRIVATE_LEGACY_PAGES },
+        { upsert: true },
+      );
     }
     catch (err) {
       logger.error('Failed to migrate named query for private legacy pages search delagator.', err);

+ 6 - 8
packages/app/src/pages/[[...path]].page.tsx

@@ -44,6 +44,8 @@ import loggerFactory from '~/utils/logger';
 import { BasicLayout } from '../components/Layout/BasicLayout';
 import GrowiContextualSubNavigation from '../components/Navbar/GrowiContextualSubNavigation';
 import DisplaySwitcher from '../components/Page/DisplaySwitcher';
+import { NotCreatablePage } from '../components/NotCreatablePage';
+import ForbiddenPage from '../components/ForbiddenPage';
 
 // import { serializeUserSecurely } from '../server/models/serializers/user-serializer';
 // import PageStatusAlert from '../client/js/components/PageStatusAlert';
@@ -65,7 +67,6 @@ import { useXss } from '../stores/xss';
 import {
   CommonProps, getNextI18NextConfig, getServerSideCommonProps, useCustomTitle,
 } from './utils/commons';
-import { registerTransformerForObjectId } from './utils/objectid-transformer';
 // import { useCurrentPageSWR } from '../stores/page';
 
 
@@ -80,9 +81,6 @@ const { removeHeadingSlash } = pathUtils;
 type IPageToShowRevisionWithMeta = IDataWithMeta<IPagePopulatedToShowRevision & PageDocument, IPageInfoForEntity>;
 type IPageToShowRevisionWithMetaSerialized = IDataWithMeta<string, string>;
 
-// register custom serializer
-registerTransformerForObjectId();
-
 superjson.registerCustom<IPageToShowRevisionWithMeta, IPageToShowRevisionWithMetaSerialized>(
   {
     isApplicable: (v): v is IPageToShowRevisionWithMeta => {
@@ -302,10 +300,10 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
                 { !props.isIdenticalPathPage && (
                   <>
                     <PageAlerts />
-                    { props.isForbidden
-                      ? <>ForbiddenPage</>
-                      : <DisplaySwitcher />
-                    }
+                    { props.isForbidden && <ForbiddenPage /> }
+                    { props.IsNotCreatable && <NotCreatablePage />}
+                    { !props.isForbidden && !props.IsNotCreatable && <DisplaySwitcher />}
+                    {/* <DisplaySwitcher /> */}
                     <div id="page-editor-navbar-bottom-container" className="d-none d-edit-block"></div>
                     {/* <PageStatusAlert /> */}
                     PageStatusAlert

+ 3 - 0
packages/app/src/pages/_app.page.tsx

@@ -18,6 +18,7 @@ import {
 } from '../stores/context';
 
 import { CommonProps } from './utils/commons';
+import { registerTransformerForObjectId } from './utils/objectid-transformer';
 // import { useInterceptorManager } from '~/stores/interceptor';
 
 const isDev = process.env.NODE_ENV === 'development';
@@ -25,6 +26,8 @@ const isDev = process.env.NODE_ENV === 'development';
 type GrowiAppProps = AppProps & {
   pageProps: CommonProps;
 };
+// register custom serializer
+registerTransformerForObjectId();
 
 function GrowiApp({ Component, pageProps }: GrowiAppProps): JSX.Element {
   useI18nextHMR(isDev);

+ 166 - 6
packages/app/src/pages/_search.page.tsx

@@ -1,26 +1,186 @@
 import {
-  NextPage, GetServerSideProps,
+  NextPage, GetServerSideProps, GetServerSidePropsContext,
 } from 'next';
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
 import dynamic from 'next/dynamic';
+import Head from 'next/head';
 
-const SearchPage: NextPage = () => {
+import { BasicLayout } from '~/components/Layout/BasicLayout';
+import { CrowiRequest } from '~/interfaces/crowi-request';
+import { RendererConfig } from '~/interfaces/services/renderer';
+import { ISidebarConfig } from '~/interfaces/sidebar-config';
+import { IUser, IUserHasId } from '~/interfaces/user';
+import { IUserUISettings } from '~/interfaces/user-ui-settings';
+import UserUISettings from '~/server/models/user-ui-settings';
+import Xss from '~/services/xss';
+import {
+  useCsrfToken, useCurrentUser, useIsSearchPage, useIsSearchScopeChildrenAsDefault,
+  useIsSearchServiceConfigured, useIsSearchServiceReachable, useRendererConfig,
+} from '~/stores/context';
+import {
+  usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser, useSidebarCollapsed,
+  useCurrentSidebarContents, useCurrentProductNavWidth,
+} from '~/stores/ui';
+import { useXss } from '~/stores/xss';
+
+import {
+  CommonProps, getNextI18NextConfig, getServerSideCommonProps, useCustomTitle,
+} from './utils/commons';
+
+type Props = CommonProps & {
+  currentUser: IUser,
+
+  isSearchServiceConfigured: boolean,
+  isSearchServiceReachable: boolean,
+  isSearchScopeChildrenAsDefault: boolean,
+
+  // UI
+  userUISettings?: IUserUISettings
+  // Sidebar
+  sidebarConfig: ISidebarConfig,
+
+  // Render config
+  rendererConfig: RendererConfig,
+
+};
+
+const SearchPage: NextPage<Props> = (props: Props) => {
+  const { userUISettings } = props;
+
+  // commons
+  useXss(new Xss());
+  useCsrfToken(props.csrfToken);
+
+  useCurrentUser(props.currentUser ?? null);
+
+  // Search
+  useIsSearchPage(true);
+  useIsSearchServiceConfigured(props.isSearchServiceConfigured);
+  useIsSearchServiceReachable(props.isSearchServiceReachable);
+  useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
+
+  // UserUISettings
+  usePreferDrawerModeByUser(userUISettings?.preferDrawerModeByUser ?? props.sidebarConfig.isSidebarDrawerMode);
+  usePreferDrawerModeOnEditByUser(userUISettings?.preferDrawerModeOnEditByUser);
+  useSidebarCollapsed(userUISettings?.isSidebarCollapsed ?? props.sidebarConfig.isSidebarClosedAtDockMode);
+  useCurrentSidebarContents(userUISettings?.currentSidebarContents);
+  useCurrentProductNavWidth(userUISettings?.currentProductNavWidth);
+
+  // render config
+  useRendererConfig(props.rendererConfig);
 
   const PutbackPageModal = (): JSX.Element => {
     const PutbackPageModal = dynamic(() => import('../components/PutbackPageModal'), { ssr: false });
     return <PutbackPageModal />;
   };
 
+  const classNames: string[] = [];
+  // if (props.isContainerFluid) {
+  //   classNames.push('growi-layout-fluid');
+  // }
+
   return (
     <>
-      SearchPage
-      <PutbackPageModal />
+      <Head>
+        {/*
+        {renderScriptTagByName('drawio-viewer')}
+        {renderScriptTagByName('highlight-addons')}
+        */}
+      </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 id="search-page">
+            Search Result Page
+            {/* render SearchPage component here */}
+          </div>
+
+        </div>
+        <PutbackPageModal />
+      </BasicLayout>
+
     </>
   );
 };
 
-export const getServerSideProps: GetServerSideProps = async() => {
+async function injectUserUISettings(context: GetServerSidePropsContext, props: Props): Promise<void> {
+  const req = context.req as CrowiRequest<IUserHasId & any>;
+  const { user } = req;
+
+  const userUISettings = user == null ? null : await UserUISettings.findOne({ user: user._id }).exec();
+  if (userUISettings != null) {
+    props.userUISettings = userUISettings.toObject();
+  }
+}
+
+function injectServerConfigurations(context: GetServerSidePropsContext, props: Props): void {
+  const req: CrowiRequest = context.req as CrowiRequest;
+  const { crowi } = req;
+  const { configManager, searchService } = crowi;
+
+  props.isSearchServiceConfigured = searchService.isConfigured;
+  props.isSearchServiceReachable = searchService.isReachable;
+  props.isSearchScopeChildrenAsDefault = configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault');
+
+  props.sidebarConfig = {
+    isSidebarDrawerMode: configManager.getConfig('crowi', 'customize:isSidebarDrawerMode'),
+    isSidebarClosedAtDockMode: configManager.getConfig('crowi', 'customize:isSidebarClosedAtDockMode'),
+  };
+
+  props.rendererConfig = {
+    isEnabledLinebreaks: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
+    isEnabledLinebreaksInComments: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),
+    adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
+    isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
+
+    plantumlUri: process.env.PLANTUML_URI ?? null,
+    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
+
+    // XSS Options
+    isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:xss:isEnabledPrevention'),
+    attrWhiteList: crowi.xssService.getAttrWhiteList(),
+    tagWhiteList: crowi.xssService.getTagWhiteList(),
+    highlightJsStyleBorder: crowi.configManager.getConfig('crowi', 'customize:highlightJsStyleBorder'),
+  };
+}
+
+/**
+ * for Server Side Translations
+ * @param context
+ * @param props
+ * @param namespacesRequired
+ */
+async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
+  const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired);
+  props._nextI18Next = nextI18NextConfig._nextI18Next;
+}
+
+export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
+  const req = context.req as CrowiRequest<IUserHasId & any>;
+  const { user } = req;
+
+  const result = await getServerSideCommonProps(context);
+
+  // check for presence
+  // see: https://github.com/vercel/next.js/issues/19271#issuecomment-730006862
+  if (!('props' in result)) {
+    throw new Error('invalid getSSP result');
+  }
+
+  const props: Props = result.props as Props;
+
+  if (user != null) {
+    props.currentUser = user.toObject();
+  }
+
+  await injectUserUISettings(context, props);
+  injectServerConfigurations(context, props);
+  await injectNextI18NextConfigurations(context, props, ['translation']);
+
   return {
-    props: { },
+    props,
   };
 };
 

+ 20 - 0
yarn.lock

@@ -19345,6 +19345,14 @@ source-map-support@0.5.19, source-map-support@^0.5.12:
     buffer-from "^1.0.0"
     source-map "^0.6.0"
 
+source-map-support@^0.5.17:
+  version "0.5.21"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+  integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
 source-map-support@^0.5.6:
   version "0.5.12"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
@@ -20872,6 +20880,18 @@ ts-node@^10.9.1:
     v8-compile-cache-lib "^3.0.1"
     yn "3.1.1"
 
+ts-node@^9.1.1:
+  version "9.1.1"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
+  integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
+  dependencies:
+    arg "^4.1.0"
+    create-require "^1.1.0"
+    diff "^4.0.1"
+    make-error "^1.1.1"
+    source-map-support "^0.5.17"
+    yn "3.1.1"
+
 tsc-alias@^1.2.9:
   version "1.2.9"
   resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.2.9.tgz#9fbf38e5eb1bd89c7f4fc26ef0712e22a6ef8939"