|
@@ -19,10 +19,9 @@ import { throttle, debounce } from 'throttle-debounce';
|
|
|
|
|
|
|
|
|
|
|
|
|
import { useShouldExpandContent } from '~/client/services/layout';
|
|
import { useShouldExpandContent } from '~/client/services/layout';
|
|
|
-import { useUpdateStateAfterSave, useSaveOrUpdate } from '~/client/services/page-operation';
|
|
|
|
|
|
|
+import { useUpdateStateAfterSave, updatePage } from '~/client/services/page-operation';
|
|
|
import { apiv3Get, apiv3PostForm } from '~/client/util/apiv3-client';
|
|
import { apiv3Get, apiv3PostForm } from '~/client/util/apiv3-client';
|
|
|
import { toastError, toastSuccess } from '~/client/util/toastr';
|
|
import { toastError, toastSuccess } from '~/client/util/toastr';
|
|
|
-import type { OptionsToSave } from '~/interfaces/page-operation';
|
|
|
|
|
import { SocketEventName } from '~/interfaces/websocket';
|
|
import { SocketEventName } from '~/interfaces/websocket';
|
|
|
import {
|
|
import {
|
|
|
useDefaultIndentSize, useCurrentUser,
|
|
useDefaultIndentSize, useCurrentUser,
|
|
@@ -32,7 +31,6 @@ import {
|
|
|
import {
|
|
import {
|
|
|
useEditorSettings,
|
|
useEditorSettings,
|
|
|
useCurrentIndentSize, useIsSlackEnabled, usePageTagsForEditors,
|
|
useCurrentIndentSize, useIsSlackEnabled, usePageTagsForEditors,
|
|
|
- useIsEnabledUnsavedWarning,
|
|
|
|
|
useIsConflict,
|
|
useIsConflict,
|
|
|
useEditingMarkdown,
|
|
useEditingMarkdown,
|
|
|
useWaitingSaveProcessing,
|
|
useWaitingSaveProcessing,
|
|
@@ -90,10 +88,9 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
const previewRef = useRef<HTMLDivElement>(null);
|
|
const previewRef = useRef<HTMLDivElement>(null);
|
|
|
- const codeMirrorEditorContainerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
|
|
const { data: isNotFound } = useIsNotFound();
|
|
const { data: isNotFound } = useIsNotFound();
|
|
|
- const { data: pageId, mutate: mutateCurrentPageId } = useCurrentPageId();
|
|
|
|
|
|
|
+ const { data: pageId } = useCurrentPageId();
|
|
|
const { data: currentPagePath } = useCurrentPagePath();
|
|
const { data: currentPagePath } = useCurrentPagePath();
|
|
|
const { data: currentPathname } = useCurrentPathname();
|
|
const { data: currentPathname } = useCurrentPathname();
|
|
|
const { data: currentPage } = useSWRxCurrentPage();
|
|
const { data: currentPage } = useSWRxCurrentPage();
|
|
@@ -125,14 +122,12 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
const { data: socket } = useGlobalSocket();
|
|
const { data: socket } = useGlobalSocket();
|
|
|
|
|
|
|
|
const { data: rendererOptions } = usePreviewOptions();
|
|
const { data: rendererOptions } = usePreviewOptions();
|
|
|
- const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
|
|
|
|
|
const { mutate: mutateIsConflict } = useIsConflict();
|
|
const { mutate: mutateIsConflict } = useIsConflict();
|
|
|
|
|
|
|
|
const { mutate: mutateResolvedTheme } = useResolvedThemeForEditor();
|
|
const { mutate: mutateResolvedTheme } = useResolvedThemeForEditor();
|
|
|
|
|
|
|
|
const shouldExpandContent = useShouldExpandContent(currentPage);
|
|
const shouldExpandContent = useShouldExpandContent(currentPage);
|
|
|
|
|
|
|
|
- const saveOrUpdate = useSaveOrUpdate();
|
|
|
|
|
const updateStateAfterSave = useUpdateStateAfterSave(pageId, { supressEditingMarkdownMutation: true });
|
|
const updateStateAfterSave = useUpdateStateAfterSave(pageId, { supressEditingMarkdownMutation: true });
|
|
|
|
|
|
|
|
const { resolvedTheme } = useNextThemes();
|
|
const { resolvedTheme } = useNextThemes();
|
|
@@ -216,40 +211,27 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
|
|
|
|
|
}, [socket, checkIsConflict]);
|
|
}, [socket, checkIsConflict]);
|
|
|
|
|
|
|
|
- const optionsToSave = useMemo((): OptionsToSave | undefined => {
|
|
|
|
|
- if (grantData == null) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- const userRelatedGrantedGroups = grantData.userRelatedGrantedGroups?.map((group) => {
|
|
|
|
|
- return { item: group.id, type: group.type };
|
|
|
|
|
- });
|
|
|
|
|
- const optionsToSave = {
|
|
|
|
|
- isSlackEnabled: isSlackEnabled ?? false,
|
|
|
|
|
- slackChannels: '', // set in save method by opts in SavePageControlls.tsx
|
|
|
|
|
- grant: grantData.grant,
|
|
|
|
|
- // pageTags: pageTags ?? [],
|
|
|
|
|
- userRelatedGrantUserGroupIds: userRelatedGrantedGroups,
|
|
|
|
|
- };
|
|
|
|
|
- return optionsToSave;
|
|
|
|
|
- }, [grantData, isSlackEnabled]);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
const save = useCallback(async(opts?: {slackChannels: string, overwriteScopesOfDescendants?: boolean}): Promise<IPageHasId | null> => {
|
|
const save = useCallback(async(opts?: {slackChannels: string, overwriteScopesOfDescendants?: boolean}): Promise<IPageHasId | null> => {
|
|
|
- if (currentPathname == null || optionsToSave == null) {
|
|
|
|
|
- logger.error('Some materials to save are invalid', { grantData, isSlackEnabled, currentPathname });
|
|
|
|
|
|
|
+ if (pageId == null || currentPagePath == null || currentRevisionId == null || grantData == null) {
|
|
|
|
|
+ logger.error('Some materials to save are invalid', {
|
|
|
|
|
+ pageId, currentPagePath, currentRevisionId, grantData,
|
|
|
|
|
+ });
|
|
|
throw new Error('Some materials to save are invalid');
|
|
throw new Error('Some materials to save are invalid');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const options = Object.assign(optionsToSave, opts);
|
|
|
|
|
-
|
|
|
|
|
try {
|
|
try {
|
|
|
mutateWaitingSaveProcessing(true);
|
|
mutateWaitingSaveProcessing(true);
|
|
|
|
|
|
|
|
- const { page } = await saveOrUpdate(
|
|
|
|
|
- codeMirrorEditor?.getDoc() ?? '',
|
|
|
|
|
- { pageId, path: currentPagePath || currentPathname, revisionId: currentRevisionId },
|
|
|
|
|
- options,
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ const { page } = await updatePage({
|
|
|
|
|
+ pageId,
|
|
|
|
|
+ revisionId: currentRevisionId,
|
|
|
|
|
+ body: codeMirrorEditor?.getDoc() ?? '',
|
|
|
|
|
+ grant: grantData?.grant,
|
|
|
|
|
+ userRelatedGrantUserGroupIds: grantData?.userRelatedGrantedGroups?.map((group) => {
|
|
|
|
|
+ return { item: group.id, type: group.type };
|
|
|
|
|
+ }),
|
|
|
|
|
+ ...(opts ?? {}),
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
// to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
|
|
// to sync revision id with page tree: https://github.com/weseek/growi/pull/7227
|
|
|
mutatePageTree();
|
|
mutatePageTree();
|
|
@@ -271,12 +253,8 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
mutateWaitingSaveProcessing(false);
|
|
mutateWaitingSaveProcessing(false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- }, [
|
|
|
|
|
- codeMirrorEditor,
|
|
|
|
|
- currentPathname, optionsToSave, grantData, isSlackEnabled, saveOrUpdate, pageId,
|
|
|
|
|
- currentPagePath, currentRevisionId,
|
|
|
|
|
- mutateWaitingSaveProcessing, mutateRemotePageId, mutateRemoteRevisionId, mutateRemoteRevisionLastUpdatedAt, mutateRemoteRevisionLastUpdateUser,
|
|
|
|
|
- ]);
|
|
|
|
|
|
|
+ // eslint-disable-next-line max-len
|
|
|
|
|
+ }, [codeMirrorEditor, grantData, pageId, currentPagePath, currentRevisionId, mutateWaitingSaveProcessing, mutateRemotePageId, mutateRemoteRevisionId, mutateRemoteRevisionLastUpdatedAt, mutateRemoteRevisionLastUpdateUser]);
|
|
|
|
|
|
|
|
const saveAndReturnToViewHandler = useCallback(async(opts: {slackChannels: string, overwriteScopesOfDescendants?: boolean}) => {
|
|
const saveAndReturnToViewHandler = useCallback(async(opts: {slackChannels: string, overwriteScopesOfDescendants?: boolean}) => {
|
|
|
const page = await save(opts);
|
|
const page = await save(opts);
|
|
@@ -284,14 +262,9 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (isNotFound) {
|
|
|
|
|
- await router.push(`/${page._id}`);
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- updateStateAfterSave?.();
|
|
|
|
|
- }
|
|
|
|
|
mutateEditorMode(EditorMode.View);
|
|
mutateEditorMode(EditorMode.View);
|
|
|
- }, [save, isNotFound, mutateEditorMode, router, updateStateAfterSave]);
|
|
|
|
|
|
|
+ updateStateAfterSave?.();
|
|
|
|
|
+ }, [mutateEditorMode, save, updateStateAfterSave]);
|
|
|
|
|
|
|
|
const saveWithShortcut = useCallback(async() => {
|
|
const saveWithShortcut = useCallback(async() => {
|
|
|
const page = await save();
|
|
const page = await save();
|
|
@@ -299,16 +272,9 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (isNotFound) {
|
|
|
|
|
- await router.push(`/${page._id}#edit`);
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- updateStateAfterSave?.();
|
|
|
|
|
- }
|
|
|
|
|
toastSuccess(t('toaster.save_succeeded'));
|
|
toastSuccess(t('toaster.save_succeeded'));
|
|
|
- mutateEditorMode(EditorMode.Editor);
|
|
|
|
|
-
|
|
|
|
|
- }, [isNotFound, mutateEditorMode, router, save, t, updateStateAfterSave]);
|
|
|
|
|
|
|
+ updateStateAfterSave?.();
|
|
|
|
|
+ }, [save, t, updateStateAfterSave]);
|
|
|
|
|
|
|
|
|
|
|
|
|
// the upload event handler
|
|
// the upload event handler
|