Skip to content
Snippets Groups Projects
Commit 3727df70 authored by Jacopo Gasparetto's avatar Jacopo Gasparetto
Browse files

Refactor InputFile folder to use only one single button to upload a file

parent 9e85d868
No related branches found
No related tags found
No related merge requests found
import { ChangeEvent } from "react"; import { ChangeEvent, ReactNode } from "react";
import { Button } from "./Button";
interface InputFileProps { interface InputFileProps {
onChange: (e: ChangeEvent<HTMLInputElement>) => void; onChange: (e: ChangeEvent<HTMLInputElement>) => void;
icon?: ReactNode
} }
export const InputFile = ({ onChange }: InputFileProps) => { export const InputFile = ({ onChange, icon }: InputFileProps) => {
const openFileSelector = () => {
const fileSelector = document.getElementById("fileSelector");
if (fileSelector) {
fileSelector.click();
}
}
return ( return (
<div className=""> <div className="">
<input <input
onChange={onChange} onChange={onChange}
className="p-4 min-w-0 flex-auto rounded border \ className="hidden"
hover:bg-neutral-200 \
file:rounded-none file:border-0 file:border-solid \
file:bg-neutral-200"
type="file" type="file"
id="fileSelector"
/>
<Button
title="Upload File"
icon={icon}
onClick={openFileSelector}
/> />
</div> </div>
); );
......
import { ChangeEvent, useEffect, useRef, useState } from 'react'; import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';
import { Page } from '../../components/Page'; import { Page } from '../../components/Page';
import { BucketObject } from '../../models/bucket'; import { BucketObject } from '../../models/bucket';
import { Column, Table } from '../../components/Table'; import { Column, Table } from '../../components/Table';
...@@ -21,6 +21,7 @@ import { ...@@ -21,6 +21,7 @@ import {
DeleteObjectCommand DeleteObjectCommand
} from '@aws-sdk/client-s3'; } from '@aws-sdk/client-s3';
type PropsType = { type PropsType = {
bucketName: string bucketName: string
} }
...@@ -28,10 +29,10 @@ type PropsType = { ...@@ -28,10 +29,10 @@ type PropsType = {
export const BucketBrowser = ({ bucketName }: PropsType) => { export const BucketBrowser = ({ bucketName }: PropsType) => {
const [bucketObjects, setBucketObjects] = useState<BucketObject[]>([]); const [bucketObjects, setBucketObjects] = useState<BucketObject[]>([]);
const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set()); const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());
const [file, setFile] = useState<File>();
const s3 = useS3Service(); const s3 = useS3Service();
const navigate = useNavigate(); const navigate = useNavigate();
const inputRef = useRef<HTMLInputElement>(); const inputRef = useRef<HTMLInputElement>();
const lockRef = useRef<boolean>(false);
const columns: Column[] = [ const columns: Column[] = [
{ id: "icon" }, { id: "icon" },
...@@ -81,48 +82,72 @@ export const BucketBrowser = ({ bucketName }: PropsType) => { ...@@ -81,48 +82,72 @@ export const BucketBrowser = ({ bucketName }: PropsType) => {
] ]
}); });
const refreshBucketObjects = useCallback(() => {
const f = async () => {
if (!s3.isAuthenticated()) {
return;
}
console.log("List Bucket objects...")
const listObjCmd = new ListObjectsV2Command({ Bucket: bucketName });
const response = await s3.client.send(listObjCmd);
const { Contents } = response;
if (Contents) {
setBucketObjects(Contents);
} else {
console.warn("Warning: bucket looks empty.");
}
};
f().catch(err => console.error(err));
}, [s3, bucketName]);
useEffect(() => { useEffect(() => {
if (!s3.isAuthenticated() || selectedRows.size > 0) { if (bucketObjects.length === 0 && !lockRef.current) {
return; refreshBucketObjects()
} }
const listObjCmd = new ListObjectsV2Command({ Bucket: bucketName }); return () => {
s3.client.send(listObjCmd) lockRef.current = true;
.then(response => { }
const { Contents } = response; }, [bucketObjects, s3, refreshBucketObjects])
if (Contents) {
setBucketObjects(Contents);
}
});
}, [s3, file, selectedRows])
const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => { const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
inputRef.current = e.target; if (!e.target.files) {
if (e.target.files) { return;
setFile(e.target.files[0]);
} }
};
const upload = () => { if (!s3.isAuthenticated()) {
if (!(file && s3.isAuthenticated())) { console.warn(
"Warning: cannot upload file because S3 service not authenticated"
);
return; return;
} }
const putObjCmd = new PutObjectCommand({ inputRef.current = e.target;
Bucket: bucketName, const { files } = e.target;
Body: file,
Key: file.name // Upload all files FIXME: use different approach for multiple files
}); Array.from(files).forEach(file => {
const putObjCmd = new PutObjectCommand({
Bucket: bucketName,
Body: file,
Key: file.name
});
s3.client.send(putObjCmd) s3.client.send(putObjCmd)
.then(() => { .then(() => {
console.log("File uploaded"); console.log("File uploaded");
if (inputRef.current) { if (inputRef.current) {
inputRef.current.files = null; inputRef.current.files = null;
inputRef.current.value = ""; inputRef.current.value = "";
} }
setFile(undefined); })
}) .then(refreshBucketObjects)
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const deleteObject = async (bucketName: string, key: string) => { const deleteObject = async (bucketName: string, key: string) => {
...@@ -157,8 +182,8 @@ export const BucketBrowser = ({ bucketName }: PropsType) => { ...@@ -157,8 +182,8 @@ export const BucketBrowser = ({ bucketName }: PropsType) => {
// Wait untill all delete are done then refresh the UI. // Wait untill all delete are done then refresh the UI.
Promise.all(promises) Promise.all(promises)
.then(() => { .then(() => {
console.log("refresh") setSelectedRows(new Set());
setSelectedRows(new Set()) refreshBucketObjects();
}); });
} }
...@@ -169,15 +194,12 @@ export const BucketBrowser = ({ bucketName }: PropsType) => { ...@@ -169,15 +194,12 @@ export const BucketBrowser = ({ bucketName }: PropsType) => {
icon={<ArrowLeftIcon />} icon={<ArrowLeftIcon />}
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
/> />
<div className='container w-2/3'> <div className='container w-2/3'>
<div className="flex mt-8 place-content-between"> <div className="flex mt-8 place-content-between">
<div className='flex space-x-4'> <div className='flex space-x-4'>
<InputFile onChange={handleFileChange} /> <InputFile
<Button
title="Upload file"
icon={<ArrowUpOnSquareIcon />} icon={<ArrowUpOnSquareIcon />}
onClick={upload} onChange={handleFileChange}
/> />
</div> </div>
<Button <Button
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment