|
@@ -1,25 +1,23 @@
|
|
|
-import type { ReactNode, JSX } from 'react';
|
|
|
|
|
-import React, { useEffect } from 'react';
|
|
|
|
|
-
|
|
|
|
|
-import EventEmitter from 'events';
|
|
|
|
|
-
|
|
|
|
|
-import { isClient } from '@growi/core/dist/utils';
|
|
|
|
|
-import type {
|
|
|
|
|
- GetServerSideProps, GetServerSidePropsContext,
|
|
|
|
|
-} from 'next';
|
|
|
|
|
|
|
+import type React from 'react';
|
|
|
|
|
+import type { JSX, ReactNode } from 'react';
|
|
|
|
|
+import { useEffect } from 'react';
|
|
|
|
|
+import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
|
|
|
import dynamic from 'next/dynamic';
|
|
import dynamic from 'next/dynamic';
|
|
|
import Head from 'next/head';
|
|
import Head from 'next/head';
|
|
|
|
|
+import { isClient } from '@growi/core/dist/utils';
|
|
|
|
|
+import EventEmitter from 'events';
|
|
|
|
|
|
|
|
import { BasicLayout } from '~/components/Layout/BasicLayout';
|
|
import { BasicLayout } from '~/components/Layout/BasicLayout';
|
|
|
import { PageView } from '~/components/PageView/PageView';
|
|
import { PageView } from '~/components/PageView/PageView';
|
|
|
import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
|
|
import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
|
|
|
import { useEditorModeClassName } from '~/services/layout/use-editor-mode-class-name';
|
|
import { useEditorModeClassName } from '~/services/layout/use-editor-mode-class-name';
|
|
|
-import {
|
|
|
|
|
- useCurrentPageData, useCurrentPagePath,
|
|
|
|
|
-} from '~/states/page';
|
|
|
|
|
|
|
+import { useCurrentPageData, useCurrentPagePath } from '~/states/page';
|
|
|
import { useHydratePageAtoms } from '~/states/page/hydrate';
|
|
import { useHydratePageAtoms } from '~/states/page/hydrate';
|
|
|
import { useRendererConfig } from '~/states/server-configurations';
|
|
import { useRendererConfig } from '~/states/server-configurations';
|
|
|
-import { useSetupGlobalSocket, useSetupGlobalSocketForPage } from '~/states/socket-io';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ useSetupGlobalSocket,
|
|
|
|
|
+ useSetupGlobalSocketForPage,
|
|
|
|
|
+} from '~/states/socket-io';
|
|
|
import { useSetEditingMarkdown } from '~/states/ui/editor';
|
|
import { useSetEditingMarkdown } from '~/states/ui/editor';
|
|
|
|
|
|
|
|
import type { NextPageWithLayout } from '../_app.page';
|
|
import type { NextPageWithLayout } from '../_app.page';
|
|
@@ -28,12 +26,17 @@ import { getServerSideCommonEachProps } from '../common-props';
|
|
|
import { useInitialCSRFetch } from '../general-page';
|
|
import { useInitialCSRFetch } from '../general-page';
|
|
|
import { useHydrateGeneralPageConfigurationAtoms } from '../general-page/hydrate';
|
|
import { useHydrateGeneralPageConfigurationAtoms } from '../general-page/hydrate';
|
|
|
import { registerPageToShowRevisionWithMeta } from '../general-page/superjson';
|
|
import { registerPageToShowRevisionWithMeta } from '../general-page/superjson';
|
|
|
-import { NextjsRoutingType, detectNextjsRoutingType } from '../utils/nextjs-routing-utils';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ detectNextjsRoutingType,
|
|
|
|
|
+ NextjsRoutingType,
|
|
|
|
|
+} from '../utils/nextjs-routing-utils';
|
|
|
import { useCustomTitleForPage } from '../utils/page-title-customization';
|
|
import { useCustomTitleForPage } from '../utils/page-title-customization';
|
|
|
import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
|
|
import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
|
|
|
-
|
|
|
|
|
import { NEXT_JS_ROUTING_PAGE } from './consts';
|
|
import { NEXT_JS_ROUTING_PAGE } from './consts';
|
|
|
-import { getServerSidePropsForInitial, getServerSidePropsForSameRoute } from './server-side-props';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ getServerSidePropsForInitial,
|
|
|
|
|
+ getServerSidePropsForSameRoute,
|
|
|
|
|
+} from './server-side-props';
|
|
|
import type { EachProps, InitialProps } from './types';
|
|
import type { EachProps, InitialProps } from './types';
|
|
|
import { useSameRouteNavigation } from './use-same-route-navigation';
|
|
import { useSameRouteNavigation } from './use-same-route-navigation';
|
|
|
import { useShallowRouting } from './use-shallow-routing';
|
|
import { useShallowRouting } from './use-shallow-routing';
|
|
@@ -46,39 +49,105 @@ declare global {
|
|
|
var globalEmitter: EventEmitter;
|
|
var globalEmitter: EventEmitter;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const GrowiContextualSubNavigation = dynamic(() => import('~/client/components/Navbar/GrowiContextualSubNavigation'), { ssr: false });
|
|
|
|
|
|
|
+const GrowiContextualSubNavigation = dynamic(
|
|
|
|
|
+ () => import('~/client/components/Navbar/GrowiContextualSubNavigation'),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
|
|
|
const GrowiPluginsActivator = dynamic(
|
|
const GrowiPluginsActivator = dynamic(
|
|
|
- () => import('~/features/growi-plugin/client/components/GrowiPluginsActivator').then(mod => mod.GrowiPluginsActivator),
|
|
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import(
|
|
|
|
|
+ '~/features/growi-plugin/client/components/GrowiPluginsActivator'
|
|
|
|
|
+ ).then((mod) => mod.GrowiPluginsActivator),
|
|
|
{ ssr: false },
|
|
{ ssr: false },
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
-const DisplaySwitcher = dynamic(() => import('~/client/components/Page/DisplaySwitcher').then(mod => mod.DisplaySwitcher), { ssr: false });
|
|
|
|
|
-const PageStatusAlert = dynamic(() => import('~/client/components/PageStatusAlert').then(mod => mod.PageStatusAlert), { ssr: false });
|
|
|
|
|
|
|
+const DisplaySwitcher = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/Page/DisplaySwitcher').then(
|
|
|
|
|
+ (mod) => mod.DisplaySwitcher,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const PageStatusAlert = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/PageStatusAlert').then(
|
|
|
|
|
+ (mod) => mod.PageStatusAlert,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
|
|
|
-const UnsavedAlertDialog = dynamic(() => import('~/client/components/UnsavedAlertDialog'), { ssr: false });
|
|
|
|
|
|
|
+const UnsavedAlertDialog = dynamic(
|
|
|
|
|
+ () => import('~/client/components/UnsavedAlertDialog'),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
const DescendantsPageListModal = dynamic(
|
|
const DescendantsPageListModal = dynamic(
|
|
|
- () => import('~/client/components/DescendantsPageListModal').then(mod => mod.DescendantsPageListModal),
|
|
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/DescendantsPageListModal').then(
|
|
|
|
|
+ (mod) => mod.DescendantsPageListModal,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const DrawioModal = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/PageEditor/DrawioModal').then(
|
|
|
|
|
+ (mod) => mod.DrawioModal,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const HandsontableModal = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/PageEditor/HandsontableModal').then(
|
|
|
|
|
+ (mod) => mod.HandsontableModal,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const TemplateModal = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/TemplateModal').then(
|
|
|
|
|
+ (mod) => mod.TemplateModal,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const LinkEditModal = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/PageEditor/LinkEditModal').then(
|
|
|
|
|
+ (mod) => mod.LinkEditModal,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const TagEditModal = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/PageTags/TagEditModal').then(
|
|
|
|
|
+ (mod) => mod.TagEditModal,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
+const ConflictDiffModal = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/PageEditor/ConflictDiffModal').then(
|
|
|
|
|
+ (mod) => mod.ConflictDiffModal,
|
|
|
|
|
+ ),
|
|
|
{ ssr: false },
|
|
{ ssr: false },
|
|
|
);
|
|
);
|
|
|
-const DrawioModal = dynamic(() => import('~/client/components/PageEditor/DrawioModal').then(mod => mod.DrawioModal), { ssr: false });
|
|
|
|
|
-const HandsontableModal = dynamic(() => import('~/client/components/PageEditor/HandsontableModal').then(mod => mod.HandsontableModal), { ssr: false });
|
|
|
|
|
-const TemplateModal = dynamic(() => import('~/client/components/TemplateModal').then(mod => mod.TemplateModal), { ssr: false });
|
|
|
|
|
-const LinkEditModal = dynamic(() => import('~/client/components/PageEditor/LinkEditModal').then(mod => mod.LinkEditModal), { ssr: false });
|
|
|
|
|
-const TagEditModal = dynamic(() => import('~/client/components/PageTags/TagEditModal').then(mod => mod.TagEditModal), { ssr: false });
|
|
|
|
|
-const ConflictDiffModal = dynamic(() => import('~/client/components/PageEditor/ConflictDiffModal').then(mod => mod.ConflictDiffModal), { ssr: false });
|
|
|
|
|
|
|
|
|
|
-const EditablePageEffects = dynamic(() => import('~/client/components/Page/EditablePageEffects').then(mod => mod.EditablePageEffects), { ssr: false });
|
|
|
|
|
|
|
+const EditablePageEffects = dynamic(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ import('~/client/components/Page/EditablePageEffects').then(
|
|
|
|
|
+ (mod) => mod.EditablePageEffects,
|
|
|
|
|
+ ),
|
|
|
|
|
+ { ssr: false },
|
|
|
|
|
+);
|
|
|
|
|
|
|
|
type Props = EachProps | InitialProps;
|
|
type Props = EachProps | InitialProps;
|
|
|
|
|
|
|
|
const isInitialProps = (props: Props): props is InitialProps => {
|
|
const isInitialProps = (props: Props): props is InitialProps => {
|
|
|
- return 'isNextjsRoutingTypeInitial' in props && props.isNextjsRoutingTypeInitial;
|
|
|
|
|
|
|
+ return (
|
|
|
|
|
+ 'isNextjsRoutingTypeInitial' in props && props.isNextjsRoutingTypeInitial
|
|
|
|
|
+ );
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-
|
|
|
|
|
const Page: NextPageWithLayout<Props> = (props: Props) => {
|
|
const Page: NextPageWithLayout<Props> = (props: Props) => {
|
|
|
-
|
|
|
|
|
// register global EventEmitter
|
|
// register global EventEmitter
|
|
|
if (isClient() && window.globalEmitter == null) {
|
|
if (isClient() && window.globalEmitter == null) {
|
|
|
window.globalEmitter = new EventEmitter();
|
|
window.globalEmitter = new EventEmitter();
|
|
@@ -129,7 +198,6 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
|
|
|
<title>{title}</title>
|
|
<title>{title}</title>
|
|
|
</Head>
|
|
</Head>
|
|
|
<div className="dynamic-layout-root justify-content-between">
|
|
<div className="dynamic-layout-root justify-content-between">
|
|
|
-
|
|
|
|
|
<GrowiContextualSubNavigation currentPage={currentPage} />
|
|
<GrowiContextualSubNavigation currentPage={currentPage} />
|
|
|
|
|
|
|
|
<PageView
|
|
<PageView
|
|
@@ -147,20 +215,31 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const BasicLayoutWithEditor = ({ children }: { children?: ReactNode }): JSX.Element => {
|
|
|
|
|
|
|
+const BasicLayoutWithEditor = ({
|
|
|
|
|
+ children,
|
|
|
|
|
+}: {
|
|
|
|
|
+ children?: ReactNode;
|
|
|
|
|
+}): JSX.Element => {
|
|
|
const editorModeClassName = useEditorModeClassName();
|
|
const editorModeClassName = useEditorModeClassName();
|
|
|
return <BasicLayout className={editorModeClassName}>{children}</BasicLayout>;
|
|
return <BasicLayout className={editorModeClassName}>{children}</BasicLayout>;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
type LayoutProps = Props & {
|
|
type LayoutProps = Props & {
|
|
|
- children?: ReactNode
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ children?: ReactNode;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
|
|
const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
|
|
|
// Hydrate sidebar atoms with server-side data - must be called unconditionally
|
|
// Hydrate sidebar atoms with server-side data - must be called unconditionally
|
|
|
const initialProps = isInitialProps(props) ? props : undefined;
|
|
const initialProps = isInitialProps(props) ? props : undefined;
|
|
|
- useHydrateBasicLayoutConfigurationAtoms(initialProps?.searchConfig, initialProps?.sidebarConfig, initialProps?.userUISettings);
|
|
|
|
|
- useHydrateGeneralPageConfigurationAtoms(initialProps?.serverConfig, initialProps?.rendererConfig);
|
|
|
|
|
|
|
+ useHydrateBasicLayoutConfigurationAtoms(
|
|
|
|
|
+ initialProps?.searchConfig,
|
|
|
|
|
+ initialProps?.sidebarConfig,
|
|
|
|
|
+ initialProps?.userUISettings,
|
|
|
|
|
+ );
|
|
|
|
|
+ useHydrateGeneralPageConfigurationAtoms(
|
|
|
|
|
+ initialProps?.serverConfig,
|
|
|
|
|
+ initialProps?.rendererConfig,
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
return <BasicLayoutWithEditor>{children}</BasicLayoutWithEditor>;
|
|
return <BasicLayoutWithEditor>{children}</BasicLayoutWithEditor>;
|
|
|
};
|
|
};
|
|
@@ -177,9 +256,7 @@ Page.getLayout = function getLayout(page: React.ReactElement<Props>) {
|
|
|
<GrowiPluginsActivator />
|
|
<GrowiPluginsActivator />
|
|
|
<DrawioViewerScriptWithAtom />
|
|
<DrawioViewerScriptWithAtom />
|
|
|
|
|
|
|
|
- <Layout {...page.props}>
|
|
|
|
|
- {page}
|
|
|
|
|
- </Layout>
|
|
|
|
|
|
|
+ <Layout {...page.props}>{page}</Layout>
|
|
|
<UnsavedAlertDialog />
|
|
<UnsavedAlertDialog />
|
|
|
<DescendantsPageListModal />
|
|
<DescendantsPageListModal />
|
|
|
<DrawioModal />
|
|
<DrawioModal />
|
|
@@ -192,14 +269,22 @@ Page.getLayout = function getLayout(page: React.ReactElement<Props>) {
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
|
|
|
|
|
|
|
+export const getServerSideProps: GetServerSideProps<Props> = async (
|
|
|
|
|
+ context: GetServerSidePropsContext,
|
|
|
|
|
+) => {
|
|
|
//
|
|
//
|
|
|
// STAGE 1
|
|
// STAGE 1
|
|
|
//
|
|
//
|
|
|
|
|
|
|
|
- const commonEachPropsResult = await getServerSideCommonEachProps(context, NEXT_JS_ROUTING_PAGE);
|
|
|
|
|
|
|
+ const commonEachPropsResult = await getServerSideCommonEachProps(
|
|
|
|
|
+ context,
|
|
|
|
|
+ NEXT_JS_ROUTING_PAGE,
|
|
|
|
|
+ );
|
|
|
// Handle early return cases (redirect/notFound)
|
|
// Handle early return cases (redirect/notFound)
|
|
|
- if ('redirect' in commonEachPropsResult || 'notFound' in commonEachPropsResult) {
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ 'redirect' in commonEachPropsResult ||
|
|
|
|
|
+ 'notFound' in commonEachPropsResult
|
|
|
|
|
+ ) {
|
|
|
return commonEachPropsResult;
|
|
return commonEachPropsResult;
|
|
|
}
|
|
}
|
|
|
const commonEachProps = await commonEachPropsResult.props;
|
|
const commonEachProps = await commonEachPropsResult.props;
|
|
@@ -219,14 +304,18 @@ export const getServerSideProps: GetServerSideProps<Props> = async(context: GetS
|
|
|
//
|
|
//
|
|
|
|
|
|
|
|
// detect Next.js routing type
|
|
// detect Next.js routing type
|
|
|
- const nextjsRoutingType = detectNextjsRoutingType(context, NEXT_JS_ROUTING_PAGE);
|
|
|
|
|
|
|
+ const nextjsRoutingType = detectNextjsRoutingType(
|
|
|
|
|
+ context,
|
|
|
|
|
+ NEXT_JS_ROUTING_PAGE,
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Merge all results in a type-safe manner (using sequential merging)
|
|
// Merge all results in a type-safe manner (using sequential merging)
|
|
|
- return mergeGetServerSidePropsResults(commonEachPropsResult, (
|
|
|
|
|
- (nextjsRoutingType === NextjsRoutingType.INITIAL)
|
|
|
|
|
|
|
+ return mergeGetServerSidePropsResults(
|
|
|
|
|
+ commonEachPropsResult,
|
|
|
|
|
+ nextjsRoutingType === NextjsRoutingType.INITIAL
|
|
|
? await getServerSidePropsForInitial(context)
|
|
? await getServerSidePropsForInitial(context)
|
|
|
- : await getServerSidePropsForSameRoute(context)
|
|
|
|
|
- ));
|
|
|
|
|
|
|
+ : await getServerSidePropsForSameRoute(context),
|
|
|
|
|
+ );
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export default Page;
|
|
export default Page;
|