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

Merge pull request #7603 from weseek/imprv/120709-121002-show-browser-alert-when-comment-is-not-posted

imprv: show alert when comment not posted
Ryoji Shimizu 2 лет назад
Родитель
Сommit
941c546fe7

+ 25 - 7
apps/app/src/components/PageComment/CommentEditor.tsx

@@ -11,19 +11,18 @@ import * as toastr from 'toastr';
 
 import { apiPostForm } from '~/client/util/apiv1-client';
 import { IEditorMethods } from '~/interfaces/editor-methods';
-import { useSWRxPageComment } from '~/stores/comment';
+import { useSWRxPageComment, useSWRxEditingCommentsNum } from '~/stores/comment';
 import {
   useCurrentUser, useIsSlackConfigured,
   useIsUploadableFile, useIsUploadableImage,
 } from '~/stores/context';
-import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
+import { useSWRxSlackChannels, useIsSlackEnabled, useIsEnabledUnsavedWarning } from '~/stores/editor';
 import { useCurrentPagePath } from '~/stores/page';
 
 import { CustomNavTab } from '../CustomNavigation/CustomNav';
 import { NotAvailableForGuest } from '../NotAvailableForGuest';
 import Editor from '../PageEditor/Editor';
 
-
 import { CommentPreview } from './CommentPreview';
 
 import styles from './CommentEditor.module.scss';
@@ -70,12 +69,18 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
   const { data: isSlackConfigured } = useIsSlackConfigured();
   const { data: isUploadableFile } = useIsUploadableFile();
   const { data: isUploadableImage } = useIsUploadableImage();
+  const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
+  const {
+    increment: incrementEditingCommentsNum,
+    decrement: decrementEditingCommentsNum,
+  } = useSWRxEditingCommentsNum();
 
   const [isReadyToUse, setIsReadyToUse] = useState(!isForNewComment);
   const [comment, setComment] = useState(commentBody ?? '');
   const [activeTab, setActiveTab] = useState('comment_editor');
   const [error, setError] = useState();
   const [slackChannels, setSlackChannels] = useState<string>('');
+  const [incremented, setIncremented] = useState(false);
 
   const editorRef = useRef<IEditorMethods>(null);
 
@@ -102,7 +107,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
     setSlackChannels(slackChannels);
   }, []);
 
-  const initializeEditor = useCallback(() => {
+  const initializeEditor = useCallback(async() => {
     setComment('');
     setActiveTab('comment_editor');
     setError(undefined);
@@ -110,7 +115,11 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
     // reset value
     if (editorRef.current == null) { return }
     editorRef.current.setValue('');
-  }, [initializeSlackEnabled]);
+    const editingCommentsNum = await decrementEditingCommentsNum();
+    if (editingCommentsNum === 0) {
+      mutateIsEnabledUnsavedWarning(false); // must be after clearing comment or else onChange will override bool
+    }
+  }, [initializeSlackEnabled, mutateIsEnabledUnsavedWarning, decrementEditingCommentsNum]);
 
   const cancelButtonClickedHandler = useCallback(() => {
     // change state to not ready
@@ -119,10 +128,12 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
       setIsReadyToUse(false);
     }
 
+    initializeEditor();
+
     if (onCancelButtonClicked != null) {
       onCancelButtonClicked();
     }
-  }, [isForNewComment, onCancelButtonClicked]);
+  }, [isForNewComment, onCancelButtonClicked, initializeEditor]);
 
   const postCommentHandler = useCallback(async() => {
     try {
@@ -237,7 +248,14 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
     );
   }, []);
 
-  const onChangeHandler = useCallback((newValue: string) => setComment(newValue), []);
+  const onChangeHandler = useCallback((newValue: string, isClean: boolean) => {
+    setComment(newValue);
+    if (!isClean && !incremented) {
+      incrementEditingCommentsNum();
+      setIncremented(true);
+    }
+    mutateIsEnabledUnsavedWarning(!isClean);
+  }, [mutateIsEnabledUnsavedWarning, incrementEditingCommentsNum, incremented]);
 
   const renderReady = () => {
     const commentPreview = getCommentHtml();

+ 20 - 0
apps/app/src/stores/comment.tsx

@@ -5,6 +5,8 @@ import { apiGet, apiPost } from '~/client/util/apiv1-client';
 
 import { ICommentHasIdList, ICommentPostArgs } from '../interfaces/comment';
 
+import { useStaticSWR } from './use-static-swr';
+
 type IResponseComment = {
   comments: ICommentHasIdList,
   ok: boolean,
@@ -62,3 +64,21 @@ export const useSWRxPageComment = (pageId: Nullable<string>): SWRResponse<IComme
     post,
   };
 };
+
+type EditingCommentsNumOperation = {
+  increment(): Promise<number | undefined>,
+  decrement(): Promise<number | undefined>,
+}
+
+export const useSWRxEditingCommentsNum = (): SWRResponse<number, Error> & EditingCommentsNumOperation => {
+  const swrResponse = useStaticSWR<number, Error>('editingCommentsNum', undefined, { fallbackData: 0 });
+
+  return {
+    ...swrResponse,
+    increment: () => swrResponse.mutate((swrResponse.data ?? 0) + 1),
+    decrement: () => {
+      const newValue = (swrResponse.data ?? 0) - 1;
+      return swrResponse.mutate(Math.max(0, newValue));
+    },
+  };
+};