Sfoglia il codice sorgente

Store and retrieve attachment in logo setting

https://youtrack.weseek.co.jp/issue/GW-7772
- Set logoPath from attachment logo id
- Set attachmentID to null on delete logo
- Store logo on crop completed
- Modify variable name of attachmentLogoId
- Modify attachmentId validation rule
- Get logo/attachment object id from string
- Add remove barnd logo api route
I Komang Mudana 4 anni fa
parent
commit
bbe81d4871

+ 21 - 10
packages/app/src/client/services/AdminCustomizeContainer.js

@@ -56,7 +56,7 @@ export default class AdminCustomizeContainer extends Container {
         'tomorrow-night':   { name: '[Dark] Tomorrow Night',  border: false },
         'tomorrow-night':   { name: '[Dark] Tomorrow Night',  border: false },
         'vs2015':           { name: '[Dark] Vs 2015',         border: false },
         'vs2015':           { name: '[Dark] Vs 2015',         border: false },
       },
       },
-      uploadedLogoSrc: this.getUploadedLogoSrc(),
+      uploadedLogoSrc: '',
       isUploadedLogo: false,
       isUploadedLogo: false,
       defaultLogoSrc: DEFAULT_LOGO,
       defaultLogoSrc: DEFAULT_LOGO,
       isDefaultLogo: false,
       isDefaultLogo: false,
@@ -67,7 +67,6 @@ export default class AdminCustomizeContainer extends Container {
     this.switchPageListLimitationM = this.switchPageListLimitationM.bind(this);
     this.switchPageListLimitationM = this.switchPageListLimitationM.bind(this);
     this.switchPageListLimitationL = this.switchPageListLimitationL.bind(this);
     this.switchPageListLimitationL = this.switchPageListLimitationL.bind(this);
     this.switchPageListLimitationXL = this.switchPageListLimitationXL.bind(this);
     this.switchPageListLimitationXL = this.switchPageListLimitationXL.bind(this);
-    this.getUploadedLogoSrc = this.getUploadedLogoSrc.bind(this);
     this.deleteLogo = this.deleteLogo.bind(this);
     this.deleteLogo = this.deleteLogo.bind(this);
     this.uploadAttachment = this.uploadAttachment.bind(this);
     this.uploadAttachment = this.uploadAttachment.bind(this);
 
 
@@ -106,12 +105,23 @@ export default class AdminCustomizeContainer extends Container {
         currentCustomizeHeader: customizeParams.customizeHeader,
         currentCustomizeHeader: customizeParams.customizeHeader,
         currentCustomizeCss: customizeParams.customizeCss,
         currentCustomizeCss: customizeParams.customizeCss,
         currentCustomizeScript: customizeParams.customizeScript,
         currentCustomizeScript: customizeParams.customizeScript,
-        attachmentId: customizeParams.attachmentId,
+        attachmentId: customizeParams.attachmentLogoId,
         isDefaultLogo: customizeParams.isDefaultLogo,
         isDefaultLogo: customizeParams.isDefaultLogo,
       });
       });
-      console.log(this.state);
       // search style name from object for display
       // search style name from object for display
       this.setState({ currentHighlightJsStyleName: this.state.highlightJsCssSelectorOptions[customizeParams.styleName].name });
       this.setState({ currentHighlightJsStyleName: this.state.highlightJsCssSelectorOptions[customizeParams.styleName].name });
+
+      // set current uploaded logo
+      if (customizeParams.attachmentLogoId) {
+        const logoPath = `/attachment/${customizeParams.attachmentLogoId}`;
+
+        this.setState({ isUploadedLogo: true });
+        this.setState({ uploadedLogoSrc: logoPath });
+      }
+      else {
+        this.setState({ isUploadedLogo: false });
+        this.setState({ uploadedLogoSrc: DEFAULT_LOGO });
+      }
     }
     }
     catch (err) {
     catch (err) {
       this.setState({ retrieveError: err });
       this.setState({ retrieveError: err });
@@ -440,20 +450,21 @@ export default class AdminCustomizeContainer extends Container {
     }
     }
   }
   }
 
 
-  getUploadedLogoSrc() {
-    this.setState({ isUploadedLogo: false });
-    return DEFAULT_LOGO;
-  }
 
 
   async deleteLogo() {
   async deleteLogo() {
     try {
     try {
-      // await this.appContainer.apiPost('/attachments.removeProfileImage', { _csrf: this.appContainer.csrfToken });
+      const formData = {
+        _csrf:  this.appContainer.csrfToken,
+        attachmentId: this.state.attachmentId,
+      };
+      await this.appContainer.apiPost('/attachments.removeBrandLogo', formData);
       this.setState({ isUploadedLogo: false, uploadedLogoSrc: DEFAULT_LOGO });
       this.setState({ isUploadedLogo: false, uploadedLogoSrc: DEFAULT_LOGO });
+      this.setState({ attachmentId: null });
     }
     }
     catch (err) {
     catch (err) {
       this.setState({ retrieveError: err });
       this.setState({ retrieveError: err });
       logger.error(err);
       logger.error(err);
-      throw new Error('Failed to delete profile image');
+      throw new Error('Failed to delete logo');
     }
     }
   }
   }
 
 

+ 9 - 3
packages/app/src/components/Admin/Customize/CustomizeLogoSetting.jsx

@@ -19,7 +19,6 @@ class CustomizeLogoSetting extends React.Component {
     this.state = {
     this.state = {
       show: false,
       show: false,
       src: null,
       src: null,
-      croppedImage: null,
     };
     };
 
 
     // this.imageRef = null;
     // this.imageRef = null;
@@ -44,7 +43,7 @@ class CustomizeLogoSetting extends React.Component {
     const { t, adminCustomizeContainer } = this.props;
     const { t, adminCustomizeContainer } = this.props;
 
 
     try {
     try {
-      await adminCustomizeContainer.uploadAttachment(this.state.croppedImage);
+      await adminCustomizeContainer.updateCustomizeLogo();
       toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.custom_script') }));
       toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.custom_script') }));
     }
     }
     catch (err) {
     catch (err) {
@@ -64,7 +63,14 @@ class CustomizeLogoSetting extends React.Component {
   }
   }
 
 
   async onCropCompleted(croppedImage) {
   async onCropCompleted(croppedImage) {
-    this.setState({ 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();
     this.hideModal();
   }
   }
 
 

+ 2 - 2
packages/app/src/server/models/config.ts

@@ -135,7 +135,7 @@ export const defaultCrowiConfigs: { [key: string]: any } = {
   'customize:isEnabledStaleNotification': false,
   'customize:isEnabledStaleNotification': false,
   'customize:isAllReplyShown': false,
   'customize:isAllReplyShown': false,
   'customize:isSearchScopeChildrenAsDefault': false,
   'customize:isSearchScopeChildrenAsDefault': false,
-  'customize:attachmentId' : '',
+  'customize:attachmentLogoId' : undefined,
   'customize:isDefaultLogo': true,
   'customize:isDefaultLogo': true,
 
 
   'notification:owner-page:isEnabled': false,
   'notification:owner-page:isEnabled': false,
@@ -245,7 +245,7 @@ schema.statics.getLocalconfig = function(crowi) {
     pageLimitationL: crowi.configManager.getConfig('crowi', 'customize:showPageLimitationL'),
     pageLimitationL: crowi.configManager.getConfig('crowi', 'customize:showPageLimitationL'),
     pageLimitationXL: crowi.configManager.getConfig('crowi', 'customize:showPageLimitationXL'),
     pageLimitationXL: crowi.configManager.getConfig('crowi', 'customize:showPageLimitationXL'),
     isDefaultLogo:  crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'),
     isDefaultLogo:  crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'),
-    attachmentId: crowi.configManager.getConfig('crowi', 'customize:attachmentId'),
+    attachmentLogoId: crowi.configManager.getConfig('crowi', 'customize:attachmentLogoId'),
   };
   };
 
 
   return localConfig;
   return localConfig;

+ 4 - 4
packages/app/src/server/routes/apiv3/customize-setting.js

@@ -136,7 +136,7 @@ module.exports = (crowi) => {
       body('customizeScript').isString(),
       body('customizeScript').isString(),
     ],
     ],
     logo: [
     logo: [
-      body('attachmentId').isString(),
+      body('attachmentId').isString().optional({ nullable: true }),
       body('isDefaultLogo').isBoolean(),
       body('isDefaultLogo').isBoolean(),
     ],
     ],
   };
   };
@@ -181,7 +181,7 @@ module.exports = (crowi) => {
       customizeHeader: await crowi.configManager.getConfig('crowi', 'customize:header'),
       customizeHeader: await crowi.configManager.getConfig('crowi', 'customize:header'),
       customizeCss: await crowi.configManager.getConfig('crowi', 'customize:css'),
       customizeCss: await crowi.configManager.getConfig('crowi', 'customize:css'),
       customizeScript: await crowi.configManager.getConfig('crowi', 'customize:script'),
       customizeScript: await crowi.configManager.getConfig('crowi', 'customize:script'),
-      attachmentId: await crowi.configManager.getConfig('crowi', 'customize:attachmentId'),
+      attachmentLogoId: await crowi.configManager.getConfig('crowi', 'customize:attachmentLogoId'),
       isDefaultLogo: await crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'),
       isDefaultLogo: await crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'),
     };
     };
 
 
@@ -617,13 +617,13 @@ module.exports = (crowi) => {
 
 
   router.put('/customize-logo', loginRequiredStrictly, adminRequired, csrf, validator.logo, apiV3FormValidator, async(req, res) => {
   router.put('/customize-logo', loginRequiredStrictly, adminRequired, csrf, validator.logo, apiV3FormValidator, async(req, res) => {
     const requestParams = {
     const requestParams = {
-      'customize:attachmentId': req.body.attachmentId,
+      'customize:attachmentLogoId': req.body.attachmentId,
       'customize:isDefaultLogo': req.body.isDefaultLogo,
       'customize:isDefaultLogo': req.body.isDefaultLogo,
     };
     };
     try {
     try {
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       const customizedParams = {
       const customizedParams = {
-        attachmentId: await crowi.configManager.getConfig('crowi', 'customize:attachmentId'),
+        attachmentLogoId: await crowi.configManager.getConfig('crowi', 'customize:attachmentLogoId'),
         isDefaultLogo: await crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'),
         isDefaultLogo: await crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'),
       };
       };
       return res.apiv3({ customizedParams });
       return res.apiv3({ customizedParams });

+ 28 - 3
packages/app/src/server/routes/attachment.js

@@ -1,5 +1,5 @@
+import mongoose from 'mongoose';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
-
 /* eslint-disable no-use-before-define */
 /* eslint-disable no-use-before-define */
 
 
 
 
@@ -710,14 +710,18 @@ module.exports = function(crowi, app) {
 
 
     const file = req.file;
     const file = req.file;
     const attachmentType = req.body.attachmentType;
     const attachmentType = req.body.attachmentType;
-    const attachmentId = req.body.attachmentId;
-    console.log(attachmentId);
+    const attachmentId = req.body.attachmentId !== 'null' ? mongoose.Types.ObjectId(req.body.attachmentId) : null;
     // check type
     // check type
     const acceptableFileType = /image\/.+/;
     const acceptableFileType = /image\/.+/;
     if (!file.mimetype.match(acceptableFileType)) {
     if (!file.mimetype.match(acceptableFileType)) {
       return res.json(ApiResponse.error('File type error. Only image files is allowed to set as user picture.'));
       return res.json(ApiResponse.error('File type error. Only image files is allowed to set as user picture.'));
     }
     }
 
 
+    // remove previous attachment
+    if (attachmentId) {
+      await attachmentService.removeAttachment(attachmentId);
+    }
+
     let attachment;
     let attachment;
     try {
     try {
       attachment = await attachmentService.createAttachment(file, req.user, null, attachmentType);
       attachment = await attachmentService.createAttachment(file, req.user, null, attachmentType);
@@ -734,5 +738,26 @@ module.exports = function(crowi, app) {
     return res.json(ApiResponse.success(result));
     return res.json(ApiResponse.success(result));
   };
   };
 
 
+  api.removeBrandLogo = async function(req, res) {
+    const attachmentId = mongoose.Types.ObjectId(req.body.attachmentId);
+    const attachment = await Attachment.findById(attachmentId);
+
+    if (attachment == null) {
+      return res.json(ApiResponse.error('attachment not found'));
+    }
+
+    try {
+      await attachmentService.removeAttachment(attachmentId);
+      // update attachmentLogoId immediately
+      await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'customize:attachmentLogoId': null });
+    }
+    catch (err) {
+      logger.error(err);
+      return res.status(500).json(ApiResponse.error('Error while deleting logo'));
+    }
+
+    return res.json(ApiResponse.success({}));
+  };
+
   return actions;
   return actions;
 };
 };

+ 1 - 0
packages/app/src/server/routes/index.js

@@ -189,6 +189,7 @@ module.exports = function(crowi, app) {
   apiV1Router.post('/attachments.removeProfileImage'   , accessTokenParser , loginRequiredStrictly , csrf, attachment.api.removeProfileImage);
   apiV1Router.post('/attachments.removeProfileImage'   , accessTokenParser , loginRequiredStrictly , csrf, attachment.api.removeProfileImage);
   apiV1Router.get('/attachments.limit'   , accessTokenParser , loginRequiredStrictly, attachment.api.limit);
   apiV1Router.get('/attachments.limit'   , accessTokenParser , loginRequiredStrictly, attachment.api.limit);
   apiV1Router.post('/attachments.uploadBrandLogo'   , uploads.single('file'), autoReap, accessTokenParser, loginRequiredStrictly ,csrf, attachment.api.uploadBrandLogo);
   apiV1Router.post('/attachments.uploadBrandLogo'   , uploads.single('file'), autoReap, accessTokenParser, loginRequiredStrictly ,csrf, attachment.api.uploadBrandLogo);
+  apiV1Router.post('/attachments.removeBrandLogo'      , accessTokenParser , loginRequiredStrictly , csrf, attachment.api.removeBrandLogo);
 
 
   // API v1
   // API v1
   app.use('/_api', unavailableWhenMaintenanceModeForApi, apiV1Router);
   app.use('/_api', unavailableWhenMaintenanceModeForApi, apiV1Router);