itizawa 6 лет назад
Родитель
Сommit
4aea26baea

+ 0 - 4
src/client/js/app.jsx

@@ -38,8 +38,6 @@ import EditorContainer from './services/EditorContainer';
 import TagContainer from './services/TagContainer';
 import TagContainer from './services/TagContainer';
 import PersonalContainer from './services/PersonalContainer';
 import PersonalContainer from './services/PersonalContainer';
 
 
-import ProfileImageUploader from './components/Me/ProfileImageUploader';
-
 import { appContainer, componentMappings } from './bootstrap';
 import { appContainer, componentMappings } from './bootstrap';
 
 
 const logger = loggerFactory('growi:app');
 const logger = loggerFactory('growi:app');
@@ -76,8 +74,6 @@ Object.assign(componentMappings, {
   'page-status-alert': <PageStatusAlert />,
   'page-status-alert': <PageStatusAlert />,
   'save-page-controls': <SavePageControls />,
   'save-page-controls': <SavePageControls />,
 
 
-  'profile-image-uploader': <ProfileImageUploader />,
-
   'user-created-list': <RecentCreated />,
   'user-created-list': <RecentCreated />,
   'user-draft-list': <MyDraftList />,
   'user-draft-list': <MyDraftList />,
 });
 });

+ 61 - 5
src/client/js/components/Me/ProfileImageSettings.jsx

@@ -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,35 @@ 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 });
+    }
+  }
+
+  onCropCompleted(croppedImageUrl) {
+    this.props.personalContainer.setState({ croppedImageUrl });
+    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 { croppedImageUrl, isGravatarEnabled } = personalContainer.state;
 
 
     return (
     return (
       <React.Fragment>
       <React.Fragment>
@@ -49,7 +88,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 +111,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 +119,33 @@ 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">
+                {croppedImageUrl && (<p><img src={croppedImageUrl} className="picture picture-lg img-circle" id="settingUserPicture" /></p>)}
+                <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}>

+ 0 - 88
src/client/js/components/Me/ProfileImageUploader.jsx

@@ -1,88 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-import AppContainer from '../../services/AppContainer';
-import { createSubscribedElement } from '../UnstatedUtils';
-import ImageCropModal from './ImageCropModal';
-
-class ProfileImageUploader extends React.Component {
-
-  constructor(props) {
-    super();
-    this.state = {
-      show: false,
-      src: null,
-      croppedImageUrl: 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);
-  }
-
-  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 });
-    }
-  }
-
-  onCropCompleted(croppedImageUrl) {
-    this.setState({ croppedImageUrl });
-    this.hideModal();
-  }
-
-  showModal() {
-    this.setState({ show: true });
-  }
-
-  hideModal() {
-    this.setState({ show: false });
-  }
-
-  cancelModal() {
-    this.hideModal();
-  }
-
-  render() {
-    const { t } = this.props;
-    const { croppedImageUrl } = this.state;
-    return (
-      <div className="ProfileImageUploader">
-        <div className="form-group">
-          <label className="col-sm-4 control-label">
-            {t('Upload new image')}
-          </label>
-        </div>
-        <div className="col-sm-8">
-          {croppedImageUrl && (
-            <img src={croppedImageUrl} className="picture picture-lg img-circle" id="settingUserPicture" />
-          )}
-          <input type="file" onChange={this.onSelectFile} name="profileImage" accept="image/*" />
-          <ImageCropModal
-            show={this.state.show}
-            src={this.state.src}
-            onModalClose={this.cancelModal}
-            onCropCompleted={this.onCropCompleted}
-          />
-        </div>
-      </div>
-    );
-  }
-
-}
-
-/**
- * Wrapper component for using unstated
- */
-const ProfileImageFormWrapper = (props) => {
-  return createSubscribedElement(ProfileImageUploader, props, [AppContainer]);
-};
-ProfileImageUploader.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-};
-export default withTranslation()(ProfileImageFormWrapper);

+ 17 - 1
src/client/js/services/PersonalContainer.js

@@ -24,6 +24,7 @@ export default class PersonalContainer extends Container {
       isEmailPublished: false,
       isEmailPublished: false,
       lang: 'en-US',
       lang: 'en-US',
       isGravatarEnabled: false,
       isGravatarEnabled: false,
+      croppedImageUrl: '',
       externalAccounts: [],
       externalAccounts: [],
       isPasswordSet: false,
       isPasswordSet: false,
       apiToken: '',
       apiToken: '',
@@ -45,7 +46,7 @@ export default class PersonalContainer extends Container {
     try {
     try {
       const response = await this.appContainer.apiv3.get('/personal-setting/');
       const response = await this.appContainer.apiv3.get('/personal-setting/');
       const { currentUser } = response.data;
       const { currentUser } = response.data;
-
+      const croppedImageUrl = this.getUploadedPictureSrc(currentUser);
       this.setState({
       this.setState({
         name: currentUser.name,
         name: currentUser.name,
         email: currentUser.email,
         email: currentUser.email,
@@ -54,6 +55,7 @@ export default class PersonalContainer extends Container {
         isGravatarEnabled: currentUser.isGravatarEnabled,
         isGravatarEnabled: currentUser.isGravatarEnabled,
         isPasswordSet: (currentUser.password != null),
         isPasswordSet: (currentUser.password != null),
         apiToken: currentUser.apiToken,
         apiToken: currentUser.apiToken,
+        croppedImageUrl,
       });
       });
     }
     }
     catch (err) {
     catch (err) {
@@ -63,6 +65,20 @@ export default class PersonalContainer extends Container {
     }
     }
   }
   }
 
 
+  /**
+   * define a function for uploaded picture
+   */
+  getUploadedPictureSrc(user) {
+    if (user.image) {
+      return user.image;
+    }
+    if (user.imageAttachment != null) {
+      return user.imageAttachment.filePathProxied;
+    }
+
+    return '/images/icons/user.svg';
+  }
+
   /**
   /**
    * retrieve external accounts that linked me
    * retrieve external accounts that linked me
    */
    */