Skip to content

Instantly share code, notes, and snippets.

@daviddamilola
Created August 25, 2020 03:23
Show Gist options
  • Save daviddamilola/2d44ff005978af5921012072a42302b5 to your computer and use it in GitHub Desktop.
Save daviddamilola/2d44ff005978af5921012072a42302b5 to your computer and use it in GitHub Desktop.
custom file upload React component -- draft
import React, { useRef } from "react";
import "./FileInput.scss";
import { greyTrash} from "assets/images/svg";
interface InputProps {
id?: string;
type: string;
handleChange?: any;
disabled?: boolean;
value?: string;
placeholder?: string;
label?: string;
ref?: string;
name?: string;
textCounter?: number | string;
required?: boolean;
checked?: boolean;
handleBlur?: any;
className?: string;
message: string;
}
interface IUploadSuccessProps {
thumbnail: any;
fileName: any;
handleDelete: any;
}
export const UploadSuccess: React.FunctionComponent<IUploadSuccessProps> = (
{thumbnail,
fileName,
handleDelete,}
) => {
return (
<>
<div className="input-wrapper thumbnail">
<div className="d-flex w-100 align-items-center justify-content-between ">
<span className=" ">
<span className="">
<img className="selected-img" src={thumbnail} alt="" />
</span>{" "}
<span className="ml-2 fileInput__text">{fileName}</span>
</span>
<span className="mr-2 delete" onClick={handleDelete}>
<img src={greyTrash} alt="delete file" />
</span>
</div>
<div className="loading w-100">
<div className="progress-p w-50"></div>
</div>
</div>
</>
);
};
const FileInput: React.SFC<InputProps> = ({
id,
message,
handleChange,
type,
disabled,
value,
placeholder,
label,
required = false,
ref,
name,
textCounter,
checked,
handleBlur,
className = "",
}) => {
const fileRef: any = useRef(null);
const fakeInputRef: any = useRef(null);
const replaceRef: any = useRef(null);
const [fileName, setFileName] = React.useState("");
const [thumbnail, setThumbnail]:any = React.useState(null);
const handlePaste = (e: any) => {
const types = e.dataTransfer.types;
if (
!types ||
(types.contains && types.contains("Files")) ||
(types.indexOf && types.indexOf("Files") !== -1)
) {
fileRef.current.classList.add("active"); // Highlight droptarget
return false; // We're interested in the drag
}
};
const awayFromFileTarget = (e: any) => {
fileRef.current.classList.remove("active");
};
//referenced from https://gist.github.com/davoclavo/4424731
function dataURItoBlob(dataURI: any) {
// convert base64 to raw binary data held in a string
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var arrayBuffer = new ArrayBuffer(byteString.length);
var _ia = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteString.length; i++) {
_ia[i] = byteString.charCodeAt(i);
}
var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });
return blob;
}
const getBlobURL =
(window.URL && URL.createObjectURL.bind(URL)) ||
(window.webkitURL && webkitURL.createObjectURL.bind(webkitURL));
const revokeBlobURL =
(window.URL && URL.revokeObjectURL.bind(URL)) ||
(window.webkitURL && webkitURL.revokeObjectURL.bind(webkitURL));
const handleDrop = (e: any) => {
e.preventDefault();
const files: any = Array.from(e.dataTransfer.files);
const type = files[0].type;
if (type.substring(0, 6) !== "video/") return;
setFileName(files[0].name);
const blobUrl = getBlobURL(files[0]);
handleChange(blobUrl);
};
const handleInputChange = (e: any) => {
setFileName(e.target.value)
}
const filehandleChange = async (e: any) => {
console.log('i was called')
let files: any = Array.from(e.target.files);
const type = files[0].type;
if (type.substring(0, 6) !== "video/") return;
setFileName(files[0].name);
const blobUrl = getBlobURL(files[0]);
//create a video from the video selected or uploaded
const video = document.createElement("video");
const canvas: any = document.createElement("canvas");
video.src = blobUrl;
video.style.display = "none";
video.preload = "true";
video.width = 150;
video.height = 75;
let width = 150
let height = 75
canvas.width = width;
canvas.height = height;
let context = canvas.getContext('2d');
context.drawImage(video, 0, 0, width, height);
let dataUri = canvas.toDataURL('image/jpeg');
const imgBlob:any =dataURItoBlob(dataUri);
const imgblobUrl: any = getBlobURL(imgBlob)
setThumbnail(imgblobUrl);
};
const handleDelete:any = () => {
revokeBlobURL(thumbnail);
setThumbnail(null)
setFileName("")
}
return (
<>
{
thumbnail ? <UploadSuccess fileName={fileName} thumbnail={thumbnail} handleDelete={handleDelete} /> :
(<label
ref={fileRef}
htmlFor={id}
className="d-flex w-100 align-items-center input-wrapper"
>
<span className="fileInput__select">
<span ref={replaceRef}>Select file</span>
</span>
<input
onDragEnter={handlePaste}
onDragLeave={awayFromFileTarget}
onDrop={handleDrop}
id="upload"
onChange= {handleInputChange}
name="upload"
value={fileName}
className="ml-2 fileInput__text"
placeholder={message}
ref={fakeInputRef}
/>
</label>
) }
<input
type="file"
name={name}
id={id}
onChange={filehandleChange}
className="fileInput"
/>
</>
);
};
export default FileInput;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment