|
|
@@ -1,9 +1,10 @@
|
|
|
import React, { useEffect } from 'react';
|
|
|
|
|
|
+
|
|
|
import EventEmitter from 'events';
|
|
|
|
|
|
import {
|
|
|
- IDataWithMeta, IPageInfoForEntity, IPagePopulatedToShowRevision, isClient, pagePathUtils, pathUtils,
|
|
|
+ IDataWithMeta, IPageInfoForEntity, IPagePopulatedToShowRevision, isClient, isIPageInfoForEntity, IUserHasId, pagePathUtils, pathUtils,
|
|
|
} from '@growi/core';
|
|
|
import ExtensibleCustomError from 'extensible-custom-error';
|
|
|
import {
|
|
|
@@ -13,6 +14,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
|
|
import dynamic from 'next/dynamic';
|
|
|
import Head from 'next/head';
|
|
|
import { useRouter } from 'next/router';
|
|
|
+import superjson from 'superjson';
|
|
|
|
|
|
import { PageAlerts } from '~/components/PageAlert/PageAlerts';
|
|
|
// import { PageComments } from '~/components/PageComment/PageComments';
|
|
|
@@ -25,8 +27,9 @@ import { CrowiRequest } from '~/interfaces/crowi-request';
|
|
|
import { CustomWindow } from '~/interfaces/global';
|
|
|
import { RendererConfig } from '~/interfaces/services/renderer';
|
|
|
import { ISidebarConfig } from '~/interfaces/sidebar-config';
|
|
|
+import { IUserUISettings } from '~/interfaces/user-ui-settings';
|
|
|
import { PageModel, PageDocument } from '~/server/models/page';
|
|
|
-import UserUISettings, { UserUISettingsDocument } from '~/server/models/user-ui-settings';
|
|
|
+import UserUISettings from '~/server/models/user-ui-settings';
|
|
|
import Xss from '~/services/xss';
|
|
|
import { useSWRxCurrentPage, useSWRxPageInfo, useSWRxPage } from '~/stores/page';
|
|
|
import {
|
|
|
@@ -66,12 +69,42 @@ import {
|
|
|
|
|
|
|
|
|
const logger = loggerFactory('growi:pages:all');
|
|
|
+
|
|
|
const {
|
|
|
isPermalink: _isPermalink, isUsersHomePage, isTrashPage: _isTrashPage, isUserPage, isCreatablePage,
|
|
|
} = pagePathUtils;
|
|
|
const { removeHeadingSlash } = pathUtils;
|
|
|
|
|
|
|
|
|
+type IPageToShowRevisionWithMeta = IDataWithMeta<IPagePopulatedToShowRevision & PageDocument, IPageInfoForEntity>;
|
|
|
+type IPageToShowRevisionWithMetaSerialized = IDataWithMeta<string, string>;
|
|
|
+// register custom serializer
|
|
|
+superjson.registerCustom<IPageToShowRevisionWithMeta, IPageToShowRevisionWithMetaSerialized>(
|
|
|
+ {
|
|
|
+ isApplicable: (v): v is IPageToShowRevisionWithMeta => {
|
|
|
+ return v?.data != null
|
|
|
+ && v?.data.toObject != null
|
|
|
+ && v?.meta != null
|
|
|
+ && isIPageInfoForEntity(v.meta);
|
|
|
+ },
|
|
|
+ serialize: (v) => {
|
|
|
+ return {
|
|
|
+ data: superjson.stringify(v.data.toObject()),
|
|
|
+ // data: superjson.stringify(v.data),
|
|
|
+ meta: superjson.stringify(v.meta),
|
|
|
+ };
|
|
|
+ },
|
|
|
+ deserialize: (v) => {
|
|
|
+ return {
|
|
|
+ data: superjson.parse(v.data),
|
|
|
+ meta: v.meta != null ? superjson.parse(v.meta) : undefined,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ },
|
|
|
+ 'IPageToShowRevisionWithMetaTransformer',
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
const IdenticalPathPage = (): JSX.Element => {
|
|
|
const IdenticalPathPage = dynamic(() => import('../components/IdenticalPathPage').then(mod => mod.IdenticalPathPage), { ssr: false });
|
|
|
return <IdenticalPathPage />;
|
|
|
@@ -82,12 +115,10 @@ const PutbackPageModal = (): JSX.Element => {
|
|
|
return <PutbackPageModal />;
|
|
|
};
|
|
|
|
|
|
-type IPageToShowRevisionWithMeta = IDataWithMeta<IPagePopulatedToShowRevision, IPageInfoForEntity>;
|
|
|
-
|
|
|
type Props = CommonProps & {
|
|
|
- currentUser: string,
|
|
|
+ currentUser: IUserHasId,
|
|
|
|
|
|
- pageWithMetaStr: string,
|
|
|
+ pageWithMeta: IPageToShowRevisionWithMeta,
|
|
|
// pageUser?: any,
|
|
|
// redirectTo?: string;
|
|
|
// redirectFrom?: string;
|
|
|
@@ -127,7 +158,7 @@ type Props = CommonProps & {
|
|
|
rendererConfig: RendererConfig,
|
|
|
|
|
|
// UI
|
|
|
- userUISettings: UserUISettingsDocument | null
|
|
|
+ userUISettings: IUserUISettings | null
|
|
|
// Sidebar
|
|
|
sidebarConfig: ISidebarConfig,
|
|
|
};
|
|
|
@@ -139,7 +170,7 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
|
|
|
const UnsavedAlertDialog = dynamic(() => import('./UnsavedAlertDialog'), { ssr: false });
|
|
|
const GrowiSubNavigationSwitcher = dynamic(() => import('../components/Navbar/GrowiSubNavigationSwitcher'), { ssr: false });
|
|
|
|
|
|
- const { data: currentUser } = useCurrentUser(props.currentUser != null ? JSON.parse(props.currentUser) : null);
|
|
|
+ const { data: currentUser } = useCurrentUser(props.currentUser ?? null);
|
|
|
|
|
|
// register global EventEmitter
|
|
|
if (isClient()) {
|
|
|
@@ -196,10 +227,9 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
|
|
|
|
|
|
// const { data: editorMode } = useEditorMode();
|
|
|
|
|
|
- let pageWithMeta: IPageToShowRevisionWithMeta | undefined;
|
|
|
- if (props.pageWithMetaStr != null) {
|
|
|
- pageWithMeta = JSON.parse(props.pageWithMetaStr) as IPageToShowRevisionWithMeta;
|
|
|
- }
|
|
|
+ const { pageWithMeta, userUISettings } = props;
|
|
|
+
|
|
|
+ console.log({ pageWithMeta, currentUser, userUISettings });
|
|
|
|
|
|
let shouldRenderPutbackPageModal = false;
|
|
|
if (pageWithMeta != null) {
|
|
|
@@ -319,7 +349,7 @@ class MultiplePagesHitsError extends ExtensibleCustomError {
|
|
|
|
|
|
}
|
|
|
|
|
|
-async function getPageData(context: GetServerSidePropsContext, props: Props): Promise<IPageToShowRevisionWithMeta|null> {
|
|
|
+async function injectPageData(context: GetServerSidePropsContext, props: Props): Promise<void> {
|
|
|
const req: CrowiRequest = context.req as CrowiRequest;
|
|
|
const { crowi } = req;
|
|
|
const { revisionId } = req.query;
|
|
|
@@ -342,8 +372,8 @@ async function getPageData(context: GetServerSidePropsContext, props: Props): Pr
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const result: IPageToShowRevisionWithMeta = await pageService.findPageAndMetaDataByViewer(pageId, currentPathname, user, true); // includeEmpty = true, isSharedPage = false
|
|
|
- const page = result?.data as unknown as PageDocument;
|
|
|
+ const pageWithMeta: IPageToShowRevisionWithMeta = await pageService.findPageAndMetaDataByViewer(pageId, currentPathname, user, true); // includeEmpty = true, isSharedPage = false
|
|
|
+ const page = pageWithMeta?.data as unknown as PageDocument;
|
|
|
|
|
|
// populate & check if the revision is latest
|
|
|
if (page != null) {
|
|
|
@@ -352,10 +382,10 @@ async function getPageData(context: GetServerSidePropsContext, props: Props): Pr
|
|
|
props.isLatestRevision = page.isLatestRevision();
|
|
|
}
|
|
|
|
|
|
- return result;
|
|
|
+ props.pageWithMeta = pageWithMeta;
|
|
|
}
|
|
|
|
|
|
-async function injectRoutingInformation(context: GetServerSidePropsContext, props: Props, pageWithMeta: IPageToShowRevisionWithMeta|null): Promise<void> {
|
|
|
+async function injectRoutingInformation(context: GetServerSidePropsContext, props: Props): Promise<void> {
|
|
|
const req: CrowiRequest = context.req as CrowiRequest;
|
|
|
const { crowi } = req;
|
|
|
const Page = crowi.model('Page') as PageModel;
|
|
|
@@ -364,7 +394,7 @@ async function injectRoutingInformation(context: GetServerSidePropsContext, prop
|
|
|
const pageId = getPageIdFromPathname(currentPathname);
|
|
|
const isPermalink = _isPermalink(currentPathname);
|
|
|
|
|
|
- const page = pageWithMeta?.data;
|
|
|
+ const page = props.pageWithMeta?.data;
|
|
|
|
|
|
if (props.isIdenticalPathPage) {
|
|
|
// TBD
|
|
|
@@ -477,7 +507,7 @@ async function injectNextI18NextConfigurations(context: GetServerSidePropsContex
|
|
|
}
|
|
|
|
|
|
export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
|
|
|
- const req: CrowiRequest = context.req as CrowiRequest;
|
|
|
+ const req = context.req as CrowiRequest<IUserHasId & any>;
|
|
|
const { user } = req;
|
|
|
|
|
|
const result = await getServerSideCommonProps(context);
|
|
|
@@ -490,10 +520,8 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
|
|
|
}
|
|
|
|
|
|
const props: Props = result.props as Props;
|
|
|
- let pageWithMeta;
|
|
|
try {
|
|
|
- pageWithMeta = await getPageData(context, props);
|
|
|
- props.pageWithMetaStr = JSON.stringify(pageWithMeta);
|
|
|
+ await injectPageData(context, props);
|
|
|
}
|
|
|
catch (err) {
|
|
|
if (err instanceof MultiplePagesHitsError) {
|
|
|
@@ -504,17 +532,19 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- injectRoutingInformation(context, props, pageWithMeta);
|
|
|
+ injectRoutingInformation(context, props);
|
|
|
injectServerConfigurations(context, props);
|
|
|
injectNextI18NextConfigurations(context, props, ['translation']);
|
|
|
|
|
|
- if (user != null) {
|
|
|
- props.currentUser = JSON.stringify(user);
|
|
|
- }
|
|
|
+ // if (user != null) {
|
|
|
+ // props.currentUser = superjson.stringify(user.toObject());
|
|
|
+ // }
|
|
|
|
|
|
// UI
|
|
|
- const userUISettings = user == null ? null : await UserUISettings.findOne({ user: user._id }).exec();
|
|
|
- props.userUISettings = JSON.parse(JSON.stringify(userUISettings));
|
|
|
+ // const userUISettings = user == null ? null : await UserUISettings.findOne({ user: user._id }).exec();
|
|
|
+ // if (userUISettings != null) {
|
|
|
+ // props.userUISettings = userUISettings.toJSON();
|
|
|
+ // }
|
|
|
|
|
|
return {
|
|
|
props,
|