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 { 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 useFileSizeValidator from "@/shared/hooks/use-file-size-validator";
|
||||||
import { cn } from "@/utils/utils";
|
import { cn } from "@/utils/utils";
|
||||||
import { useEffect } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
CONSOLE_ERROR_MSG,
|
CONSOLE_ERROR_MSG,
|
||||||
INVALID_FILE_ALERT,
|
INVALID_FILE_ALERT,
|
||||||
|
|
@ -24,68 +23,75 @@ export default function InputFileComponent({
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const { validateFileSize } = useFileSizeValidator(setErrorData);
|
const { validateFileSize } = useFileSizeValidator(setErrorData);
|
||||||
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
// Clear component state
|
// Clear component state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled && value !== "") {
|
if (disabled && value !== "") {
|
||||||
handleOnNewValue({ value: "", file_path: "" }, { skipSnapshot: true });
|
handleOnNewValue({ value: "", file_path: "" }, { skipSnapshot: true });
|
||||||
}
|
}
|
||||||
}, [disabled, handleOnNewValue]);
|
}, [disabled, handleOnNewValue, value]);
|
||||||
|
|
||||||
function checkFileType(fileName: string): boolean {
|
function checkFileType(fileName: string): boolean {
|
||||||
if (fileTypes === undefined) return true;
|
if (!fileTypes?.length) return true;
|
||||||
for (let index = 0; index < fileTypes.length; index++) {
|
return fileTypes.some((type) =>
|
||||||
if (fileName.endsWith(fileTypes[index])) {
|
fileName.toLowerCase().endsWith(type.toLowerCase()),
|
||||||
return true;
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { mutate, isPending } = usePostUploadFile();
|
const { mutate, isPending } = usePostUploadFile();
|
||||||
|
|
||||||
const handleButtonClick = (): void => {
|
const handleFileSelection = (file: File | null) => {
|
||||||
createFileUpload({ multiple: false, accept: fileTypes?.join(",") }).then(
|
if (!file) {
|
||||||
(files) => {
|
setErrorData({
|
||||||
const file = files[0];
|
title: "Error selecting file",
|
||||||
if (file) {
|
list: ["No file was selected"],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!validateFileSize(file)) {
|
if (!validateFileSize(file)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkFileType(file.name)) {
|
if (!checkFileType(file.name)) {
|
||||||
// Upload the file
|
setErrorData({
|
||||||
|
title: INVALID_FILE_ALERT,
|
||||||
|
list: [fileTypes?.join(", ") || ""],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mutate(
|
mutate(
|
||||||
{ file, id: currentFlowId },
|
{ file, id: currentFlowId },
|
||||||
{
|
{
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
// Get the file name from the response
|
|
||||||
const { file_path } = data;
|
const { file_path } = data;
|
||||||
|
|
||||||
// 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 });
|
handleOnNewValue({ value: file.name, file_path });
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error(CONSOLE_ERROR_MSG);
|
console.error(CONSOLE_ERROR_MSG);
|
||||||
setErrorData({
|
setErrorData({
|
||||||
title: "Error uploading file",
|
title: "Error uploading file",
|
||||||
list: [error.response?.data?.detail],
|
list: [error.response?.data?.detail || "Unknown error occurred"],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
};
|
||||||
// Show an error if the file type is not allowed
|
|
||||||
setErrorData({
|
const handleButtonClick = () => {
|
||||||
title: INVALID_FILE_ALERT,
|
fileInputRef.current?.click();
|
||||||
list: [fileTypes?.join(", ") || ""],
|
};
|
||||||
});
|
|
||||||
|
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;
|
const isDisabled = disabled || isPending;
|
||||||
|
|
@ -96,18 +102,29 @@ export default function InputFileComponent({
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<div className="relative flex w-full">
|
<div className="relative flex w-full">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<input
|
<Button
|
||||||
|
unstyled
|
||||||
data-testid="input-file-component"
|
data-testid="input-file-component"
|
||||||
type="text"
|
|
||||||
className={cn(
|
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",
|
!value && "text-placeholder-foreground",
|
||||||
editNode && "h-6",
|
editNode && "h-6",
|
||||||
)}
|
)}
|
||||||
value={value || "Upload a file..."}
|
|
||||||
readOnly
|
|
||||||
disabled={isDisabled}
|
|
||||||
onClick={handleButtonClick}
|
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>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue