Files
frontend-app-authoring/src/generic/modal-dropzone/useModalDropzone.jsx
vladislavkeblysh 65f45f72f0 feat: [FC-0044] Textbooks Page (#890)
Implement Textbooks page.

---------

Co-authored-by: Glib Glugovskiy <glib.glugovskiy@raccoongang.com>
2024-04-30 18:38:43 -03:00

132 lines
3.6 KiB
JavaScript

import { useState, useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { useIntl } from '@edx/frontend-platform/i18n';
import { RequestStatus } from '../../data/constants';
import { uploadAssets } from './data/api';
import messages from './messages';
const useModalDropzone = ({
onChange, onCancel, onClose, fileTypes, onSavingStatus, onSelectFile,
}) => {
const { courseId } = useParams();
const intl = useIntl();
const [selectedFile, setSelectedFile] = useState(null);
const [previewUrl, setPreviewUrl] = useState(null);
const [uploadProgress, setUploadProgress] = useState(0);
const [disabledUploadBtn, setDisabledUploadBtn] = useState(true);
const VALID_IMAGE_TYPES = ['png', 'jpeg'];
const imageValidator = (file) => {
const fileType = file.name.split('.').pop().toLowerCase();
const extensionsList = fileTypes.map(type => `.${type.toLowerCase()}`).join(', ');
const typesList = fileTypes.map(type => type.toUpperCase()).join(', ');
if (!fileTypes.map(type => type.toLowerCase()).includes(fileType)) {
return intl.formatMessage(messages.uploadImageValidationText, {
types: typesList,
extensions: extensionsList,
});
}
return null;
};
/**
* Constructs an accept object for Dropzone based on provided file types.
*
* @param {string[]} types - Array of file extensions.
* @returns {Object} Accept object for Dropzone.
*
* Example:
* input: ['png', 'jpg', 'pdf', 'docx']
* output:
* {
* "image/*": [".png", ".jpg"],
* "* /*": [".pdf", ".docx"]
* }
*/
const constructAcceptObject = (types) => types
.reduce((acc, type) => {
// eslint-disable-next-line no-nested-ternary
const mimeType = type === 'pdf' ? 'application/pdf' : VALID_IMAGE_TYPES.includes(type) ? 'image/*' : '*/*';
if (!acc[mimeType]) {
acc[mimeType] = [];
}
acc[mimeType].push(`.${type}`);
return acc;
}, {});
const accept = useMemo(() => constructAcceptObject(fileTypes), [fileTypes]);
const handleSelectFile = ({ fileData }) => {
const file = fileData.get('file');
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setPreviewUrl(reader.result);
setDisabledUploadBtn(false);
};
reader.readAsDataURL(file);
setSelectedFile(fileData);
if (onSelectFile) {
onSelectFile(file.path);
}
}
};
const handleCancel = () => {
setPreviewUrl(null);
setDisabledUploadBtn(true);
onSavingStatus({ status: RequestStatus.CLEAR });
setUploadProgress(0);
onCancel();
onClose();
};
const handleUpload = async () => {
if (!selectedFile) { return; }
onSavingStatus(RequestStatus.PENDING);
const onUploadProgress = (progressEvent) => {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
setUploadProgress(percentCompleted);
};
try {
const response = await uploadAssets(courseId, selectedFile, onUploadProgress);
const { url } = response.asset;
if (url) {
onChange(url);
onSavingStatus({ status: RequestStatus.SUCCESSFUL });
onClose();
}
} catch (error) {
onSavingStatus({ status: RequestStatus.FAILED });
} finally {
setDisabledUploadBtn(true);
setUploadProgress(0);
setPreviewUrl(null);
}
};
return {
intl,
accept,
uploadProgress,
previewUrl,
disabledUploadBtn,
handleSelectFile,
imageValidator,
handleCancel,
handleUpload,
};
};
export default useModalDropzone;