mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-05 22:38:48 +00:00
[Improvement] Filepicker widget : The file picker should reject files with existing file names. (#3046)
* fixes: multiple files with same file name can be uploaded * removes unwanted logs * compare file paths for validating existing selected files * disable picker if max count is reched * fixes loading spinner postions * max file count for single selection * disables the dropzone on max count only when multiple is true * show max count msg for dnd file to the dropzone * clean up * check already selectedFile count with max file count on adding new files * reverts accepted file data for singly selected files * Remove validation for existing files on filepicker Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com>
This commit is contained in:
parent
caf68b10e8
commit
9da311c68f
1 changed files with 53 additions and 11 deletions
|
|
@ -77,17 +77,21 @@ export const FilePicker = ({
|
|||
borderColor: '#ff1744',
|
||||
};
|
||||
|
||||
const [disablePicker, setDisablePicker] = React.useState(false);
|
||||
|
||||
const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject, acceptedFiles, fileRejections } =
|
||||
useDropzone({
|
||||
accept: parsedFileType,
|
||||
noClick: !parsedEnablePicker,
|
||||
noDrag: !parsedEnableDropzone,
|
||||
noClick: !parsedEnablePicker || disablePicker,
|
||||
noDrag: !parsedEnableDropzone || disablePicker,
|
||||
noKeyboard: true,
|
||||
maxFiles: parsedMaxFileCount,
|
||||
minSize: parsedMinSize,
|
||||
maxSize: parsedMaxSize,
|
||||
multiple: parsedEnableMultiple,
|
||||
disabled: parsedDisabledState,
|
||||
disabled: disablePicker,
|
||||
validator: validateFileExists,
|
||||
onDropRejected: () => (selectedFiles.length > 0 ? setShowSelectedFiles(true) : setShowSelectedFiles(false)),
|
||||
onFileDialogCancel: () => (selectedFiles.length > 0 ? setShowSelectedFiles(true) : setShowSelectedFiles(false)),
|
||||
});
|
||||
|
||||
|
|
@ -106,6 +110,30 @@ export const FilePicker = ({
|
|||
const [showSelectedFiles, setShowSelectedFiles] = React.useState(false);
|
||||
const [selectedFiles, setSelectedFiles] = React.useState([]);
|
||||
|
||||
//* custom validator
|
||||
function validateFileExists(_file) {
|
||||
const selectedFilesCount = selectedFiles.length;
|
||||
|
||||
if (selectedFilesCount === parsedMaxFileCount) {
|
||||
return {
|
||||
code: 'max_file_count_reached',
|
||||
message: `Max file count reached`,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (parsedDisabledState) setDisablePicker(true);
|
||||
|
||||
if (selectedFiles.length === parsedMaxFileCount && parsedEnableMultiple) {
|
||||
setDisablePicker(true);
|
||||
} else {
|
||||
setDisablePicker(false);
|
||||
}
|
||||
}, [selectedFiles.length, parsedDisabledState, parsedMaxFileCount, parsedEnableMultiple]);
|
||||
|
||||
/**
|
||||
* *getFileData()
|
||||
* @param {*} file
|
||||
|
|
@ -152,6 +180,7 @@ export const FilePicker = ({
|
|||
dataURL: readFileAsDataURL, // TODO: Fix dataURL to have correct format
|
||||
base64Data: readFileAsDataURL,
|
||||
parsedData: shouldProcessFileParsing ? await processFileContent(file.type, readFileAsText) : null,
|
||||
filePath: file.path,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -202,7 +231,9 @@ export const FilePicker = ({
|
|||
acceptedFiles.map((acceptedFile) => {
|
||||
const acceptedFileData = fileReader(acceptedFile);
|
||||
acceptedFileData.then((data) => {
|
||||
fileData.push(data);
|
||||
if (fileData.length < parsedMaxFileCount) {
|
||||
fileData.push(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
setSelectedFiles(fileData);
|
||||
|
|
@ -226,8 +257,10 @@ export const FilePicker = ({
|
|||
}
|
||||
|
||||
return () => {
|
||||
if (selectedFiles.length === 0) {
|
||||
setShowSelectedFiles(false);
|
||||
}
|
||||
setAccepted(false);
|
||||
setShowSelectedFiles(false);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -255,8 +288,8 @@ export const FilePicker = ({
|
|||
<input {...getInputProps()} />
|
||||
<FilePicker.Signifiers signifier={accepted} feedback={null} cls="spinner-border text-azure p-0" />
|
||||
|
||||
{showSelectedFiles ? (
|
||||
<FilePicker.AcceptedFiles width={width - 10} height={height} showFilezone={setShowSelectedFiles}>
|
||||
{showSelectedFiles && !accepted ? (
|
||||
<FilePicker.AcceptedFiles width={width - 10} height={height}>
|
||||
{selectedFiles.map((acceptedFile, index) => (
|
||||
<>
|
||||
<div key={index} className="col-10">
|
||||
|
|
@ -288,7 +321,16 @@ export const FilePicker = ({
|
|||
/>
|
||||
)}
|
||||
|
||||
<FilePicker.Signifiers signifier={isDragAccept} feedback={'All files will be accepted'} cls="text-lime mt-3" />
|
||||
<FilePicker.Signifiers
|
||||
signifier={isDragAccept && !(selectedFiles.length === parsedMaxFileCount)}
|
||||
feedback={'All files will be accepted'}
|
||||
cls="text-lime mt-3"
|
||||
/>
|
||||
<FilePicker.Signifiers
|
||||
signifier={isDragAccept && selectedFiles.length === parsedMaxFileCount}
|
||||
feedback={'Max file reached!'}
|
||||
cls="text-red mt-3"
|
||||
/>
|
||||
|
||||
<FilePicker.Signifiers signifier={isDragReject} feedback={'Files will be rejected!'} cls="text-red mt-3" />
|
||||
</div>
|
||||
|
|
@ -298,13 +340,13 @@ export const FilePicker = ({
|
|||
|
||||
FilePicker.Signifiers = ({ signifier, feedback, cls }) => {
|
||||
if (signifier) {
|
||||
return <>{feedback === null ? <div className={cls}></div> : <p className={cls}>{feedback}</p>}</>;
|
||||
return <>{feedback === null ? <center className={cls}></center> : <p className={cls}>{feedback}</p>}</>;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
FilePicker.AcceptedFiles = ({ children, width, height, showFilezone }) => {
|
||||
FilePicker.AcceptedFiles = ({ children, width, height }) => {
|
||||
const styles = {
|
||||
color: '#bdbdbd',
|
||||
outline: 'none',
|
||||
|
|
@ -316,7 +358,7 @@ FilePicker.AcceptedFiles = ({ children, width, height, showFilezone }) => {
|
|||
height,
|
||||
};
|
||||
return (
|
||||
<aside style={styles} onClick={() => showFilezone(false)}>
|
||||
<aside style={styles}>
|
||||
<span className="text-info">Files</span>
|
||||
<div className="row accepted-files">{children}</div>
|
||||
</aside>
|
||||
|
|
|
|||
Loading…
Reference in a new issue