jam411 3 лет назад
Родитель
Сommit
d3ae9bdb09

+ 7 - 10
packages/app/src/components/PageComment.tsx

@@ -8,6 +8,7 @@ import { Button } from 'reactstrap';
 import { toastError } from '~/client/util/apiNotification';
 import { apiPost } from '~/client/util/apiv1-client';
 import { useCurrentPagePath } from '~/stores/context';
+import { useDeleteCommentModal } from '~/stores/modal';
 import { useSWRxCurrentPage } from '~/stores/page';
 import { useCommentPreviewOptions } from '~/stores/renderer';
 
@@ -17,14 +18,11 @@ import { useSWRxPageComment } from '../stores/comment';
 import { Comment } from './PageComment/Comment';
 import { CommentEditorProps } from './PageComment/CommentEditor';
 import { CommentEditorLazyRenderer } from './PageComment/CommentEditorLazyRenderer';
-import { DeleteCommentModalProps } from './PageComment/DeleteCommentModal';
+import { DeleteCommentModal } from './PageComment/DeleteCommentModal';
 import { ReplyComments } from './PageComment/ReplyComments';
 
 import styles from './PageComment.module.scss';
 
-const DeleteCommentModal = dynamic<DeleteCommentModalProps>(
-  () => import('./PageComment/DeleteCommentModal').then(mod => mod.DeleteCommentModal), { ssr: false },
-);
 // TODO: Update Skelton
 const CommentEditor = dynamic<CommentEditorProps>(() => import('./PageComment/CommentEditor').then(mod => mod.CommentEditor), { ssr: false });
 
@@ -43,6 +41,7 @@ export const PageComment: FC<PageCommentProps> = memo((props:PageCommentProps):
     pageId, highlightKeywords, isReadOnly, titleAlign, hideIfEmpty,
   } = props;
 
+  const { open: openDeleteCommentModal, close: closeDeleteCommentModal } = useDeleteCommentModal();
   const { data: comments, mutate } = useSWRxPageComment(pageId);
   const { data: rendererOptions } = useCommentPreviewOptions();
   const { data: currentPage } = useSWRxCurrentPage();
@@ -93,13 +92,13 @@ export const PageComment: FC<PageCommentProps> = memo((props:PageCommentProps):
 
   const onClickDeleteButton = useCallback((comment: ICommentHasId) => {
     setCommentToBeDeleted(comment);
-    setIsDeleteConfirmModalShown(true);
-  }, []);
+    openDeleteCommentModal();
+  }, [openDeleteCommentModal]);
 
   const onCancelDeleteComment = useCallback(() => {
     setCommentToBeDeleted(null);
-    setIsDeleteConfirmModalShown(false);
-  }, []);
+    closeDeleteCommentModal();
+  }, [closeDeleteCommentModal]);
 
   const onDeleteCommentAfterOperation = useCallback(() => {
     onCancelDeleteComment();
@@ -230,10 +229,8 @@ export const PageComment: FC<PageCommentProps> = memo((props:PageCommentProps):
       </div>
       {(!isReadOnly && commentToBeDeleted != null) && (
         <DeleteCommentModal
-          isShown={isDeleteConfirmModalShown}
           comment={commentToBeDeleted}
           errorMessage={errorMessageOnDelete}
-          cancel={onCancelDeleteComment}
           confirmedToDelete={onDeleteComment}
         />
       )}

+ 36 - 26
packages/app/src/components/PageComment/DeleteCommentModal.tsx

@@ -6,61 +6,71 @@ import {
   Button, Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
 
+import { useDeleteCommentModal } from '~/stores/modal';
+
 import { ICommentHasId } from '../../interfaces/comment';
 import Username from '../User/Username';
 
 import styles from './DeleteCommentModal.module.scss';
 
 
-export type DeleteCommentModalProps = {
-  isShown: boolean,
+type DeleteCommentModalProps = {
   comment: ICommentHasId,
   errorMessage: string,
-  cancel: () => void, // for cancel evnet handling
   confirmedToDelete: () => void, // for confirmed event handling
 }
 
 export const DeleteCommentModal = (props: DeleteCommentModalProps): JSX.Element => {
 
   const {
-    isShown, comment, errorMessage, cancel, confirmedToDelete,
+    confirmedToDelete,
   } = props;
 
+  const { data: status, close } = useDeleteCommentModal();
+
+  if (status == null || status.comment == null) {
+    return <></>;
+  }
+
   /*
    * the threshold for omitting body
    */
   const OMIT_BODY_THRES = 400;
 
-  const commentDate = format(new Date(comment.createdAt), 'yyyy/MM/dd HH:mm');
+  const commentDate = format(new Date(status.comment.createdAt), 'yyyy/MM/dd HH:mm');
 
   // generate body
-  let commentBody = comment.comment;
+  let commentBody = status.comment.comment;
   if (commentBody.length > OMIT_BODY_THRES) { // omit
     commentBody = `${commentBody.substr(0, OMIT_BODY_THRES)}...`;
   }
   const commentBodyElement = <span style={{ whiteSpace: 'pre-wrap' }}>{commentBody}</span>;
 
   return (
-    <Modal isOpen={isShown} toggle={cancel} className={`${styles['page-comment-delete-modal']}`}>
-      <ModalHeader tag="h4" toggle={cancel} className="bg-danger text-light">
-        <span>
-          <i className="icon-fw icon-fire"></i>
-          Delete comment?
-        </span>
-      </ModalHeader>
-      <ModalBody>
-        <UserPicture user={comment.creator} size="xs" /> <strong><Username user={comment.creator}></Username></strong> wrote on {commentDate}:
-        <p className="card well comment-body mt-2 p-2">{commentBodyElement}</p>
-      </ModalBody>
-      <ModalFooter>
-        <span className="text-danger">{errorMessage}</span>&nbsp;
-        <Button onClick={cancel}>Cancel</Button>
-        <Button color="danger" onClick={confirmedToDelete}>
-          <i className="icon icon-fire"></i>
-          Delete
-        </Button>
-      </ModalFooter>
-    </Modal>
+    <>
+      { status != null && (
+        <Modal isOpen={status.isOpened} toggle={close} className={`${styles['page-comment-delete-modal']}`}>
+          <ModalHeader tag="h4" toggle={close} className="bg-danger text-light">
+            <span>
+              <i className="icon-fw icon-fire"></i>
+              Delete comment?
+            </span>
+          </ModalHeader>
+          <ModalBody>
+            <UserPicture user={status.comment.creator} size="xs" /> <strong><Username user={status.comment.creator}></Username></strong> wrote on {commentDate}:
+            <p className="card well comment-body mt-2 p-2">{commentBodyElement}</p>
+          </ModalBody>
+          <ModalFooter>
+            <span className="text-danger">{status.errorMessage}</span>&nbsp;
+            <Button onClick={close}>Cancel</Button>
+            <Button color="danger" onClick={confirmedToDelete}>
+              <i className="icon icon-fire"></i>
+              Delete
+            </Button>
+          </ModalFooter>
+        </Modal>
+      )}
+    </>
   );
 
 };

+ 48 - 0
packages/app/src/stores/modal.tsx

@@ -1,11 +1,13 @@
 import { SWRResponse } from 'swr';
 
+import { ICommentHasId } from '~/interfaces/comment';
 import { IPageToDeleteWithMeta, IPageToRenameWithMeta } from '~/interfaces/page';
 import {
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction,
 } from '~/interfaces/ui';
 import { IUserGroupHasId } from '~/interfaces/user';
 
+
 import { useStaticSWR } from './use-static-swr';
 
 
@@ -438,3 +440,49 @@ export const useShortcutsModal = (): SWRResponse<ShortcutsModalStatus, Error> &
     },
   };
 };
+
+/*
+  * DeleteCommentModal
+  */
+export type IDeleteCommentModal = {
+  comment: string,
+  errorMessage: string,
+}
+
+export type IDeleteCommentModalOption = {
+  onDeleteComment?: () => void,
+}
+
+type DeleteCommentModalStatus = {
+  isOpened: boolean,
+  comment?: ICommentHasId,
+  errorMessage?: IDeleteCommentModal,
+  opts?: IDeleteCommentModalOption,
+}
+
+type DeleteCommentModalUtils = {
+  open(
+    comment?: ICommentHasId,
+    errorMessage?: IDeleteCommentModal,
+    opts?: IDeleteCommentModalOption,
+  ): Promise<DeleteCommentModalStatus | undefined>,
+  close(): Promise<DeleteCommentModalStatus | undefined>,
+}
+
+export const useDeleteCommentModal = (status?: DeleteCommentModalStatus): SWRResponse<DeleteCommentModalStatus, Error> & DeleteCommentModalUtils => {
+  const initialStatus: DeleteCommentModalStatus = {
+    isOpened: false,
+  };
+  const swrResponse = useStaticSWR<DeleteCommentModalStatus, Error>('deleteCommentModal', status, { fallbackData: initialStatus });
+  return {
+    ...swrResponse,
+    open: (
+        comment?: ICommentHasId,
+        errorMessage?: IDeleteCommentModal,
+        opts?: IDeleteCommentModalOption,
+    ) => swrResponse.mutate({
+      isOpened: true, comment, errorMessage, opts,
+    }),
+    close: () => swrResponse.mutate({ isOpened: false }),
+  };
+};