Просмотр исходного кода

convert new component to typescript

https://youtrack.weseek.co.jp/issue/GW-7772
- Remove withTransaltion in CropLogoModal component
- Remove  CustomizeLogoSetting.jsx component
- Modify all function in CustomizeLogoSetting.tsx
- Modify null check of attachmentId variable in attachment route
I Komang Mudana 4 лет назад
Родитель
Сommit
ccb0b00368

+ 2 - 2
packages/app/src/components/Admin/Customize/CropLogoModal.jsx

@@ -8,7 +8,7 @@ import {
   ModalBody,
   ModalFooter,
 } from 'reactstrap';
-import { withTranslation } from 'react-i18next';
+
 import ReactCrop from 'react-image-crop';
 import loggerFactory from '~/utils/logger';
 import AppContainer from '~/client/services/AppContainer';
@@ -125,4 +125,4 @@ CropLogoModal.propTypes = {
   onModalClose: PropTypes.func.isRequired,
   onCropCompleted: PropTypes.func.isRequired,
 };
-export default withTranslation()(LogoFormWrapper);
+export default (LogoFormWrapper);

+ 0 - 177
packages/app/src/components/Admin/Customize/CustomizeLogoSetting.jsx

@@ -1,177 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-
-import { withUnstatedContainers } from '../../UnstatedUtils';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
-
-import AppContainer from '~/client/services/AppContainer';
-
-import AdminCustomizeContainer from '~/client/services/AdminCustomizeContainer';
-import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
-import CropLogoModal from './CropLogoModal';
-
-class CustomizeLogoSetting extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.state = {
-      show: false,
-      src: null,
-    };
-
-    // this.imageRef = null;
-    this.onSelectFile = this.onSelectFile.bind(this);
-    this.onClickDeleteBtn = this.onClickDeleteBtn.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);
-  }
-
-  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 onClickSubmit() {
-    const { t, adminCustomizeContainer } = this.props;
-
-    try {
-      await adminCustomizeContainer.updateCustomizeLogo();
-      toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.custom_logo') }));
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }
-
-  async onClickDeleteBtn() {
-    const { t, adminCustomizeContainer } = this.props;
-    try {
-      await adminCustomizeContainer.deleteLogo();
-      toastSuccess(t('toaster.update_successed', { target: t('Current Image') }));
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }
-
-  async onCropCompleted(croppedImage) {
-    const { t, adminCustomizeContainer } = this.props;
-    try {
-      await adminCustomizeContainer.uploadAttachment(croppedImage);
-      toastSuccess(t('toaster.update_successed', { target: t('Current Image') }));
-    }
-    catch (err) {
-      toastError(err);
-    }
-    this.hideModal();
-  }
-
-
-  hideModal() {
-    this.setState({ show: false });
-  }
-
-  cancelModal() {
-    this.hideModal();
-  }
-
-  render() {
-    const { t, adminCustomizeContainer } = this.props;
-    const {
-      uploadedLogoSrc, isUploadedLogo, isDefaultLogo, defaultLogoSrc,
-    } = adminCustomizeContainer.state;
-
-    return (
-      <React.Fragment>
-        <div className="row">
-          <div className="col-12">
-            <h2 className="admin-setting-header">{t('admin:customize_setting.custom_logo')}</h2>
-            <div className="row">
-              <div className="col-md-6 col-12">
-                <h4>
-                  <div className="custom-control custom-radio radio-primary">
-                    <input
-                      type="radio"
-                      id="radioDefaultLogo"
-                      className="custom-control-input"
-                      form="formImageType"
-                      name="imagetypeForm[isDefaultLogo]"
-                      checked={isDefaultLogo}
-                      onChange={() => { adminCustomizeContainer.switchDefaultLogo() }}
-                    />
-                    <label className="custom-control-label" htmlFor="radioDefaultLogo">
-                      Default Logo
-                    </label>
-                  </div>
-                </h4>
-                <img src={defaultLogoSrc} width="64" />
-              </div>
-              <div className="col-md-6 col-12">
-                <h4>
-                  <div className="custom-control custom-radio radio-primary">
-                    <input
-                      type="radio"
-                      id="radioUploadLogo"
-                      className="custom-control-input"
-                      form="formImageType"
-                      name="imagetypeForm[isDefaultLogo]"
-                      checked={!isDefaultLogo}
-                      onChange={() => { adminCustomizeContainer.switchDefaultLogo() }}
-                    />
-                    <label className="custom-control-label" htmlFor="radioUploadLogo">
-                      { t('Upload Logo') }
-                    </label>
-                  </div>
-                </h4>
-                <div className="row mb-3">
-                  <label className="col-sm-4 col-12 col-form-label text-left">
-                    { t('Current Logo') }
-                  </label>
-                  <div className="col-sm-8 col-12">
-                    {uploadedLogoSrc && (<p><img src={uploadedLogoSrc} className="picture picture-lg " id="settingBrandLogo" width="64" /></p>)}
-                    {isUploadedLogo && <button type="button" className="btn btn-danger" onClick={this.onClickDeleteBtn}>{ t('Delete Logo') }</button>}
-                  </div>
-                </div>
-                <div className="row">
-                  <label className="col-sm-4 col-12 col-form-label text-left">
-                    {t('Upload new logo')}
-                  </label>
-                  <div className="col-sm-8 col-12">
-                    <input type="file" onChange={this.onSelectFile} name="brandLogo" accept="image/*" />
-                  </div>
-                </div>
-              </div>
-            </div>
-            <AdminUpdateButtonRow onClick={this.onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
-          </div>
-        </div>
-
-        <CropLogoModal
-          show={this.state.show}
-          src={this.state.src}
-          onModalClose={this.cancelModal}
-          onCropCompleted={this.onCropCompleted}
-        />
-      </React.Fragment>
-    );
-  }
-
-}
-
-const CustomizeLogoSettingWrapper = withUnstatedContainers(CustomizeLogoSetting, [AppContainer, AdminCustomizeContainer]);
-
-CustomizeLogoSetting.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  adminCustomizeContainer: PropTypes.instanceOf(AdminCustomizeContainer).isRequired,
-};
-
-export default withTranslation()(CustomizeLogoSettingWrapper);

+ 71 - 11
packages/app/src/components/Admin/Customize/CustomizeLogoSetting.tsx

@@ -1,6 +1,5 @@
-import React, { FC } from 'react';
-import PropTypes from 'prop-types';
-import { useTranslation, withTranslation } from 'react-i18next';
+import React, { FC, useState } from 'react';
+import { useTranslation } from 'react-i18next';
 
 import { withUnstatedContainers } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
@@ -11,9 +10,68 @@ import AdminCustomizeContainer from '~/client/services/AdminCustomizeContainer';
 import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 import CropLogoModal from './CropLogoModal';
 
+type Props = {
+  adminCustomizeContainer : AdminCustomizeContainer
+}
 
 const CustomizeLogoSetting: FC<Props> = (props: Props) => {
 
+  const { t } = useTranslation();
+  const { adminCustomizeContainer } = props;
+  const [isShow, setIsShow] = useState<boolean>(false);
+  const [src, setSrc] = useState<ArrayBuffer | string | null>(null);
+  const {
+    uploadedLogoSrc, isUploadedLogo, isDefaultLogo, defaultLogoSrc,
+  } = adminCustomizeContainer.state;
+
+  const hideModal = () => {
+    setIsShow(false);
+  };
+
+  const cancelModal = () => {
+    hideModal();
+  };
+
+  const onSelectFile = (e) => {
+    if (e.target.files && e.target.files.length > 0) {
+      const reader = new FileReader();
+      reader.addEventListener('load', () => setSrc(reader.result));
+      reader.readAsDataURL(e.target.files[0]);
+      setIsShow(true);
+    }
+  };
+
+  const onClickSubmit = async() => {
+    try {
+      await adminCustomizeContainer.updateCustomizeLogo();
+      toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.custom_logo') }));
+    }
+    catch (err) {
+      toastError(err);
+    }
+  };
+
+  const onClickDeleteBtn = async() => {
+    try {
+      await adminCustomizeContainer.deleteLogo();
+      toastSuccess(t('toaster.update_successed', { target: t('Current Image') }));
+    }
+    catch (err) {
+      toastError(err);
+    }
+  };
+
+  const onCropCompleted = async(croppedImage) => {
+    try {
+      await adminCustomizeContainer.uploadAttachment(croppedImage);
+      toastSuccess(t('toaster.update_successed', { target: t('Current Image') }));
+    }
+    catch (err) {
+      toastError(err);
+    }
+    hideModal();
+  };
+
 
   return (
     <React.Fragment>
@@ -63,7 +121,7 @@ const CustomizeLogoSetting: FC<Props> = (props: Props) => {
                 </label>
                 <div className="col-sm-8 col-12">
                   {uploadedLogoSrc && (<p><img src={uploadedLogoSrc} className="picture picture-lg " id="settingBrandLogo" width="64" /></p>)}
-                  {isUploadedLogo && <button type="button" className="btn btn-danger" onClick={this.onClickDeleteBtn}>{ t('Delete Logo') }</button>}
+                  {isUploadedLogo && <button type="button" className="btn btn-danger" onClick={onClickDeleteBtn}>{ t('Delete Logo') }</button>}
                 </div>
               </div>
               <div className="row">
@@ -71,25 +129,27 @@ const CustomizeLogoSetting: FC<Props> = (props: Props) => {
                   {t('Upload new logo')}
                 </label>
                 <div className="col-sm-8 col-12">
-                  <input type="file" onChange={this.onSelectFile} name="brandLogo" accept="image/*" />
+                  <input type="file" onChange={onSelectFile} name="brandLogo" accept="image/*" />
                 </div>
               </div>
             </div>
           </div>
-          <AdminUpdateButtonRow onClick={this.onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
+          <AdminUpdateButtonRow onClick={onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
         </div>
       </div>
 
       <CropLogoModal
-        show={this.state.show}
-        src={this.state.src}
-        onModalClose={this.cancelModal}
-        onCropCompleted={this.onCropCompleted}
+        show={isShow}
+        src={src}
+        onModalClose={cancelModal}
+        onCropCompleted={onCropCompleted}
       />
     </React.Fragment>
   );
+
+
 };
 
-const CustomizeLogoSettingWrapper = withUnstatedContainers(CustomizeLogoSetting, [AppContainer]);
+const CustomizeLogoSettingWrapper = withUnstatedContainers(CustomizeLogoSetting, [AppContainer, AdminCustomizeContainer]);
 
 export default CustomizeLogoSettingWrapper;

+ 9 - 1
packages/app/src/server/routes/attachment.js

@@ -710,7 +710,15 @@ module.exports = function(crowi, app) {
 
     const file = req.file;
     const attachmentType = req.body.attachmentType;
-    const attachmentId = req.body.attachmentId !== 'null' ? mongoose.Types.ObjectId(req.body.attachmentId) : null;
+
+    let attachmentId;
+    if (req.body.attachmentId === 'null' || req.body.attachmentId === 'undefined') {
+      attachmentId = null;
+    }
+    else {
+      attachmentId = mongoose.Types.ObjectId(req.body.attachmentId);
+    }
+
     // check type
     const acceptableFileType = /image\/.+/;
     if (!file.mimetype.match(acceptableFileType)) {