fix: simplify InputFileComponent to use native file picker (#5692)
* ✨ (index.tsx): Add useRef hook to manage file input element reference for better control over file selection process 🐛 (index.tsx): Fix handleButtonClick function to handle file selection asynchronously and provide fallback option if file selection fails 🐛 (index.tsx): Fix handleNativeInputChange function to correctly handle file selection from native file input element and reset its value after selection * 📝 (index.tsx): Remove unused createFileUpload function and simplify handleButtonClick function to trigger file input click directly ♻️ (index.tsx): Refactor input element to use Button component for better styling and consistency * 📝 (inputFileComponent/index.tsx): remove unnecessary comment in handleButtonClick function
This commit is contained in:
parent
8a4fc2c338
commit
65530e210f
1 changed files with 71 additions and 54 deletions
|
|
@ -1,8 +1,7 @@
|
|||
import { usePostUploadFile } from "@/controllers/API/queries/files/use-post-upload-file";
|
||||
import { createFileUpload } from "@/helpers/create-file-upload";
|
||||
import useFileSizeValidator from "@/shared/hooks/use-file-size-validator";
|
||||
import { cn } from "@/utils/utils";
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import {
|
||||
CONSOLE_ERROR_MSG,
|
||||
INVALID_FILE_ALERT,
|
||||
|
|
@ -24,70 +23,77 @@ export default function InputFileComponent({
|
|||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const { validateFileSize } = useFileSizeValidator(setErrorData);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// Clear component state
|
||||
useEffect(() => {
|
||||
if (disabled && value !== "") {
|
||||
handleOnNewValue({ value: "", file_path: "" }, { skipSnapshot: true });
|
||||
}
|
||||
}, [disabled, handleOnNewValue]);
|
||||
}, [disabled, handleOnNewValue, value]);
|
||||
|
||||
function checkFileType(fileName: string): boolean {
|
||||
if (fileTypes === undefined) return true;
|
||||
for (let index = 0; index < fileTypes.length; index++) {
|
||||
if (fileName.endsWith(fileTypes[index])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (!fileTypes?.length) return true;
|
||||
return fileTypes.some((type) =>
|
||||
fileName.toLowerCase().endsWith(type.toLowerCase()),
|
||||
);
|
||||
}
|
||||
|
||||
const { mutate, isPending } = usePostUploadFile();
|
||||
|
||||
const handleButtonClick = (): void => {
|
||||
createFileUpload({ multiple: false, accept: fileTypes?.join(",") }).then(
|
||||
(files) => {
|
||||
const file = files[0];
|
||||
if (file) {
|
||||
if (!validateFileSize(file)) {
|
||||
return;
|
||||
}
|
||||
const handleFileSelection = (file: File | null) => {
|
||||
if (!file) {
|
||||
setErrorData({
|
||||
title: "Error selecting file",
|
||||
list: ["No file was selected"],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkFileType(file.name)) {
|
||||
// Upload the file
|
||||
mutate(
|
||||
{ file, id: currentFlowId },
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
// Get the file name from the response
|
||||
const { file_path } = data;
|
||||
if (!validateFileSize(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sets the value that goes to the backend
|
||||
// Update the state and on with the name of the file
|
||||
// sets the value to the user
|
||||
handleOnNewValue({ value: file.name, file_path });
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(CONSOLE_ERROR_MSG);
|
||||
setErrorData({
|
||||
title: "Error uploading file",
|
||||
list: [error.response?.data?.detail],
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// Show an error if the file type is not allowed
|
||||
setErrorData({
|
||||
title: INVALID_FILE_ALERT,
|
||||
list: [fileTypes?.join(", ") || ""],
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!checkFileType(file.name)) {
|
||||
setErrorData({
|
||||
title: INVALID_FILE_ALERT,
|
||||
list: [fileTypes?.join(", ") || ""],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
mutate(
|
||||
{ file, id: currentFlowId },
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
const { file_path } = data;
|
||||
handleOnNewValue({ value: file.name, file_path });
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(CONSOLE_ERROR_MSG);
|
||||
setErrorData({
|
||||
title: "Error uploading file",
|
||||
list: [error.response?.data?.detail || "Unknown error occurred"],
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const handleButtonClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
const handleNativeInputChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>,
|
||||
) => {
|
||||
const file = event.target.files?.[0] || null;
|
||||
handleFileSelection(file);
|
||||
if (event.target) {
|
||||
event.target.value = "";
|
||||
}
|
||||
};
|
||||
|
||||
const isDisabled = disabled || isPending;
|
||||
|
||||
return (
|
||||
|
|
@ -96,18 +102,29 @@ export default function InputFileComponent({
|
|||
<div className="flex items-center gap-2.5">
|
||||
<div className="relative flex w-full">
|
||||
<div className="w-full">
|
||||
<input
|
||||
<Button
|
||||
unstyled
|
||||
data-testid="input-file-component"
|
||||
type="text"
|
||||
className={cn(
|
||||
"primary-input h-9 w-full cursor-pointer rounded-r-none text-sm focus:border-border focus:outline-none focus:ring-0",
|
||||
"primary-input h-9 w-full justify-start rounded-r-none text-sm focus:border-border focus:outline-none focus:ring-0",
|
||||
!value && "text-placeholder-foreground",
|
||||
editNode && "h-6",
|
||||
)}
|
||||
value={value || "Upload a file..."}
|
||||
readOnly
|
||||
disabled={isDisabled}
|
||||
onClick={handleButtonClick}
|
||||
disabled={isDisabled}
|
||||
variant="outline"
|
||||
>
|
||||
<span className={cn(editNode && "relative -top-1.5")}>
|
||||
{value || "Upload a file..."}
|
||||
</span>
|
||||
</Button>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
className="hidden"
|
||||
accept={fileTypes?.join(",")}
|
||||
onChange={handleNativeInputChange}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue