|
@@ -9,11 +9,23 @@ import { createSubscribedElement } from '../UnstatedUtils';
|
|
|
import AppContainer from '../../services/AppContainer';
|
|
import AppContainer from '../../services/AppContainer';
|
|
|
import PersonalContainer from '../../services/PersonalContainer';
|
|
import PersonalContainer from '../../services/PersonalContainer';
|
|
|
|
|
|
|
|
|
|
+import ImageCropModal from './ImageCropModal';
|
|
|
|
|
+
|
|
|
class ProfileImageSettings extends React.Component {
|
|
class ProfileImageSettings extends React.Component {
|
|
|
|
|
|
|
|
constructor(appContainer) {
|
|
constructor(appContainer) {
|
|
|
super();
|
|
super();
|
|
|
|
|
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ show: false,
|
|
|
|
|
+ src: null,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ this.imageRef = null;
|
|
|
|
|
+ this.onSelectFile = this.onSelectFile.bind(this);
|
|
|
|
|
+ this.hideModal = this.hideModal.bind(this);
|
|
|
|
|
+ this.cancelModal = this.cancelModal.bind(this);
|
|
|
|
|
+ this.onCropCompleted = this.onCropCompleted.bind(this);
|
|
|
this.onClickSubmit = this.onClickSubmit.bind(this);
|
|
this.onClickSubmit = this.onClickSubmit.bind(this);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -35,8 +47,43 @@ class ProfileImageSettings extends React.Component {
|
|
|
return `https://gravatar.com/avatar/${hash}`;
|
|
return `https://gravatar.com/avatar/${hash}`;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ onSelectFile(e) {
|
|
|
|
|
+ if (e.target.files && e.target.files.length > 0) {
|
|
|
|
|
+ const reader = new FileReader();
|
|
|
|
|
+ reader.addEventListener('load', () => this.setState({ src: reader.result }));
|
|
|
|
|
+ reader.readAsDataURL(e.target.files[0]);
|
|
|
|
|
+ this.setState({ show: true });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async onCropCompleted(croppedImageUrl) {
|
|
|
|
|
+ const { t, personalContainer } = this.props;
|
|
|
|
|
+ personalContainer.setState({ croppedImageUrl });
|
|
|
|
|
+ try {
|
|
|
|
|
+ await personalContainer.uploadAttachment(croppedImageUrl);
|
|
|
|
|
+ toastSuccess(t('toaster.update_successed', { target: t('Upload Image') }));
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ toastError(err);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.hideModal();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ showModal() {
|
|
|
|
|
+ this.setState({ show: true });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hideModal() {
|
|
|
|
|
+ this.setState({ show: false });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cancelModal() {
|
|
|
|
|
+ this.hideModal();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
render() {
|
|
render() {
|
|
|
const { t, personalContainer } = this.props;
|
|
const { t, personalContainer } = this.props;
|
|
|
|
|
+ const { uploadedPictureSrc, isGravatarEnabled } = personalContainer.state;
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<React.Fragment>
|
|
<React.Fragment>
|
|
@@ -49,7 +96,7 @@ class ProfileImageSettings extends React.Component {
|
|
|
id="radioGravatar"
|
|
id="radioGravatar"
|
|
|
form="formImageType"
|
|
form="formImageType"
|
|
|
name="imagetypeForm[isGravatarEnabled]"
|
|
name="imagetypeForm[isGravatarEnabled]"
|
|
|
- checked={personalContainer.state.isGravatarEnabled}
|
|
|
|
|
|
|
+ checked={isGravatarEnabled}
|
|
|
onChange={() => { personalContainer.changeIsGravatarEnabled(true) }}
|
|
onChange={() => { personalContainer.changeIsGravatarEnabled(true) }}
|
|
|
/>
|
|
/>
|
|
|
<label htmlFor="radioGravatar">
|
|
<label htmlFor="radioGravatar">
|
|
@@ -72,7 +119,7 @@ class ProfileImageSettings extends React.Component {
|
|
|
id="radioUploadPicture"
|
|
id="radioUploadPicture"
|
|
|
form="formImageType"
|
|
form="formImageType"
|
|
|
name="imagetypeForm[isGravatarEnabled]"
|
|
name="imagetypeForm[isGravatarEnabled]"
|
|
|
- checked={!personalContainer.state.isGravatarEnabled}
|
|
|
|
|
|
|
+ checked={!isGravatarEnabled}
|
|
|
onChange={() => { personalContainer.changeIsGravatarEnabled(false) }}
|
|
onChange={() => { personalContainer.changeIsGravatarEnabled(false) }}
|
|
|
/>
|
|
/>
|
|
|
<label htmlFor="radioUploadPicture">
|
|
<label htmlFor="radioUploadPicture">
|
|
@@ -80,16 +127,34 @@ class ProfileImageSettings extends React.Component {
|
|
|
</label>
|
|
</label>
|
|
|
</div>
|
|
</div>
|
|
|
</h4>
|
|
</h4>
|
|
|
- <div className="form-group">
|
|
|
|
|
- <div id="pictureUploadFormMessage"></div>
|
|
|
|
|
|
|
+ <div className="row mb-3">
|
|
|
<label className="col-sm-4 control-label">
|
|
<label className="col-sm-4 control-label">
|
|
|
{ t('Current Image') }
|
|
{ t('Current Image') }
|
|
|
</label>
|
|
</label>
|
|
|
- {/* TDOO GW-1198 uproad profile image */}
|
|
|
|
|
|
|
+ <div className="col-sm-8">
|
|
|
|
|
+ {uploadedPictureSrc && (<p><img src={uploadedPictureSrc} className="picture picture-lg img-circle" id="settingUserPicture" /></p>)}
|
|
|
|
|
+ {/* TODO GW-1218 create apiV3 for delete image */}
|
|
|
|
|
+ <button type="button" className="btn btn-danger">{ t('Delete Image') }</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="row">
|
|
|
|
|
+ <label className="col-sm-4 control-label">
|
|
|
|
|
+ {t('Upload new image')}
|
|
|
|
|
+ </label>
|
|
|
|
|
+ <div className="col-sm-8">
|
|
|
|
|
+ <input type="file" onChange={this.onSelectFile} name="profileImage" accept="image/*" />
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <ImageCropModal
|
|
|
|
|
+ show={this.state.show}
|
|
|
|
|
+ src={this.state.src}
|
|
|
|
|
+ onModalClose={this.cancelModal}
|
|
|
|
|
+ onCropCompleted={this.onCropCompleted}
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
<div className="row my-3">
|
|
<div className="row my-3">
|
|
|
<div className="col-xs-offset-4 col-xs-5">
|
|
<div className="col-xs-offset-4 col-xs-5">
|
|
|
<button type="button" className="btn btn-primary" onClick={this.onClickSubmit} disabled={personalContainer.state.retrieveError != null}>
|
|
<button type="button" className="btn btn-primary" onClick={this.onClickSubmit} disabled={personalContainer.state.retrieveError != null}>
|