DeleteAttachmentModal.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* eslint-disable react/prop-types */
  2. import React, { useCallback } from 'react';
  3. import { HasObjectId, IAttachment } from '@growi/core';
  4. import { UserPicture } from '@growi/ui';
  5. import {
  6. Button,
  7. Modal, ModalHeader, ModalBody, ModalFooter,
  8. } from 'reactstrap';
  9. import { Username } from '../User/Username';
  10. import styles from './DeleteAttachmentModal.module.scss';
  11. function iconNameByFormat(format: string): string {
  12. if (format.match(/image\/.+/i)) {
  13. return 'icon-picture';
  14. }
  15. return 'icon-doc';
  16. }
  17. type Props = {
  18. isOpen: boolean,
  19. toggle: () => void,
  20. attachmentToDelete: IAttachment & HasObjectId | null,
  21. deleting: boolean,
  22. deleteError: string,
  23. onAttachmentDeleteClickedConfirm?: (attachment: IAttachment & HasObjectId) => Promise<void>,
  24. }
  25. export const DeleteAttachmentModal = (props: Props): JSX.Element => {
  26. const {
  27. isOpen, toggle,
  28. attachmentToDelete, deleting, deleteError,
  29. onAttachmentDeleteClickedConfirm,
  30. } = props;
  31. const onDeleteConfirm = useCallback(() => {
  32. if (attachmentToDelete == null || onAttachmentDeleteClickedConfirm == null) {
  33. return;
  34. }
  35. onAttachmentDeleteClickedConfirm(attachmentToDelete);
  36. }, [attachmentToDelete, onAttachmentDeleteClickedConfirm]);
  37. const renderByFileFormat = useCallback((attachment) => {
  38. const content = (attachment.fileFormat.match(/image\/.+/i))
  39. // eslint-disable-next-line @next/next/no-img-element
  40. ? <img src={attachment.filePathProxied} alt="deleting image" />
  41. : '';
  42. return (
  43. <div className="attachment-delete-image">
  44. <p>
  45. <i className={iconNameByFormat(attachment.fileFormat)}></i> {attachment.originalName}
  46. </p>
  47. <p>
  48. uploaded by <UserPicture user={attachment.creator} size="sm"></UserPicture> <Username user={attachment.creator}></Username>
  49. </p>
  50. {content}
  51. </div>
  52. );
  53. }, []);
  54. let deletingIndicator = <></>;
  55. if (deleting) {
  56. deletingIndicator = <div className="speeding-wheel-sm"></div>;
  57. }
  58. if (deleteError) {
  59. deletingIndicator = <span>{deleteError}</span>;
  60. }
  61. return (
  62. <Modal
  63. isOpen={isOpen}
  64. className={`${styles['attachment-delete-modal']} attachment-delete-modal`}
  65. size="lg"
  66. aria-labelledby="contained-modal-title-lg"
  67. fade={false}
  68. >
  69. <ModalHeader tag="h4" toggle={toggle} className="bg-danger text-light">
  70. <span id="contained-modal-title-lg">Delete attachment?</span>
  71. </ModalHeader>
  72. <ModalBody>
  73. {renderByFileFormat(attachmentToDelete)}
  74. </ModalBody>
  75. <ModalFooter>
  76. <div className="mr-3 d-inline-block">
  77. {deletingIndicator}
  78. </div>
  79. <Button
  80. color="danger"
  81. onClick={onDeleteConfirm}
  82. disabled={deleting}
  83. >Delete!
  84. </Button>
  85. </ModalFooter>
  86. </Modal>
  87. );
  88. };