Skip to content

Instantly share code, notes, and snippets.

@sushilbansal
Last active March 11, 2022 09:37
Show Gist options
  • Save sushilbansal/0b2e2e5fd43d91430cd0d98587478338 to your computer and use it in GitHub Desktop.
Save sushilbansal/0b2e2e5fd43d91430cd0d98587478338 to your computer and use it in GitHub Desktop.
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