|
|
@@ -1,23 +1,22 @@
|
|
|
-import React, { useCallback, useEffect, useRef } from 'react';
|
|
|
+import React, {
|
|
|
+ useCallback, useEffect, useRef,
|
|
|
+} from 'react';
|
|
|
|
|
|
import EventEmitter from 'events';
|
|
|
|
|
|
import { pagePathUtils, IPagePopulatedToShowRevision } from '@growi/core';
|
|
|
-import { DrawioEditByViewerProps } from '@growi/remark-drawio';
|
|
|
import { useTranslation } from 'next-i18next';
|
|
|
import dynamic from 'next/dynamic';
|
|
|
import { HtmlElementNode } from 'rehype-toc';
|
|
|
|
|
|
-import MarkdownTable from '~/client/models/MarkdownTable';
|
|
|
-import { useSaveOrUpdate } from '~/client/services/page-operation';
|
|
|
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
|
|
|
-import { OptionsToSave } from '~/interfaces/page-operation';
|
|
|
+import { useDrawioModalLauncherForView } from '~/client/services/side-effects/drawio-modal-launcher-for-view';
|
|
|
+import { useHandsontableModalLauncherForView } from '~/client/services/side-effects/handsontable-modal-launcher-for-view';
|
|
|
+import { toastSuccess, toastError } from '~/client/util/toastr';
|
|
|
import {
|
|
|
- useIsGuestUser, useShareLinkId, useCurrentPathname, useIsNotFound,
|
|
|
+ useIsGuestUser, useCurrentPathname, useIsNotFound,
|
|
|
} from '~/stores/context';
|
|
|
import { useEditingMarkdown } from '~/stores/editor';
|
|
|
-import { useDrawioModal, useHandsontableModal } from '~/stores/modal';
|
|
|
-import { useCurrentPagePath, useSWRxCurrentPage, useSWRxTagsInfo } from '~/stores/page';
|
|
|
+import { useCurrentPagePath, useSWRxCurrentPage } from '~/stores/page';
|
|
|
import { useViewOptions } from '~/stores/renderer';
|
|
|
import {
|
|
|
useCurrentPageTocNode,
|
|
|
@@ -27,8 +26,6 @@ import { registerGrowiFacade } from '~/utils/growi-facade';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
import RevisionRenderer from './Page/RevisionRenderer';
|
|
|
-import mdu from './PageEditor/MarkdownDrawioUtil';
|
|
|
-import mtu from './PageEditor/MarkdownTableUtil';
|
|
|
import { UserInfo } from './User/UserInfo';
|
|
|
|
|
|
import styles from './Page.module.scss';
|
|
|
@@ -68,18 +65,12 @@ const PageSubstance = (props: PageSubstanceProps): JSX.Element => {
|
|
|
const { data: currentPathname } = useCurrentPathname();
|
|
|
const isSharedPage = pagePathUtils.isSharedPage(currentPathname ?? '');
|
|
|
|
|
|
- const { data: shareLinkId } = useShareLinkId();
|
|
|
const { mutate: mutateCurrentPage } = useSWRxCurrentPage();
|
|
|
const { mutate: mutateEditingMarkdown } = useEditingMarkdown();
|
|
|
- const { data: tagsInfo } = useSWRxTagsInfo(currentPage?._id);
|
|
|
const { data: isGuestUser } = useIsGuestUser();
|
|
|
const { data: isMobile } = useIsMobile();
|
|
|
const { data: rendererOptions, mutate: mutateRendererOptions } = useViewOptions(storeTocNodeHandler);
|
|
|
const { mutate: mutateCurrentPageTocNode } = useCurrentPageTocNode();
|
|
|
- const { open: openDrawioModal } = useDrawioModal();
|
|
|
- const { open: openHandsontableModal } = useHandsontableModal();
|
|
|
-
|
|
|
- const saveOrUpdate = useSaveOrUpdate();
|
|
|
|
|
|
|
|
|
// register to facade
|
|
|
@@ -99,37 +90,8 @@ const PageSubstance = (props: PageSubstanceProps): JSX.Element => {
|
|
|
}, [mutateCurrentPageTocNode, tocRef.current]); // include tocRef.current to call mutateCurrentPageTocNode when tocRef.current changes
|
|
|
|
|
|
|
|
|
- // TODO: refactor commonize saveByDrawioModal and saveByHandsontableModal
|
|
|
- const saveByDrawioModal = useCallback(async(drawioMxFile: string, bol: number, eol: number) => {
|
|
|
- if (currentPage == null || tagsInfo == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // disable if share link
|
|
|
- if (shareLinkId != null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const currentMarkdown = currentPage.revision.body;
|
|
|
- const optionsToSave: OptionsToSave = {
|
|
|
- isSlackEnabled: false,
|
|
|
- slackChannels: '',
|
|
|
- grant: currentPage.grant,
|
|
|
- grantUserGroupId: currentPage.grantedGroup?._id,
|
|
|
- grantUserGroupName: currentPage.grantedGroup?.name,
|
|
|
- pageTags: tagsInfo.tags,
|
|
|
- };
|
|
|
-
|
|
|
- const newMarkdown = mdu.replaceDrawioInMarkdown(drawioMxFile, currentMarkdown, bol, eol);
|
|
|
-
|
|
|
- try {
|
|
|
- const currentRevisionId = currentPage.revision._id;
|
|
|
- await saveOrUpdate(
|
|
|
- newMarkdown,
|
|
|
- { pageId: currentPage._id, path: currentPage.path, revisionId: currentRevisionId },
|
|
|
- optionsToSave,
|
|
|
- );
|
|
|
-
|
|
|
+ useHandsontableModalLauncherForView({
|
|
|
+ onSaveSuccess: (newMarkdown) => {
|
|
|
toastSuccess(t('toaster.save_succeeded'));
|
|
|
|
|
|
// rerender
|
|
|
@@ -137,55 +99,14 @@ const PageSubstance = (props: PageSubstanceProps): JSX.Element => {
|
|
|
mutateCurrentPage();
|
|
|
}
|
|
|
mutateEditingMarkdown(newMarkdown);
|
|
|
- }
|
|
|
- catch (error) {
|
|
|
- logger.error('failed to save', error);
|
|
|
+ },
|
|
|
+ onSaveError: (error) => {
|
|
|
toastError(error);
|
|
|
- }
|
|
|
- }, [currentPage, isSharedPage, mutateCurrentPage, mutateEditingMarkdown, saveOrUpdate, shareLinkId, t, tagsInfo]);
|
|
|
-
|
|
|
- // set handler to open DrawioModal
|
|
|
- useEffect(() => {
|
|
|
- // disable if share link
|
|
|
- if (shareLinkId != null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const handler = (data: DrawioEditByViewerProps) => {
|
|
|
- openDrawioModal(data.drawioMxFile, drawioMxFile => saveByDrawioModal(drawioMxFile, data.bol, data.eol));
|
|
|
- };
|
|
|
- globalEmitter.on('launchDrawioModal', handler);
|
|
|
-
|
|
|
- return function cleanup() {
|
|
|
- globalEmitter.removeListener('launchDrawioModal', handler);
|
|
|
- };
|
|
|
- }, [openDrawioModal, saveByDrawioModal, shareLinkId]);
|
|
|
-
|
|
|
- const saveByHandsontableModal = useCallback(async(table: MarkdownTable, bol: number, eol: number) => {
|
|
|
- if (currentPage == null || tagsInfo == null || shareLinkId != null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const currentMarkdown = currentPage.revision.body;
|
|
|
- const optionsToSave: OptionsToSave = {
|
|
|
- isSlackEnabled: false,
|
|
|
- slackChannels: '',
|
|
|
- grant: currentPage.grant,
|
|
|
- grantUserGroupId: currentPage.grantedGroup?._id,
|
|
|
- grantUserGroupName: currentPage.grantedGroup?.name,
|
|
|
- pageTags: tagsInfo.tags,
|
|
|
- };
|
|
|
-
|
|
|
- const newMarkdown = mtu.replaceMarkdownTableInMarkdown(table, currentMarkdown, bol, eol);
|
|
|
-
|
|
|
- try {
|
|
|
- const currentRevisionId = currentPage.revision._id;
|
|
|
- await saveOrUpdate(
|
|
|
- newMarkdown,
|
|
|
- { pageId: currentPage._id, path: currentPage.path, revisionId: currentRevisionId },
|
|
|
- optionsToSave,
|
|
|
- );
|
|
|
+ },
|
|
|
+ });
|
|
|
|
|
|
+ useDrawioModalLauncherForView({
|
|
|
+ onSaveSuccess: (newMarkdown) => {
|
|
|
toastSuccess(t('toaster.save_succeeded'));
|
|
|
|
|
|
// rerender
|
|
|
@@ -193,30 +114,12 @@ const PageSubstance = (props: PageSubstanceProps): JSX.Element => {
|
|
|
mutateCurrentPage();
|
|
|
}
|
|
|
mutateEditingMarkdown(newMarkdown);
|
|
|
- }
|
|
|
- catch (error) {
|
|
|
- logger.error('failed to save', error);
|
|
|
+ },
|
|
|
+ onSaveError: (error) => {
|
|
|
toastError(error);
|
|
|
- }
|
|
|
- }, [currentPage, isSharedPage, mutateCurrentPage, mutateEditingMarkdown, saveOrUpdate, shareLinkId, t, tagsInfo]);
|
|
|
+ },
|
|
|
+ });
|
|
|
|
|
|
- // set handler to open HandsonTableModal
|
|
|
- useEffect(() => {
|
|
|
- if (currentPage == null || shareLinkId != null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const handler = (bol: number, eol: number) => {
|
|
|
- const markdown = currentPage.revision.body;
|
|
|
- const currentMarkdownTable = mtu.getMarkdownTableFromLine(markdown, bol, eol);
|
|
|
- openHandsontableModal(currentMarkdownTable, undefined, false, table => saveByHandsontableModal(table, bol, eol));
|
|
|
- };
|
|
|
- globalEmitter.on('launchHandsonTableModal', handler);
|
|
|
-
|
|
|
- return function cleanup() {
|
|
|
- globalEmitter.removeListener('launchHandsonTableModal', handler);
|
|
|
- };
|
|
|
- }, [currentPage, openHandsontableModal, saveByHandsontableModal, shareLinkId]);
|
|
|
|
|
|
if (currentPage == null || isGuestUser == null || rendererOptions == null) {
|
|
|
const entries = Object.entries({
|
|
|
@@ -226,6 +129,7 @@ const PageSubstance = (props: PageSubstanceProps): JSX.Element => {
|
|
|
.filter(([, value]) => value != null);
|
|
|
|
|
|
logger.warn('Some of materials are missing.', Object.fromEntries(entries));
|
|
|
+
|
|
|
return <></>;
|
|
|
}
|
|
|
|
|
|
@@ -260,7 +164,11 @@ export const Page = React.memo((): JSX.Element => {
|
|
|
return (
|
|
|
<>
|
|
|
{ isUsersHomePagePath && <UserInfo author={currentPage?.creator} /> }
|
|
|
- { !isNotFound && <PageSubstance currentPage={currentPage ?? undefined} /> }
|
|
|
+
|
|
|
+ { !isNotFound && (
|
|
|
+ <PageSubstance currentPage={currentPage ?? undefined} />
|
|
|
+ ) }
|
|
|
+
|
|
|
{ isNotFound && <NotFoundPage /> }
|
|
|
</>
|
|
|
);
|