From bdf65a2812e55ccb88777d361c4e285b132c7309 Mon Sep 17 00:00:00 2001 From: Lucy Jemutai Date: Thu, 19 Dec 2024 11:44:52 +0300 Subject: [PATCH] Enable Deleting or Clearing Files in File Picker Component in Edit Mode --- src/components/inputs/file/file.component.tsx | 50 +++++++++++++- src/components/inputs/file/file.scss | 65 +++++++++++++++++-- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/components/inputs/file/file.component.tsx b/src/components/inputs/file/file.component.tsx index c4abe4a4d..f0a3933f7 100644 --- a/src/components/inputs/file/file.component.tsx +++ b/src/components/inputs/file/file.component.tsx @@ -3,13 +3,14 @@ import { FileUploader, Button } from '@carbon/react'; import { useTranslation } from 'react-i18next'; import { isTrue } from '../../../utils/boolean-utils'; import Camera from './camera/camera.component'; -import { Close, DocumentPdf } from '@carbon/react/icons'; +import { Close, DocumentPdf, TrashCan } from '@carbon/react/icons'; import styles from './file.scss'; import { type FormFieldInputProps } from '../../../types'; import { useFormProviderContext } from '../../../provider/form-provider'; import { isViewMode } from '../../../utils/common-utils'; import FieldValueView from '../../value/view/field-value-view.component'; import FieldLabel from '../../field-label/field-label.component'; +import { deleteAttachmentPermanently, showSnackbar, useAbortController } from '@openmrs/esm-framework'; type DataSourceType = 'filePicker' | 'camera' | null; @@ -20,6 +21,34 @@ const File: React.FC = ({ field, value, setFieldValue }) => const [dataSource, setDataSource] = useState(null); const { sessionMode } = useFormProviderContext(); + const abortController = useAbortController(); + + const handleDeleteAttachment = useCallback(() => { + if (value && value.id) { + deleteAttachmentPermanently(value.id, abortController) + .then(() => { + setFieldValue(null); + showSnackbar({ + title: t('fileDeleted', 'File deleted'), + subtitle: t('successfullyDeleted', 'File successfully deleted'), + kind: 'success', + isLowContrast: true, + }); + }) + .catch((error) => { + if (error.name !== 'AbortError') { + showSnackbar({ + title: t('error', 'Error'), + subtitle: t('failedDeleting', "File couldn't be deleted"), + kind: 'error', + }); + } + }); + } else { + setFieldValue(null); + } + }, [value, setFieldValue, t, abortController]); + const labelDescription = useMemo(() => { return field.questionOptions.allowedFileTypes ? t( @@ -87,6 +116,25 @@ const File: React.FC = ({ field, value, setFieldValue }) => {t('cameraCapture', 'Camera capture')} + {value && !isViewMode(sessionMode) && ( +
+ {(Array.isArray(value) ? value : [value]).map((file, index) => ( +
+ {file.bytesContentFamily === 'PDF' ? ( +
+ +
+ ) : ( + file.src && Preview + )} +
+ {t('clearFile', 'Clear file')} + +
+
+ ))} +
+ )} {!dataSource && value && (
diff --git a/src/components/inputs/file/file.scss b/src/components/inputs/file/file.scss index 06eacfcf5..adeb452a2 100644 --- a/src/components/inputs/file/file.scss +++ b/src/components/inputs/file/file.scss @@ -28,10 +28,7 @@ display: flex; align-items: center; margin-bottom: 1rem; -} - -.selectorButton { - margin-right: 1rem; + flex-wrap: wrap; } .caption { @@ -90,6 +87,66 @@ padding: 1rem; } +.selectorButton { + margin-right: 1rem; + margin-bottom: 0.5rem; +} + +.attachmentContainer { + display: flex; + flex-wrap: wrap; + gap: 1rem; +} + +.trashCanContainer { + position: relative; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} + +.trashIcon { + font-size: 20px; + color: red; + transition: transform 0.3s ease; +} + +.trashIcon:hover { + transform: scale(1.2); +} +.trashTooltip { + position: absolute; + bottom: 30px; + left: 50%; + transform: translateX(-50%); + background-color: #333; + color: white; + padding: 5px 10px; + border-radius: 4px; + font-size: 12px; + white-space: nowrap; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease-in-out; +} + +.trashCanContainer:hover .trashTooltip { + opacity: 1; + visibility: visible; +} + +.attachmentPreview { + position: relative; + display: inline-block; +} + +.attachmentPreview img { + max-width: 200px; + border: 1px solid #ccc; + border-radius: 8px; +} + .pdfThumbnail { cursor: pointer; background-color: gray;