Skip to content

Commit

Permalink
Apply Upload view #72
Browse files Browse the repository at this point in the history
  • Loading branch information
KimKwon committed Apr 4, 2021
1 parent 86a94cf commit f11aae1
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 171 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"query-string": "^6.13.1",
"react": "^16.11.0",
"react-background-slider": "^1.2.0",
"react-cropper": "^1.3.0",
"react-cropper": "2.1.7",
"react-dom": "^16.11.0",
"react-images-upload": "^1.2.7",
"react-photo-gallery": "^8.0.0",
Expand Down
120 changes: 120 additions & 0 deletions src/Components/Upload/ImageCropper/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React, { useRef, useState, useEffect, useCallback } from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';

import NoStyleButton from 'Components/Form/NoStyleButton';

import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';

import Button from '@material-ui/core/Button';

function ImageCropper(props) {
const { imgHandler } = props;
const cropperRef = useRef(null);
const user = useSelector((state) => state.authReducer.user);

const [pictureImg, setPictureImg] = useState(null);
const [pictureImgUrl, setPictureImgUrl] = useState(null);

const handlePictureImg = async (e) => {
if (e.target.files[0] !== undefined) {
setPictureImg(e.target.files[0]);
setPictureImgUrl(URL.createObjectURL(e.target.files[0]));
}
};

const handlePostUpload = useCallback(async () => {
if (user && cropperRef.current) {
const imgElement = cropperRef.current;
const { cropper } = imgElement;
if (pictureImg && cropper) {
const { name } = pictureImg;
const canvas = cropper.getCroppedCanvas();
if (canvas) {
canvas.toBlob(
async (croppedImg) => {
const image = new FormData();
image.append('img', croppedImg, name);
imgHandler(image);
},
undefined,
1,
);
}
} else {
// TO DO :: notify uploading image !
}
} else {
// TO DO :: implement login modal !
}
}, [imgHandler, pictureImgUrl, user, pictureImg]);

const removePicture = () => {
setPictureImg(null);
setPictureImgUrl(null);
};

useEffect(() => {
handlePostUpload();
}, [pictureImg, handlePostUpload]);

return (
<>
<div className="imageCropper">
<div className="imageCropper__creator">
<div className="imageCropper__creator-previewPic">
{pictureImg && (
<>
<Cropper
className="cropper"
alt="imageCrop"
style={{ zIndex: 2 }}
src={pictureImgUrl}
ref={cropperRef}
crop={handlePostUpload}
/>
<NoStyleButton
className="imageCropper__creator-previewPic__remove"
onClick={removePicture}
>
X
</NoStyleButton>
</>
)}
{!pictureImg && (
<div className="imageCropper__creator-previewPic__empty">
<div className="imageCropper__creator-previewPic__empty-uploadPic">
<Button
size="small"
fullWidth
disableRipple
disableFocusRipple
>
<label htmlFor="art-upload">
upload image
<input
accept="image/*"
type="file"
name="img"
id="art-upload"
style={{ display: 'none' }}
onChange={handlePictureImg}
/>
</label>
</Button>
</div>
</div>
)}
</div>
</div>
</div>
</>
);
}

ImageCropper.propTypes = {
imgHandler: PropTypes.func.isRequired,
};

export default ImageCropper;
59 changes: 59 additions & 0 deletions src/Components/Upload/ImageCropper/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
ImageCropper Component Styling
*/

.imageCropper {
width: 100%;
border-radius: 18px;
button:focus {
outline: none;
}
&__creator {
margin-bottom: 1rem;
&-previewPic {
position: relative;
display: flex;
margin: auto;
border: 2px dotted #ccd0d5;
background-color: rgba(255, 244, 201, 0.3);

&__remove {
margin: 0.5rem;
z-index: 1;
position: absolute;
top: 0;
left: 0;
color: $main-color;
font-weight: bolder;
font-size: 1.5rem;
}

&__empty {
position: relative;
height: 400px;
width: 100%;
background-color: $background-color;
opacity: 50%;
&-uploadPic {
z-index: 1;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
label {
margin: 0;
cursor: pointer;
font-family: 'GothamRound';
color: $main-color;
}
}
}

.cropper {
margin: auto;
max-width: 80%;
max-height: 400px;
}
}
}
}
153 changes: 52 additions & 101 deletions src/Components/Upload/UploadPost/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import * as PostAction from 'Redux/post';

import PropTypes from 'prop-types';

import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';

import RoundLoader from 'Components/Loader/Round';
import NoStyleButton from 'Components/Form/NoStyleButton';
import ImageCropper from 'Components/Upload/ImageCropper';

import plusButton from 'Assets/images/plus.svg';

import { Modal } from 'reactstrap';
import TextField from '@material-ui/core/TextField';

const defaultProps = {
user: null,
token: null,
Expand Down Expand Up @@ -48,23 +47,16 @@ class Upload extends Component {
constructor(props) {
super(props);
this.state = {
pictureImg: null,
pictureImgUrl: null,
imageFormData: null,
content: '',
modal: false,
};
}

handlePictureImg = async (e) => {
if (e.target.files[0] !== undefined) {
await new Promise((accept) =>
this.setState({ pictureImg: e.target.files[0] }, accept),
);
const { pictureImg } = this.state;
this.setState({
pictureImgUrl: URL.createObjectURL(pictureImg),
});
}
handlePictureWithCropper = (imageFormData) => {
this.setState({
imageFormData,
});
};

handleContent = (e) => {
Expand All @@ -73,29 +65,17 @@ class Upload extends Component {

handlePostUpload = async () => {
const { user, uploadPost, token } = this.props;
const { pictureImgUrl, pictureImg, content } = this.state;
const { imageFormData, content } = this.state;
if (user) {
if (pictureImgUrl) {
this.cropper.getCroppedCanvas({ imageSmoothingQuality: 'high' }).toBlob(
async (croppedImg) => {
const image = new FormData();
const params = new URLSearchParams();
image.append('img', croppedImg, pictureImg.name);
params.append('title', content);
params.append('user_id', user.id);
params.append('description', content);
params.append('category_id', 5);
params.append('is_public', true);
const postUpload = await uploadPost(image, params, token);
if (postUpload) window.location.reload();
// TO DO :: notify failed to upload image
},
undefined,
1,
);
} else {
// TO DO :: notify uploading image !
}
const params = new URLSearchParams();

params.append('title', content);
params.append('user_id', user.id);
params.append('description', content);
params.append('category_id', 5);
params.append('is_public', true);
const postUpload = await uploadPost(imageFormData, params, token);
if (postUpload) window.location.reload();
} else {
// TO DO :: implement login modal !
}
Expand All @@ -107,84 +87,55 @@ class Upload extends Component {
};

render() {
const { content, modal, pictureImgUrl } = this.state;
const { content, modal } = this.state;
const { isUploading } = this.props;
return (
<>
{isUploading && <RoundLoader />}
<button
type="button"
onClick={this.toggle}
className="uploadModalButton"
>
<img src={plusButton} alt="+" />
</button>
<Modal isOpen={modal} toggle={this.toggle} className="className">
<ModalHeader toggle={this.toggle}>
Upload Your Masterpiece!
</ModalHeader>
<ModalBody>
<div className="postUpload">
<div className="postUpload__creator">
<div className="postUpload__creator-uploadPic">
<Button
size="small"
fullWidth
disableRipple
disableFocusRipple
>
<label htmlFor="art-upload">
upload image
<input
accept="image/*"
type="file"
name="img"
id="art-upload"
style={{ display: 'none' }}
onChange={this.handlePictureImg}
/>
</label>
</Button>
<>
<button
type="button"
onClick={this.toggle}
className="uploadModalButton"
>
<img src={plusButton} alt="+" />
</button>
<Modal isOpen={modal} toggle={this.toggle}>
<div className="uploadPost">
<div className="uploadPost__header">
<div className="uploadPost__header__title">
Upload Your Masterpiece!
</div>
{pictureImgUrl && (
<div className="postUpload__creator-previewPic">
<Cropper
className="cropper"
alt="original"
src={pictureImgUrl}
ref={(cropper) => {
this.cropper = cropper;
}}
// Cropper.js options
center
/>
</div>
)}
<div className="postUpload__creator-content">
</div>
<div className="uploadPost__content">
<div className="uploadPost__content__border">
<ImageCropper imgHandler={this.handlePictureWithCropper} />
</div>
<div className="uploadPost__content__input">
<TextField
id="outlined-multiline"
placeholder="Type your art..."
placeholder="Art's title"
value={content}
multiline
rows="3"
rowsMax="10"
variant="outlined"
fullWidth
onChange={this.handleContent}
/>
</div>
</div>
<div className="uploadPost__footer">
<NoStyleButton onClick={this.handlePostUpload}>
<div className="uploadPost__footer__upload">
<div className="uploadPost__footer__upload__text">
upload!
</div>
</div>
</NoStyleButton>
</div>
</div>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.handlePostUpload}>
Upload
</Button>
<Button color="secondary" onClick={this.toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</Modal>
</>
</>
);
}
Expand Down
Loading

0 comments on commit f11aae1

Please # to comment.