From bbdc6586b70c7f2f2aca0a9591009590d4a82c88 Mon Sep 17 00:00:00 2001 From: Eric Olkowski Date: Mon, 24 Apr 2023 14:22:42 -0400 Subject: [PATCH 1/2] feat(MultiFileUpload): added event param to onFileDrop --- .../MultipleFileUpload/MultipleFileUpload.tsx | 6 ++--- .../examples/MultipleFileUploadBasic.tsx | 3 ++- .../MultipleFileUploadRejectedFile.tsx | 25 ++++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUpload.tsx b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUpload.tsx index 6d895828f7c..82a09edb0f0 100644 --- a/packages/react-core/src/components/MultipleFileUpload/MultipleFileUpload.tsx +++ b/packages/react-core/src/components/MultipleFileUpload/MultipleFileUpload.tsx @@ -18,7 +18,7 @@ export interface MultipleFileUploadProps extends Omit void; + onFileDrop?: (event: DropEvent, data: File[]) => void; } export const MultipleFileUploadContext = React.createContext({ @@ -34,7 +34,7 @@ export const MultipleFileUpload: React.FunctionComponent { const onDropAccepted = (acceptedFiles: File[], event: DropEvent) => { - onFileDrop(acceptedFiles); + onFileDrop(event, acceptedFiles); // allow users to set a custom drop accepted handler rather than using on data change dropzoneProps.onDropAccepted && dropzoneProps.onDropAccepted(acceptedFiles, event); }; @@ -47,7 +47,7 @@ export const MultipleFileUpload: React.FunctionComponent event.preventDefault() // Prevents clicking TextArea from opening file dialog + onClick: (event) => event.preventDefault() // Prevents clicking TextArea from opening file dialog }); return ( diff --git a/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUploadBasic.tsx b/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUploadBasic.tsx index c05b8992ef7..275bf04b13c 100644 --- a/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUploadBasic.tsx +++ b/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUploadBasic.tsx @@ -8,6 +8,7 @@ import { HelperText, HelperTextItem } from '@patternfly/react-core'; +import { DropEvent } from 'react-dropzone'; import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; interface readFile { @@ -68,7 +69,7 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => { }; // callback that will be called by the react dropzone with the newly dropped file objects - const handleFileDrop = (droppedFiles: File[]) => { + const handleFileDrop = (_event: DropEvent, droppedFiles: File[]) => { // identify what, if any, files are re-uploads of already uploaded files const currentFileNames = currentFiles.map((file) => file.name); const reUploads = droppedFiles.filter((droppedFile) => currentFileNames.includes(droppedFile.name)); diff --git a/packages/react-core/src/demos/examples/MultipleFileUpload/MultipleFileUploadRejectedFile.tsx b/packages/react-core/src/demos/examples/MultipleFileUpload/MultipleFileUploadRejectedFile.tsx index c937027ee56..dc25d33b999 100644 --- a/packages/react-core/src/demos/examples/MultipleFileUpload/MultipleFileUploadRejectedFile.tsx +++ b/packages/react-core/src/demos/examples/MultipleFileUpload/MultipleFileUploadRejectedFile.tsx @@ -8,6 +8,7 @@ import { Modal, Checkbox } from '@patternfly/react-core'; +import { DropEvent } from 'react-dropzone'; import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; interface readFile { @@ -34,7 +35,7 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => { React.useEffect(() => { if (readFileData.length < currentFiles.length) { setStatusIcon('inProgress'); - } else if (readFileData.every(file => file.loadResult === 'success')) { + } else if (readFileData.every((file) => file.loadResult === 'success')) { setStatusIcon('success'); } else { setStatusIcon('danger'); @@ -44,39 +45,39 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => { // remove files from both state arrays based on their name const removeFiles = (namesOfFilesToRemove: string[]) => { const newCurrentFiles = currentFiles.filter( - currentFile => !namesOfFilesToRemove.some(fileName => fileName === currentFile.name) + (currentFile) => !namesOfFilesToRemove.some((fileName) => fileName === currentFile.name) ); setCurrentFiles(newCurrentFiles); const newReadFiles = readFileData.filter( - readFile => !namesOfFilesToRemove.some(fileName => fileName === readFile.fileName) + (readFile) => !namesOfFilesToRemove.some((fileName) => fileName === readFile.fileName) ); setReadFileData(newReadFiles); }; // callback that will be called by the react dropzone with the newly dropped file objects - const handleFileDrop = (droppedFiles: File[]) => { + const handleFileDrop = (_event: DropEvent, droppedFiles: File[]) => { // identify what, if any, files are re-uploads of already uploaded files - const currentFileNames = currentFiles.map(file => file.name); - const reUploads = droppedFiles.filter(droppedFile => currentFileNames.includes(droppedFile.name)); + const currentFileNames = currentFiles.map((file) => file.name); + const reUploads = droppedFiles.filter((droppedFile) => currentFileNames.includes(droppedFile.name)); /** this promise chain is needed because if the file removal is done at the same time as the file adding react * won't realize that the status items for the re-uploaded files needs to be re-rendered */ Promise.resolve() - .then(() => removeFiles(reUploads.map(file => file.name))) - .then(() => setCurrentFiles(prevFiles => [...prevFiles, ...droppedFiles])); + .then(() => removeFiles(reUploads.map((file) => file.name))) + .then(() => setCurrentFiles((prevFiles) => [...prevFiles, ...droppedFiles])); }; // callback called by the status item when a file is successfully read with the built-in file reader const handleReadSuccess = (data: string, file: File) => { - setReadFileData(prevReadFiles => [...prevReadFiles, { data, fileName: file.name, loadResult: 'success' }]); + setReadFileData((prevReadFiles) => [...prevReadFiles, { data, fileName: file.name, loadResult: 'success' }]); }; // callback called by the status item when a file encounters an error while being read with the built-in file reader const handleReadFail = (error: DOMException, file: File) => { - setReadFileData(prevReadFiles => [ + setReadFileData((prevReadFiles) => [ ...prevReadFiles, { loadError: error, fileName: file.name, loadResult: 'danger' } ]); @@ -95,7 +96,7 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => { } }; - const successfullyReadFileCount = readFileData.filter(fileData => fileData.loadResult === 'success').length; + const successfullyReadFileCount = readFileData.filter((fileData) => fileData.loadResult === 'success').length; return ( <> @@ -123,7 +124,7 @@ export const MultipleFileUploadBasic: React.FunctionComponent = () => { statusToggleText={`${successfullyReadFileCount} of ${currentFiles.length} files uploaded`} statusToggleIcon={statusIcon} > - {currentFiles.map(file => ( + {currentFiles.map((file) => ( Date: Tue, 2 May 2023 11:59:01 -0400 Subject: [PATCH 2/2] Added documentation for react-dropzone types --- .../examples/MultipleFileUpload.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUpload.md b/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUpload.md index 9761a6d6b29..a141651c4ca 100644 --- a/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUpload.md +++ b/packages/react-core/src/components/MultipleFileUpload/examples/MultipleFileUpload.md @@ -50,4 +50,18 @@ The "Show as horizontal" checkbox can be used to easily toggle the `isHorizontal The "Demonstrate error reporting by forcing uploads to fail" checkbox shows how our `progressHelperText` prop can be used to provide status messages to users, such as when a file fails to upload. While this checkbox is checked it will cause any file uploaded to automatically fail the file reading process, and helper text will be dynamically rendered which informs the user of that error. ```ts file="./MultipleFileUploadBasic.tsx" + ``` + +## Types + +Multiple file upload uses both the `DropEvent` and `DropzoneOptions` types from react-dropzone. The `DropEvent` type is a union comprised of the following types: + +```noLive + React.DragEvent + | React.ChangeEvent + | DragEvent + | Event +``` + +`DropzoneOptions` is comprised of additional props with their own types. For more information on using `DropzoneOptions` visit [react-dropzone props and methods](https://react-dropzone.js.org/#src).