DeleteCommentModal.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import React from 'react';
  2. import { isPopulated } from '@growi/core';
  3. import { UserPicture } from '@growi/ui/dist/components';
  4. import { format } from 'date-fns';
  5. import { t } from 'i18next';
  6. import { useTranslation } from 'next-i18next';
  7. import {
  8. Button, Modal, ModalHeader, ModalBody, ModalFooter,
  9. } from 'reactstrap';
  10. import type { ICommentHasId } from '../../interfaces/comment';
  11. import { Username } from '../User/Username';
  12. import styles from './DeleteCommentModal.module.scss';
  13. export type DeleteCommentModalProps = {
  14. isShown: boolean,
  15. comment: ICommentHasId | null,
  16. errorMessage: string,
  17. cancelToDelete: () => void,
  18. confirmToDelete: () => void,
  19. }
  20. export const DeleteCommentModal = (props: DeleteCommentModalProps): JSX.Element => {
  21. const {
  22. isShown, comment, errorMessage, cancelToDelete, confirmToDelete,
  23. } = props;
  24. const { t } = useTranslation();
  25. const headerContent = () => {
  26. if (comment == null || isShown === false) {
  27. return <></>;
  28. }
  29. return (
  30. <span>
  31. <span className="material-symbols-outlined">delete_forever</span>
  32. {t('page_comment.delete_comment')}
  33. </span>
  34. );
  35. };
  36. const bodyContent = () => {
  37. if (comment == null || isShown === false) {
  38. return <></>;
  39. }
  40. // the threshold for omitting body
  41. const OMIT_BODY_THRES = 400;
  42. const commentDate = format(new Date(comment.createdAt), 'yyyy/MM/dd HH:mm');
  43. const creator = isPopulated(comment.creator) ? comment.creator : undefined;
  44. let commentBody = comment.comment;
  45. if (commentBody.length > OMIT_BODY_THRES) { // omit
  46. commentBody = `${commentBody.substr(0, OMIT_BODY_THRES)}...`;
  47. }
  48. const commentBodyElement = <span style={{ whiteSpace: 'pre-wrap' }}>{commentBody}</span>;
  49. return (
  50. <>
  51. <UserPicture user={creator} size="xs" /> <strong className="me-2"><Username user={creator}></Username></strong>{commentDate}:
  52. <p className="card custom-card comment-body mt-2 p-2">{commentBodyElement}</p>
  53. </>
  54. );
  55. };
  56. const footerContent = () => {
  57. if (comment == null || isShown === false) {
  58. return <></>;
  59. }
  60. return (
  61. <>
  62. <span className="text-danger">{errorMessage}</span>&nbsp;
  63. <Button onClick={cancelToDelete}>{t('Cancel')}</Button>
  64. <Button color="danger" onClick={confirmToDelete}>
  65. <span className="material-symbols-outlined">delete_forever</span>
  66. {t('Delete')}
  67. </Button>
  68. </>
  69. );
  70. };
  71. return (
  72. <Modal isOpen={isShown} toggle={cancelToDelete} className={`${styles['page-comment-delete-modal']}`}>
  73. <ModalHeader tag="h4" toggle={cancelToDelete} className="bg-danger text-light">
  74. {headerContent()}
  75. </ModalHeader>
  76. <ModalBody>
  77. {bodyContent()}
  78. </ModalBody>
  79. <ModalFooter>
  80. {footerContent()}
  81. </ModalFooter>
  82. </Modal>
  83. );
  84. };