Last active
March 11, 2022 09:37
-
-
Save sushilbansal/0b2e2e5fd43d91430cd0d98587478338 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useRef, useState } from 'react'; | |
import Cropper from 'react-cropper'; | |
import Button from '@material-ui/core/Button'; | |
import Dialog from '@material-ui/core/Dialog'; | |
import DialogActions from '@material-ui/core/DialogActions'; | |
import DialogContent from '@material-ui/core/DialogContent'; | |
import DialogTitle from '@material-ui/core/DialogTitle'; | |
import { IMAGE_SERVER_URL } from '../../../common'; | |
import { useUploadImageMutation } from '../../../controller'; | |
import { base64StringtoFile } from '../../util/ImageCrop'; | |
import { ConfirmationButton } from './ConfirmationButton'; | |
interface Props { | |
uploadTextIcon: any; | |
uploadedImageURL: (image: string) => void; | |
} | |
export const ImageCropper = (props: Props) => { | |
const { uploadTextIcon, uploadedImageURL } = props; | |
// Opens the Cropper dialog | |
const [openDialog, setOpenDialog] = useState(false); | |
const [selectedFile, setSelectedFile] = useState<any>(null); | |
// Using this to show the cropped image quickly to the user. | |
const [croppedFilePath, setCroppedFilePath] = useState<any>(null); | |
const [croppedFile, setCroppedFile] = useState<any>(null); | |
// Mutation to upload the image to the server | |
const [uploadImageMutation] = useUploadImageMutation(); | |
const cropper = useRef(null); | |
// Image input ref. It will be used to reset the file input to blank. | |
const fileInputRef = useRef<any>(null); | |
// Will close the cropper dialog | |
const handleClose = () => { | |
// Reset the image input to blank incase user selects the same file. | |
// If users selects the same file then onChange will not fire. | |
if (fileInputRef && fileInputRef.current) { | |
fileInputRef.current.value = ""; | |
} | |
setOpenDialog(false); | |
}; | |
const confirmCroppedImage = async () => { | |
// Upload cropped image to the server. | |
const { data } = await uploadImageMutation({ | |
variables: { input: { picture: croppedFile } }, | |
}); | |
// Getting the file name of the uploaded image on the server. | |
// Create a full URL to store that in slate. | |
if (data && data.uploadImage && data.uploadImage.filename) { | |
const url = `${IMAGE_SERVER_URL}${encodeURI(data.uploadImage.filename)}`; | |
uploadedImageURL(url); | |
} | |
handleClose(); | |
}; | |
// This method will run when any image is selected. | |
const fileSelectHandler = async (event: any) => { | |
if (event.target.files && event.target.files.length > 0) { | |
const file = event.target.files[0]; | |
const newFile = Object.assign(file, { | |
preview: URL.createObjectURL(file), | |
}); | |
setSelectedFile(newFile); | |
setOpenDialog(true); | |
} | |
}; | |
// Will crop any selected image and will set the croppedImage file to be saved to DB. | |
const _crop = () => { | |
const str = (cropper as any).current | |
.getCroppedCanvas() | |
.toDataURL(selectedFile.type, 0.8); | |
setCroppedFilePath(str); | |
setCroppedFile(base64StringtoFile(str, selectedFile.name)); | |
}; | |
return ( | |
<> | |
<input | |
accept="image/*" | |
style={{ display: "none" }} | |
id="upload-image" | |
type="file" | |
onChange={fileSelectHandler} | |
ref={fileInputRef} | |
/> | |
<label htmlFor="upload-image">{uploadTextIcon()}</label> | |
<Dialog | |
open={openDialog} | |
onClose={handleClose} | |
scroll="paper" | |
aria-labelledby="scroll-dialog-title" | |
aria-describedby="scroll-dialog-description" | |
> | |
<DialogTitle id="scroll-dialog-title">Select image</DialogTitle> | |
<DialogContent dividers={true}> | |
{selectedFile && ( | |
<Cropper | |
ref={cropper} | |
src={selectedFile?.preview} | |
style={{ height: 400, width: "100%", marginBottom: 30 }} | |
guides={true} | |
zoomOnWheel={false} | |
crop={_crop} | |
/> | |
)} | |
{ /* Showing the cropped image here */} | |
{croppedFilePath && ( | |
<span style={{ display: "flex", flexDirection: "column" }}> | |
<span style={{ fontWeight: "bolder" }}>Cropped Image: </span> | |
<img src={croppedFilePath} style={{ width: "100%" }} /> | |
</span> | |
)} | |
</DialogContent> | |
<DialogActions> | |
<Button | |
onClick={handleClose} | |
color="secondary" | |
style={{ textTransform: "none" }} | |
> | |
Cancel | |
</Button> | |
<ConfirmationButton | |
label="Confirm Image" | |
onSubmit={confirmCroppedImage} | |
/> | |
</DialogActions> | |
</Dialog> | |
</> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment