|
@@ -3,30 +3,39 @@ import React, {
|
|
|
} from 'react';
|
|
} from 'react';
|
|
|
|
|
|
|
|
import { UserPicture } from '@growi/ui';
|
|
import { UserPicture } from '@growi/ui';
|
|
|
|
|
+import dynamic from 'next/dynamic';
|
|
|
import {
|
|
import {
|
|
|
Button, TabContent, TabPane,
|
|
Button, TabContent, TabPane,
|
|
|
} from 'reactstrap';
|
|
} from 'reactstrap';
|
|
|
import * as toastr from 'toastr';
|
|
import * as toastr from 'toastr';
|
|
|
|
|
|
|
|
import { apiPostForm } from '~/client/util/apiv1-client';
|
|
import { apiPostForm } from '~/client/util/apiv1-client';
|
|
|
-import { RendererOptions } from '~/services/renderer/renderer';
|
|
|
|
|
|
|
+import { IEditorMethods } from '~/interfaces/editor-methods';
|
|
|
import { useSWRxPageComment } from '~/stores/comment';
|
|
import { useSWRxPageComment } from '~/stores/comment';
|
|
|
import {
|
|
import {
|
|
|
- useCurrentPagePath, useCurrentPageId, useCurrentUser, useRevisionId, useIsSlackConfigured,
|
|
|
|
|
|
|
+ useCurrentPagePath, useCurrentUser, useRevisionId, useIsSlackConfigured,
|
|
|
useIsUploadableFile, useIsUploadableImage,
|
|
useIsUploadableFile, useIsUploadableImage,
|
|
|
} from '~/stores/context';
|
|
} from '~/stores/context';
|
|
|
import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
|
|
import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
|
|
|
|
|
|
|
|
import { CustomNavTab } from '../CustomNavigation/CustomNav';
|
|
import { CustomNavTab } from '../CustomNavigation/CustomNav';
|
|
|
import NotAvailableForGuest from '../NotAvailableForGuest';
|
|
import NotAvailableForGuest from '../NotAvailableForGuest';
|
|
|
-import Editor from '../PageEditor/Editor';
|
|
|
|
|
-import { SlackNotification } from '../SlackNotification';
|
|
|
|
|
|
|
+import { Skelton } from '../Skelton';
|
|
|
|
|
+
|
|
|
|
|
|
|
|
import { CommentPreview } from './CommentPreview';
|
|
import { CommentPreview } from './CommentPreview';
|
|
|
|
|
|
|
|
import styles from './CommentEditor.module.scss';
|
|
import styles from './CommentEditor.module.scss';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+const SlackNotification = dynamic(() => import('../SlackNotification').then(mod => mod.SlackNotification), { ssr: false });
|
|
|
|
|
+const Editor = dynamic(() => import('../PageEditor/Editor'),
|
|
|
|
|
+ {
|
|
|
|
|
+ ssr: false,
|
|
|
|
|
+ loading: () => <Skelton additionalClass="grw-skelton page-comment-editor-skelton" />,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
const navTabMapping = {
|
|
const navTabMapping = {
|
|
|
comment_editor: {
|
|
comment_editor: {
|
|
|
Icon: () => <i className="icon-settings" />,
|
|
Icon: () => <i className="icon-settings" />,
|
|
@@ -41,7 +50,7 @@ const navTabMapping = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export type CommentEditorProps = {
|
|
export type CommentEditorProps = {
|
|
|
- rendererOptions: RendererOptions,
|
|
|
|
|
|
|
+ pageId: string,
|
|
|
isForNewComment?: boolean,
|
|
isForNewComment?: boolean,
|
|
|
replyTo?: string,
|
|
replyTo?: string,
|
|
|
currentCommentId?: string,
|
|
currentCommentId?: string,
|
|
@@ -50,23 +59,17 @@ export type CommentEditorProps = {
|
|
|
onCommentButtonClicked?: () => void,
|
|
onCommentButtonClicked?: () => void,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type EditorRef = {
|
|
|
|
|
- setValue: (value: string) => void,
|
|
|
|
|
- insertText: (text: string) => void,
|
|
|
|
|
- terminateUploadingState: () => void,
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
|
|
export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
- rendererOptions, isForNewComment, replyTo,
|
|
|
|
|
|
|
+ pageId, isForNewComment, replyTo,
|
|
|
currentCommentId, commentBody, onCancelButtonClicked, onCommentButtonClicked,
|
|
currentCommentId, commentBody, onCancelButtonClicked, onCommentButtonClicked,
|
|
|
} = props;
|
|
} = props;
|
|
|
|
|
|
|
|
const { data: currentUser } = useCurrentUser();
|
|
const { data: currentUser } = useCurrentUser();
|
|
|
const { data: currentPagePath } = useCurrentPagePath();
|
|
const { data: currentPagePath } = useCurrentPagePath();
|
|
|
- const { data: currentPageId } = useCurrentPageId();
|
|
|
|
|
- const { update: updateComment, post: postComment } = useSWRxPageComment(currentPageId);
|
|
|
|
|
|
|
+ const { update: updateComment, post: postComment } = useSWRxPageComment(pageId);
|
|
|
const { data: revisionId } = useRevisionId();
|
|
const { data: revisionId } = useRevisionId();
|
|
|
const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
|
|
const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
|
|
|
const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
|
|
const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
|
|
@@ -80,7 +83,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
|
|
|
const [error, setError] = useState();
|
|
const [error, setError] = useState();
|
|
|
const [slackChannels, setSlackChannels] = useState(slackChannelsData?.toString());
|
|
const [slackChannels, setSlackChannels] = useState(slackChannelsData?.toString());
|
|
|
|
|
|
|
|
- const editorRef = useRef<EditorRef>(null);
|
|
|
|
|
|
|
+ const editorRef = useRef<IEditorMethods>(null);
|
|
|
|
|
|
|
|
const handleSelect = useCallback((activeTab: string) => {
|
|
const handleSelect = useCallback((activeTab: string) => {
|
|
|
setActiveTab(activeTab);
|
|
setActiveTab(activeTab);
|
|
@@ -173,7 +176,6 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
|
|
|
if (editorRef.current == null) { return }
|
|
if (editorRef.current == null) { return }
|
|
|
|
|
|
|
|
const pagePath = currentPagePath;
|
|
const pagePath = currentPagePath;
|
|
|
- const pageId = currentPageId;
|
|
|
|
|
const endpoint = '/attachments.add';
|
|
const endpoint = '/attachments.add';
|
|
|
const formData = new FormData();
|
|
const formData = new FormData();
|
|
|
formData.append('file', file);
|
|
formData.append('file', file);
|
|
@@ -199,7 +201,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
|
|
|
finally {
|
|
finally {
|
|
|
editorRef.current.terminateUploadingState();
|
|
editorRef.current.terminateUploadingState();
|
|
|
}
|
|
}
|
|
|
- }, [apiErrorHandler, currentPageId, currentPagePath]);
|
|
|
|
|
|
|
+ }, [apiErrorHandler, currentPagePath, pageId]);
|
|
|
|
|
|
|
|
const getCommentHtml = useCallback(() => {
|
|
const getCommentHtml = useCallback(() => {
|
|
|
if (currentPagePath == null) {
|
|
if (currentPagePath == null) {
|
|
@@ -208,12 +210,11 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<CommentPreview
|
|
<CommentPreview
|
|
|
- rendererOptions={rendererOptions}
|
|
|
|
|
markdown={comment}
|
|
markdown={comment}
|
|
|
path={currentPagePath}
|
|
path={currentPagePath}
|
|
|
/>
|
|
/>
|
|
|
);
|
|
);
|
|
|
- }, [currentPagePath, comment, rendererOptions]);
|
|
|
|
|
|
|
+ }, [currentPagePath, comment]);
|
|
|
|
|
|
|
|
const renderBeforeReady = useCallback((): JSX.Element => {
|
|
const renderBeforeReady = useCallback((): JSX.Element => {
|
|
|
return (
|
|
return (
|