DeleteAttachmentModal.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import React, {
  2. useCallback, useMemo, useState,
  3. } from 'react';
  4. import type { IUser } from '@growi/core';
  5. import { UserPicture, LoadingSpinner } from '@growi/ui/dist/components';
  6. import { useTranslation } from 'next-i18next';
  7. import {
  8. Button, Modal, ModalHeader, ModalBody, ModalFooter,
  9. } from 'reactstrap';
  10. import { toastSuccess, toastError } from '~/client/util/toastr';
  11. import { useDeleteAttachmentModal } from '~/stores/modal';
  12. import loggerFactory from '~/utils/logger';
  13. import { Username } from '../User/Username';
  14. import styles from './DeleteAttachmentModal.module.scss';
  15. const logger = loggerFactory('growi:attachmentDelete');
  16. const iconByFormat = (format: string): string => {
  17. return format.match(/image\/.+/i) ? 'image' : 'description';
  18. };
  19. export const DeleteAttachmentModal: React.FC = () => {
  20. const [deleting, setDeleting] = useState<boolean>(false);
  21. const [deleteError, setDeleteError] = useState<string>('');
  22. const { t } = useTranslation();
  23. const { data: deleteAttachmentModal, close: closeDeleteAttachmentModal } = useDeleteAttachmentModal();
  24. const isOpen = deleteAttachmentModal?.isOpened;
  25. const attachment = deleteAttachmentModal?.attachment;
  26. const remove = deleteAttachmentModal?.remove;
  27. const toggleHandler = useCallback(() => {
  28. closeDeleteAttachmentModal();
  29. setDeleting(false);
  30. setDeleteError('');
  31. }, [closeDeleteAttachmentModal]);
  32. const onClickDeleteButtonHandler = useCallback(async() => {
  33. if (remove == null || attachment == null) {
  34. return;
  35. }
  36. setDeleting(true);
  37. try {
  38. await remove({ attachment_id: attachment._id });
  39. setDeleting(false);
  40. closeDeleteAttachmentModal();
  41. toastSuccess(`Delete ${attachment.originalName}`);
  42. }
  43. catch (err) {
  44. setDeleting(false);
  45. setDeleteError('Attachment could not be deleted.');
  46. toastError(err);
  47. logger.error(err);
  48. }
  49. }, [attachment, closeDeleteAttachmentModal, remove]);
  50. const attachmentFileFormat = useMemo(() => {
  51. if (attachment == null) {
  52. return;
  53. }
  54. const content = (attachment.fileFormat.match(/image\/.+/i))
  55. // eslint-disable-next-line @next/next/no-img-element
  56. ? <img src={attachment.filePathProxied} alt="deleting image" />
  57. : '';
  58. return (
  59. <div className="attachment-delete-image">
  60. <p>
  61. <span className="material-symbols-outlined">{iconByFormat(attachment.fileFormat)}</span> {attachment.originalName}
  62. </p>
  63. <p>
  64. uploaded by <UserPicture user={attachment.creator} size="sm"></UserPicture> <Username user={attachment.creator as IUser}></Username>
  65. </p>
  66. {content}
  67. </div>
  68. );
  69. }, [attachment]);
  70. const deletingIndicator = useMemo(() => {
  71. if (deleting) {
  72. return <LoadingSpinner />;
  73. }
  74. if (deleteError) {
  75. return <span>{deleteError}</span>;
  76. }
  77. return <></>;
  78. }, [deleting, deleteError]);
  79. return (
  80. <Modal
  81. isOpen={isOpen}
  82. className={`${styles['attachment-delete-modal']} attachment-delete-modal`}
  83. size="lg"
  84. aria-labelledby="contained-modal-title-lg"
  85. fade={false}
  86. >
  87. <ModalHeader tag="h4" toggle={toggleHandler} className="bg-danger text-light">
  88. <span id="contained-modal-title-lg">{t('delete_attachment_modal.confirm_delete_attachment')}</span>
  89. </ModalHeader>
  90. <ModalBody>
  91. {attachmentFileFormat}
  92. </ModalBody>
  93. <ModalFooter>
  94. <div className="me-3 d-inline-block">
  95. {deletingIndicator}
  96. </div>
  97. <Button
  98. color="danger"
  99. onClick={onClickDeleteButtonHandler}
  100. disabled={deleting}
  101. >{t('commons:Delete')}
  102. </Button>
  103. </ModalFooter>
  104. </Modal>
  105. );
  106. };