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

Merge branch 'master' into imprv/115672-presentation-preview

reiji-h 2 лет назад
Родитель
Сommit
b7bfd912fd

+ 2 - 4
apps/app/src/client/services/page-operation.ts

@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
 
-import { SubscriptionStatusType, Nullable } from '@growi/core';
+import { SubscriptionStatusType, type Nullable } from '@growi/core';
 import urljoin from 'url-join';
 
 import { OptionsToSave } from '~/interfaces/page-operation';
@@ -153,10 +153,8 @@ export const useSaveOrUpdate = (): SaveOrUpdateFunction => {
     // markdown = pageEditor.getMarkdown();
     // }
 
-    const isNoRevisionPage = pageId != null && revisionId == null;
-
     let res;
-    if (pageId == null || isNoRevisionPage) {
+    if (pageId == null || revisionId == null) {
       res = await createPage(path, markdown, options);
     }
     else {

+ 2 - 2
apps/app/src/components/PageEditor.tsx

@@ -112,7 +112,7 @@ const PageEditor = React.memo((): JSX.Element => {
 
   // TODO: remove workaround
   // for https://redmine.weseek.co.jp/issues/125923
-  const [createdPageRevisionIdWithAttachment, setCreatedPageRevisionIdWithAttachment] = useState('');
+  const [createdPageRevisionIdWithAttachment, setCreatedPageRevisionIdWithAttachment] = useState();
 
   // TODO: remove workaround
   // for https://redmine.weseek.co.jp/issues/125923
@@ -158,7 +158,7 @@ const PageEditor = React.memo((): JSX.Element => {
   // TODO: remove workaround
   // for https://redmine.weseek.co.jp/issues/125923
   useEffect(() => {
-    setCreatedPageRevisionIdWithAttachment('');
+    setCreatedPageRevisionIdWithAttachment(undefined);
   }, [router]);
 
   useEffect(() => {

+ 4 - 5
apps/app/src/components/SavePageControls.tsx

@@ -14,7 +14,7 @@ import {
   useIsEditable, useIsAclEnabled,
 } from '~/stores/context';
 import { useWaitingSaveProcessing } from '~/stores/editor';
-import { useCurrentPagePath, useCurrentPageId } from '~/stores/page';
+import { useSWRxCurrentPage } from '~/stores/page';
 import { useSelectedGrant } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 
@@ -38,11 +38,10 @@ export type SavePageControlsProps = {
 export const SavePageControls = (props: SavePageControlsProps): JSX.Element | null => {
   const { slackChannels } = props;
   const { t } = useTranslation();
-  const { data: currentPagePath } = useCurrentPagePath();
+  const { data: currentPage } = useSWRxCurrentPage();
   const { data: isEditable } = useIsEditable();
   const { data: isAclEnabled } = useIsAclEnabled();
   const { data: grantData, mutate: mutateGrant } = useSelectedGrant();
-  const { data: pageId } = useCurrentPageId();
   const { data: _isWaitingSaveProcessing } = useWaitingSaveProcessing();
 
   const isWaitingSaveProcessing = _isWaitingSaveProcessing === true; // ignore undefined
@@ -72,8 +71,8 @@ export const SavePageControls = (props: SavePageControlsProps): JSX.Element | nu
 
   const { grant, grantedGroup } = grantData;
 
-  const isRootPage = isTopPage(currentPagePath ?? '');
-  const labelSubmitButton = pageId == null ? t('Create') : t('Update');
+  const isRootPage = isTopPage(currentPage?.path ?? '');
+  const labelSubmitButton = (currentPage != null && !currentPage.isEmpty) ? t('Update') : t('Create');
   const labelOverwriteScopes = t('page_edit.overwrite_scopes', { operation: labelSubmitButton });
 
   return (

+ 4 - 7
apps/app/src/pages/utils/commons.ts

@@ -172,23 +172,20 @@ export const useInitSidebarConfig = (sidebarConfig: ISidebarConfig, userUISettin
   useCurrentProductNavWidth(userUISettings?.currentProductNavWidth);
 };
 
-
 export const skipSSR = async(page: PageDocument): Promise<boolean> => {
   if (!isServer()) {
     throw new Error('This method is not available on the client-side');
   }
 
-  // page document only stores the bodyLength of the latest revision
-  if (!page.isLatestRevision() || page.latestRevisionBodyLength == null) {
+  const latestRevisionBodyLength = await page.getLatestRevisionBodyLength();
+
+  if (latestRevisionBodyLength == null) {
     return true;
   }
 
   const { configManager } = await import('~/server/service/config-manager');
   await configManager.loadConfigs();
   const ssrMaxRevisionBodyLength = configManager.getConfig('crowi', 'app:ssrMaxRevisionBodyLength');
-  if (ssrMaxRevisionBodyLength < page.latestRevisionBodyLength) {
-    return true;
-  }
 
-  return false;
+  return ssrMaxRevisionBodyLength < latestRevisionBodyLength;
 };

+ 37 - 1
apps/app/src/server/models/page.ts

@@ -2,7 +2,9 @@
 
 import nodePath from 'path';
 
-import { HasObjectId, pagePathUtils, pathUtils } from '@growi/core';
+import {
+  HasObjectId, isPopulated, pagePathUtils, pathUtils,
+} from '@growi/core';
 import { collectAncestorPaths } from '@growi/core/dist/utils/page-path-utils/collect-ancestor-paths';
 import escapeStringRegexp from 'escape-string-regexp';
 import mongoose, {
@@ -40,6 +42,8 @@ const STATUS_DELETED = 'deleted';
 
 export interface PageDocument extends IPage, Document {
   [x:string]: any // for obsolete methods
+  getLatestRevisionBodyLength(): Promise<number | null | undefined>
+  calculateAndUpdateLatestRevisionBodyLength(this: PageDocument): Promise<void>
 }
 
 
@@ -959,6 +963,38 @@ schema.statics.findNonEmptyClosestAncestor = async function(path: string): Promi
   return ancestors[0];
 };
 
+/*
+ * get latest revision body length
+ */
+schema.methods.getLatestRevisionBodyLength = async function(this: PageDocument): Promise<number | null | undefined> {
+  if (!this.isLatestRevision() || this.revision == null) {
+    return null;
+  }
+
+  if (this.latestRevisionBodyLength == null) {
+    await this.calculateAndUpdateLatestRevisionBodyLength();
+  }
+
+  return this.latestRevisionBodyLength;
+};
+
+/*
+ * calculate and update latestRevisionBodyLength
+ */
+schema.methods.calculateAndUpdateLatestRevisionBodyLength = async function(this: PageDocument): Promise<void> {
+  if (!this.isLatestRevision() || this.revision == null) {
+    logger.error('revision field is required.');
+    return;
+  }
+
+  // eslint-disable-next-line rulesdir/no-populate
+  const populatedPageDocument = await this.populate<PageDocument>('revision', 'body');
+
+  assert(isPopulated(populatedPageDocument.revision));
+
+  this.latestRevisionBodyLength = populatedPageDocument.revision.body.length;
+  await this.save();
+};
 
 export type PageCreateOptions = {
   format?: string