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

Merge branch 'reactify-admin/enable-aws-setting' into reactify-admin/enable-plugin-setting

yusuketk 6 лет назад
Родитель
Сommit
eb9af049d0

+ 43 - 68
src/client/js/components/Admin/App/AppSetting.jsx

@@ -8,6 +8,7 @@ import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
 import AdminAppContainer from '../../../services/AdminAppContainer';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:appSettings');
 
@@ -37,47 +38,35 @@ class AppSetting extends React.Component {
 
     return (
       <React.Fragment>
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label className="col-xs-3 control-label">{t('app_setting.Site Name')}</label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[app:title]"
-                  type="text"
-                  name="title"
-                  defaultValue={adminAppContainer.state.title}
-                  onChange={(e) => { adminAppContainer.changeTitle(e.target.value) }}
-                  placeholder="GROWI"
-                />
-                <p className="help-block">{t('app_setting.sitename_change')}</p>
-              </div>
-            </div>
+        <div className="row md-5">
+          <label className="col-xs-3 control-label">{t('app_setting.Site Name')}</label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              defaultValue={adminAppContainer.state.title}
+              onChange={(e) => { adminAppContainer.changeTitle(e.target.value) }}
+              placeholder="GROWI"
+            />
+            <p className="help-block">{t('app_setting.sitename_change')}</p>
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label className="col-xs-3 control-label">{t('app_setting.Confidential name')}</label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[app:confidential]"
-                  type="text"
-                  name="confidential"
-                  defaultValue={adminAppContainer.state.confidential}
-                  onChange={(e) => { adminAppContainer.changeConfidential(e.target.value) }}
-                  placeholder={t('app_setting.ex) internal use only')}
-                />
-                <p className="help-block">{t('app_setting.header_content')}</p>
-              </div>
-            </div>
+        <div className="row md-5">
+          <label className="col-xs-3 control-label">{t('app_setting.Confidential name')}</label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              defaultValue={adminAppContainer.state.confidential}
+              onChange={(e) => { adminAppContainer.changeConfidential(e.target.value) }}
+              placeholder={t('app_setting.ex) internal use only')}
+            />
+            <p className="help-block">{t('app_setting.header_content')}</p>
           </div>
         </div>
 
-        <div className="form-group">
+        <div className="row md-5">
           <label className="col-xs-3 control-label">{t('app_setting.Default Language for new users')}</label>
           <div className="col-xs-6">
             <div className="radio radio-primary radio-inline">
@@ -105,43 +94,29 @@ class AppSetting extends React.Component {
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label className="col-xs-3 control-label">{t('app_setting.File Uploading')}</label>
-              <div className="col-xs-6">
-                <div className="checkbox checkbox-info">
-                  <input
-                    type="checkbox"
-                    id="cbFileUpload"
-                    name="fileUpload"
-                    checked={adminAppContainer.state.fileUpload}
-                    onChange={(e) => { adminAppContainer.changeFileUpload(e.target.checked) }}
-                  />
-                  <label htmlFor="cbFileUpload">{t('app_setting.enable_files_except_image')}</label>
-                </div>
-
-                <p className="help-block">
-                  {t('app_setting.enable_files_except_image')}
-                  <br />
-                  {t('app_setting.attach_enable')}
-                </p>
-              </div>
+        <div className="row md-5">
+          <label className="col-xs-3 control-label">{t('app_setting.File Uploading')}</label>
+          <div className="col-xs-6">
+            <div className="checkbox checkbox-info">
+              <input
+                type="checkbox"
+                id="cbFileUpload"
+                name="fileUpload"
+                checked={adminAppContainer.state.fileUpload}
+                onChange={(e) => { adminAppContainer.changeFileUpload(e.target.checked) }}
+              />
+              <label htmlFor="cbFileUpload">{t('app_setting.enable_files_except_image')}</label>
             </div>
-          </div>
-        </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <div className="col-xs-offset-3 col-xs-6">
-                <button type="submit" className="btn btn-primary" onClick={this.submitHandler}>
-                  {t('app_setting.Update')}
-                </button>
-              </div>
-            </div>
+            <p className="help-block">
+              {t('app_setting.enable_files_except_image')}
+              <br />
+              {t('app_setting.attach_enable')}
+            </p>
           </div>
         </div>
+
+        <AdminUpdateButtonRow onClick={this.submitHandler} disabled={adminAppContainer.state.retrieveError != null} />
       </React.Fragment>
     );
   }

+ 70 - 110
src/client/js/components/Admin/App/AwsSetting.jsx

@@ -8,6 +8,7 @@ import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
 import AdminAppContainer from '../../../services/AdminAppContainer';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:appSettings');
 
@@ -49,131 +50,90 @@ class AwsSetting extends React.Component {
           </span>
         </p>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label htmlFor="settingForm[app:region]" className="col-xs-3 control-label">
-                {t('app_setting.region')}
-              </label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[app:region]"
-                  type="text"
-                  name="settingForm[aws:region]"
-                  placeholder={`${t('eg')} ap-northeast-1`}
-                  defaultValue={adminAppContainer.state.region}
-                  onChange={(e) => {
-                    adminAppContainer.changeRegion(e.target.value);
-                  }}
-                />
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">
+            {t('app_setting.region')}
+          </label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              placeholder={`${t('eg')} ap-northeast-1`}
+              defaultValue={adminAppContainer.state.region}
+              onChange={(e) => {
+                adminAppContainer.changeRegion(e.target.value);
+              }}
+            />
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label htmlFor="settingForm[aws:customEndpoint]" className="col-xs-3 control-label">
-                {t('app_setting.custom endpoint')}
-              </label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[aws:customEndpoint]"
-                  type="text"
-                  name="settingForm[aws:customEndpoint]"
-                  placeholder={`${t('eg')} http://localhost:9000`}
-                  defaultValue={adminAppContainer.state.customEndpoint}
-                  onChange={(e) => {
-                    adminAppContainer.changeCustomEndpoint(e.target.value);
-                  }}
-                />
-                <p className="help-block">{t('app_setting.custom_endpoint_change')}</p>
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">
+            {t('app_setting.custom endpoint')}
+          </label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              placeholder={`${t('eg')} http://localhost:9000`}
+              defaultValue={adminAppContainer.state.customEndpoint}
+              onChange={(e) => {
+                adminAppContainer.changeCustomEndpoint(e.target.value);
+              }}
+            />
+            <p className="help-block">{t('app_setting.custom_endpoint_change')}</p>
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label htmlFor="settingForm[aws:bucket]" className="col-xs-3 control-label">
-                {t('app_setting.bucket name')}
-              </label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[aws:bucket]"
-                  type="text"
-                  name="settingForm[aws:bucket]"
-                  placeholder={`${t('eg')} crowi`}
-                  defaultValue={adminAppContainer.state.bucket}
-                  onChange={(e) => {
-                    adminAppContainer.changeBucket(e.target.value);
-                  }}
-                />
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">
+            {t('app_setting.bucket name')}
+          </label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              placeholder={`${t('eg')} crowi`}
+              defaultValue={adminAppContainer.state.bucket}
+              onChange={(e) => {
+                adminAppContainer.changeBucket(e.target.value);
+              }}
+            />
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label htmlFor="settingForm[aws:accessKeyId]" className="col-xs-3 control-label">
-                Access Key ID
-              </label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[aws:accessKeyId]"
-                  type="text"
-                  name="settingForm[aws:accessKeyId]"
-                  defaultValue={adminAppContainer.state.accessKeyId}
-                  onChange={(e) => {
-                    adminAppContainer.changeAccessKeyId(e.target.value);
-                  }}
-                />
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">
+            Access Key ID
+          </label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              defaultValue={adminAppContainer.state.accessKeyId}
+              onChange={(e) => {
+                adminAppContainer.changeAccessKeyId(e.target.value);
+              }}
+            />
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label htmlFor="settingForm[aws:secretAccessKey]" className="col-xs-3 control-label">
-                Secret Access Key
-              </label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[aws:secretAccessKey]"
-                  type="text"
-                  name="settingForm[aws:secretAccessKey]"
-                  defaultValue={adminAppContainer.state.secretKey}
-                  onChange={(e) => {
-                    adminAppContainer.changeSecretKey(e.target.value);
-                  }}
-                />
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">
+            Secret Access Key
+          </label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              defaultValue={adminAppContainer.state.secretKey}
+              onChange={(e) => {
+                adminAppContainer.changeSecretKey(e.target.value);
+              }}
+            />
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <div className="col-xs-offset-3 col-xs-6">
-                <button type="submit" className="btn btn-primary" onClick={this.submitHandler}>
-                  {t('app_setting.Update')}
-                </button>
-              </div>
-            </div>
-          </div>
-        </div>
+        <AdminUpdateButtonRow onClick={this.submitHandler} disabled={adminAppContainer.state.retrieveError != null} />
       </React.Fragment>
     );
   }

+ 48 - 76
src/client/js/components/Admin/App/MailSetting.jsx

@@ -8,6 +8,7 @@ import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
 import AdminAppContainer from '../../../services/AdminAppContainer';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:appSettings');
 
@@ -38,91 +39,62 @@ class MailSetting extends React.Component {
     return (
       <React.Fragment>
         <p className="well">{t('app_setting.SMTP_used')} {t('app_setting.SMTP_but_AWS')}<br />{t('app_setting.neihter_of')}</p>
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label htmlFor="settingForm[mail.from]" className="col-xs-3 control-label">{t('app_setting.From e-mail address')}</label>
-              <div className="col-xs-6">
-                <input
-                  className="form-control"
-                  id="settingForm[mail.from]"
-                  type="text"
-                  name="settingForm[mail:from]"
-                  placeholder={`${t('eg')} mail@growi.org`}
-                  defaultValue={adminAppContainer.state.fromAddress}
-                  onChange={(e) => { adminAppContainer.changeFromAddress(e.target.value) }}
-                />
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">{t('app_setting.From e-mail address')}</label>
+          <div className="col-xs-6">
+            <input
+              className="form-control"
+              type="text"
+              placeholder={`${t('eg')} mail@growi.org`}
+              defaultValue={adminAppContainer.state.fromAddress}
+              onChange={(e) => { adminAppContainer.changeFromAddress(e.target.value) }}
+            />
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <label className="col-xs-3 control-label">{ t('app_setting.SMTP settings') }</label>
-              <div className="col-xs-4">
-                <label>{ t('app_setting.Host') }</label>
-                <input
-                  className="form-control"
-                  type="text"
-                  name="settingForm[mail:smtpHost]"
-                  defaultValue={adminAppContainer.state.smtpHost}
-                  onChange={(e) => { adminAppContainer.changeSmtpHost(e.target.value) }}
-                />
-              </div>
-              <div className="col-xs-2">
-                <label>{ t('app_setting.Port') }</label>
-                <input
-                  className="form-control"
-                  type="text"
-                  name="settingForm[mail:smtpPort]"
-                  defaultValue={adminAppContainer.state.smtpPort}
-                  onChange={(e) => { adminAppContainer.changeSmtpPort(e.target.value) }}
-                />
-              </div>
-            </div>
+        <div className="row mb-5">
+          <label className="col-xs-3 control-label">{ t('app_setting.SMTP settings') }</label>
+          <div className="col-xs-4">
+            <label>{ t('app_setting.Host') }</label>
+            <input
+              className="form-control"
+              type="text"
+              defaultValue={adminAppContainer.state.smtpHost}
+              onChange={(e) => { adminAppContainer.changeSmtpHost(e.target.value) }}
+            />
           </div>
-        </div>
-
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <div className="col-xs-3 col-xs-offset-3">
-                <label>{ t('app_setting.User') }</label>
-                <input
-                  className="form-control"
-                  type="text"
-                  name="settingForm[mail:smtpUser]"
-                  defaultValue={adminAppContainer.state.SmtpUser}
-                  onChange={(e) => { adminAppContainer.changeSmtpUser(e.target.value) }}
-                />
-              </div>
-              <div className="col-xs-3">
-                <label>{ t('Password') }</label>
-                <input
-                  className="form-control"
-                  type="password"
-                  name="settingForm[mail:smtpPassword]"
-                  defaultValue={adminAppContainer.state.smtpPassword}
-                  onChange={(e) => { adminAppContainer.changeSmtpPassword(e.target.value) }}
-                />
-              </div>
-            </div>
+          <div className="col-xs-2">
+            <label>{ t('app_setting.Port') }</label>
+            <input
+              className="form-control"
+              defaultValue={adminAppContainer.state.smtpPort}
+              onChange={(e) => { adminAppContainer.changeSmtpPort(e.target.value) }}
+            />
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <div className="col-xs-offset-3 col-xs-6">
-                <button type="submit" className="btn btn-primary" onClick={this.submitHandler}>
-                  {t('app_setting.Update')}
-                </button>
-              </div>
-            </div>
+        <div className="row mb-5">
+          <div className="col-xs-3 col-xs-offset-3">
+            <label>{ t('app_setting.User') }</label>
+            <input
+              className="form-control"
+              type="text"
+              defaultValue={adminAppContainer.state.SmtpUser}
+              onChange={(e) => { adminAppContainer.changeSmtpUser(e.target.value) }}
+            />
+          </div>
+          <div className="col-xs-3">
+            <label>{ t('Password') }</label>
+            <input
+              className="form-control"
+              type="password"
+              defaultValue={adminAppContainer.state.smtpPassword}
+              onChange={(e) => { adminAppContainer.changeSmtpPassword(e.target.value) }}
+            />
           </div>
         </div>
+
+        <AdminUpdateButtonRow onClick={this.submitHandler} disabled={adminAppContainer.state.retrieveError != null} />
       </React.Fragment>
     );
   }

+ 17 - 31
src/client/js/components/Admin/App/PluginSetting.jsx

@@ -7,6 +7,8 @@ import { createSubscribedElement } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
+import AdminAppContainer from '../../../services/AdminAppContainer';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 // eslint-disable-next-line no-unused-vars
 const logger = loggerFactory('growi:app:pluginSetting');
@@ -16,21 +18,15 @@ class PluginSetting extends React.Component {
   constructor(props) {
     super(props);
 
-    this.state = {
-      // TODO GW-690 fetch from db
-      isEnabledPlugins: true,
-    };
-
-    this.onClickSubmit = this.onClickSubmit.bind(this);
-    this.switchIsEnabledPlugins = this.switchIsEnabledPlugins.bind(this);
+    this.submitHandler = this.submitHandler.bind(this);
   }
 
-  async onClickSubmit() {
-    const { t } = this.props;
+  async submitHandler() {
+    const { t, adminAppContainer } = this.props;
 
     try {
-      // TODO GW-690 post apiV3
-      toastSuccess(t('app_setting.update', { target: 'Plugin Setting' }));
+      await adminAppContainer.updatePluginSettingHandler();
+      toastSuccess(t('app_setting.updated_plugin_setting'));
     }
     catch (err) {
       toastError(err);
@@ -38,18 +34,12 @@ class PluginSetting extends React.Component {
     }
   }
 
-  switchIsEnabledPlugins() {
-    this.setState({ isEnabledPlugins: !this.state.isEnabledPlugins });
-  }
-
-
   render() {
-    const { t } = this.props;
+    const { t, adminAppContainer } = this.props;
 
     return (
       <React.Fragment>
-
-        <p className="well">{ t('app_setting.Enable plugin loading') }</p>
+        <p className="well">{t('app_setting.Enable plugin loading')}</p>
 
         <div className="row mb-5">
           <div className="col-xs-offset-3 col-xs-6 text-left">
@@ -57,22 +47,17 @@ class PluginSetting extends React.Component {
               <input
                 id="isEnabledPlugins"
                 type="checkbox"
-                checked={this.state.isEnabledPlugins}
-                onChange={this.switchIsEnabledPlugins}
+                checked={adminAppContainer.isEnabledPlugins}
+                onChange={(e) => {
+                  adminAppContainer.changeIsEnabledPlugins(e.target.checked);
+                }}
               />
-              <label htmlFor="isEnabledPlugins">
-                { t('app_setting.Load plugins') }
-              </label>
+              <label htmlFor="isEnabledPlugins">{t('app_setting.Load plugins')}</label>
             </div>
           </div>
         </div>
 
-        <div className="row my-3">
-          <div className="col-xs-offset-4 col-xs-5">
-            <div className="btn btn-primary" onClick={this.onClickSubmit}>{ t('Update') }</div>
-          </div>
-        </div>
-
+        <AdminUpdateButtonRow onClick={this.submitHandler} disabled={adminAppContainer.state.retrieveError != null} />
       </React.Fragment>
     );
   }
@@ -83,12 +68,13 @@ class PluginSetting extends React.Component {
  * Wrapper component for using unstated
  */
 const PluginSettingWrapper = (props) => {
-  return createSubscribedElement(PluginSetting, props, [AppContainer]);
+  return createSubscribedElement(PluginSetting, props, [AppContainer, AdminAppContainer]);
 };
 
 PluginSetting.propTypes = {
   t: PropTypes.func.isRequired, // i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  adminAppContainer: PropTypes.instanceOf(AdminAppContainer).isRequired,
 };
 
 export default withTranslation()(PluginSettingWrapper);

+ 2 - 11
src/client/js/components/Admin/App/SiteUrlSetting.jsx

@@ -8,6 +8,7 @@ import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
 import AdminAppContainer from '../../../services/AdminAppContainer';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:appSettings');
 
@@ -84,17 +85,7 @@ class SiteUrlSetting extends React.Component {
           </div>
         </div>
 
-        <div className="row">
-          <div className="col-md-12">
-            <div className="form-group">
-              <div className="col-xs-offset-3 col-xs-6">
-                <button type="submit" className="btn btn-primary" onClick={this.submitHandler}>
-                  {t('app_setting.Update')}
-                </button>
-              </div>
-            </div>
-          </div>
-        </div>
+        <AdminUpdateButtonRow onClick={this.submitHandler} disabled={adminAppContainer.state.retrieveError != null} />
       </React.Fragment>
     );
   }

+ 26 - 0
src/client/js/services/AdminAppContainer.js

@@ -18,6 +18,7 @@ export default class AdminAppContainer extends Container {
     this.appContainer = appContainer;
 
     this.state = {
+      retrieveError: null,
       title: '',
       confidential: '',
       globalLang: '',
@@ -35,6 +36,7 @@ export default class AdminAppContainer extends Container {
       bucket: '',
       accessKeyId: '',
       secretKey: '',
+      isEnabledPlugins: true,
     };
 
     this.changeTitle = this.changeTitle.bind(this);
@@ -52,10 +54,12 @@ export default class AdminAppContainer extends Container {
     this.changeBucket = this.changeBucket.bind(this);
     this.changeAccessKeyId = this.changeAccessKeyId.bind(this);
     this.changeSecretKey = this.changeSecretKey.bind(this);
+    this.changeIsEnabledPlugins = this.changeIsEnabledPlugins.bind(this);
     this.updateAppSettingHandler = this.updateAppSettingHandler.bind(this);
     this.updateSiteUrlSettingHandler = this.updateSiteUrlSettingHandler.bind(this);
     this.updateMailSettingHandler = this.updateMailSettingHandler.bind(this);
     this.updateAwsSettingHandler = this.updateAwsSettingHandler.bind(this);
+    this.updatePluginSettingHandler = this.updatePluginSettingHandler.bind(this);
   }
 
   /**
@@ -91,6 +95,7 @@ export default class AdminAppContainer extends Container {
         bucket: appSettingsParams.bucket,
         accessKeyId: appSettingsParams.accessKeyId,
         secretKey: appSettingsParams.secretKey,
+        isEnabledPlugins: appSettingsParams.isEnabledPlugins,
       });
 
     }
@@ -206,6 +211,13 @@ export default class AdminAppContainer extends Container {
     this.setState({ secretKey });
   }
 
+  /**
+   * Change secret key
+   */
+  changeIsEnabledPlugins(isEnabledPlugins) {
+    this.setState({ isEnabledPlugins });
+  }
+
   /**
    * Update app setting
    * @memberOf AdminAppContainer
@@ -270,4 +282,18 @@ export default class AdminAppContainer extends Container {
     return awsSettingParams;
   }
 
+  /**
+   * Update plugin setting
+   * @memberOf AdminAppContainer
+   * @return {Array} Appearance
+   */
+  async updatePluginSettingHandler() {
+    const response = await this.appContainer.apiv3.put('/app-settings/plugin-setting', {
+      isEnabledPlugins: this.state.isEnabledPlugins,
+    });
+    const { pluginSettingParams } = response.data;
+    return pluginSettingParams;
+  }
+
+
 }

+ 65 - 28
src/server/routes/apiv3/app-settings.js

@@ -36,6 +36,9 @@ const validator = {
     body('accessKeyId').trim(),
     body('secretKey').trim(),
   ],
+  pluginSetting: [
+    body('isEnabledPlugins').isBoolean(),
+  ],
 };
 
 
@@ -52,6 +55,7 @@ const validator = {
  *    schemas:
  *      AppSettingParams:
  *        type: object
+ *        properties:
  *          title:
  *            type: String
  *            description: site name show on page header and tilte of HTML
@@ -66,6 +70,7 @@ const validator = {
  *            description: enable upload file except image file
  *     SiteUrlSettingParams:
  *        type: object
+ *        properties:
  *          siteUrl:
  *            type: String
  *            description: Site URL. e.g. https://example.com, https://example.com:8080
@@ -74,6 +79,7 @@ const validator = {
  *            description: environment variable 'APP_SITE_URL'
  *     MailSettingParams:
  *        type: object
+ *        properties:
  *          fromAddress:
  *            type: String
  *            description: e-mail address used as from address of mail which sent from GROWI app
@@ -106,6 +112,11 @@ const validator = {
  *          secretKey:
  *            type: String
  *            description: secret key for authentification of AWS
+ *      PluginSettingParams:
+ *        type: object
+ *          isEnabledPlugins:
+ *            type: String
+ *            description: enable use plugins
  */
 
 module.exports = (crowi) => {
@@ -131,10 +142,9 @@ module.exports = (crowi) => {
    *              application/json:
    *                schema:
    *                  properties:
-   *                    schema:
-   *                      $ref: '#/components/schemas/AppSettingParams'
-   *                      $ref: '#/components/schemas/SiteUrlSettingParams'
-   *                      $ref: '#/components/schemas/MailSettingParams'
+   *                    appSettingsParams:
+   *                      type: object
+   *                      description: app settings params
    */
   router.get('/', accessTokenParser, loginRequired, adminRequired, async(req, res) => {
     const appSettingsParams = {
@@ -154,6 +164,7 @@ module.exports = (crowi) => {
       bucket: crowi.configManager.getConfig('crowi', 'aws:bucket'),
       accessKeyId: crowi.configManager.getConfig('crowi', 'aws:accessKeyId'),
       secretKey: crowi.configManager.getConfig('crowi', 'aws:secretKey'),
+      isEnabledPlugins: crowi.configManager.getConfig('crowi', 'plugin:isEnabledPlugins'),
     };
     return res.apiv3({ appSettingsParams });
 
@@ -172,18 +183,14 @@ module.exports = (crowi) => {
    *          content:
    *            application/json:
    *              schema:
-   *                type: object
-   *                properties:
-   *                  $ref: '#/components/schemas/AppSettingParams'
+   *                $ref: '#/components/schemas/AppSettingParams'
    *        responses:
    *          200:
    *            description: Succeeded to update app setting
    *            content:
    *              application/json:
    *                schema:
-   *                  properties:
-   *                    status:
-   *                      $ref: '#/components/schemas/AppSettingParams'
+   *                  $ref: '#/components/schemas/AppSettingParams'
    */
   router.put('/app-setting', loginRequiredStrictly, adminRequired, csrf, validator.appSetting, ApiV3FormValidator, async(req, res) => {
     const requestAppSettingParams = {
@@ -223,18 +230,14 @@ module.exports = (crowi) => {
    *          content:
    *            application/json:
    *              schema:
-   *                type: object
-   *                properties:
-   *                  $ref: '#/components/schemas/SiteUrlSettingParams'
+   *                $ref: '#/components/schemas/SiteUrlSettingParams'
    *        responses:
    *          200:
    *            description: Succeeded to update site url setting
    *            content:
    *              application/json:
    *                schema:
-   *                  properties:
-   *                    status:
-   *                      $ref: '#/components/schemas/SiteUrlSettingParams'
+   *                  $ref: '#/components/schemas/SiteUrlSettingParams'
    */
   router.put('/site-url-setting', loginRequiredStrictly, adminRequired, csrf, validator.siteUrlSetting, ApiV3FormValidator, async(req, res) => {
 
@@ -317,18 +320,14 @@ module.exports = (crowi) => {
    *          content:
    *            application/json:
    *              schema:
-   *                type: object
-   *                properties:
-   *                  $ref: '#/components/schemas/MailSettingParams'
+   *                $ref: '#/components/schemas/MailSettingParams'
    *        responses:
    *          200:
    *            description: Succeeded to update site url setting
    *            content:
    *              application/json:
    *                schema:
-   *                  properties:
-   *                    status:
-   *                      $ref: '#/components/schemas/MailSettingParams'
+   *                  $ref: '#/components/schemas/MailSettingParams'
    */
   router.put('/mail-setting', loginRequiredStrictly, adminRequired, csrf, validator.mailSetting, ApiV3FormValidator, async(req, res) => {
     // テストメール送信によるバリデート
@@ -381,18 +380,14 @@ module.exports = (crowi) => {
    *          content:
    *            application/json:
    *              schema:
-   *                type: object
-   *                properties:
-   *                  $ref: '#/components/schemas/AwsSettingParams'
+   *                $ref: '#/components/schemas/AwsSettingParams'
    *        responses:
    *          200:
    *            description: Succeeded to update aws setting
    *            content:
    *              application/json:
    *                schema:
-   *                  properties:
-   *                    status:
-   *                      $ref: '#/components/schemas/AwsSettingParams'
+   *                  $ref: '#/components/schemas/AwsSettingParams'
    */
   router.put('/aws-setting', loginRequiredStrictly, adminRequired, csrf, validator.awsSetting, ApiV3FormValidator, async(req, res) => {
     const requestAwsSettingParams = {
@@ -421,5 +416,47 @@ module.exports = (crowi) => {
     }
 
   });
+
+  /**
+   * @swagger
+   *
+   *    /app-settings/plugin-setting:
+   *      put:
+   *        tags: [AppSettings]
+   *        description: Update plugin setting
+   *        requestBody:
+   *          required: true
+   *          content:
+   *            application/json:
+   *              schema:
+   *                $ref: '#/components/schemas/PluginSettingParams'
+   *        responses:
+   *          200:
+   *            description: Succeeded to update plugin setting
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  $ref: '#/components/schemas/PluginSettingParams'
+   */
+  router.put('/plugin-setting', loginRequiredStrictly, adminRequired, csrf, validator.pluginSetting, ApiV3FormValidator, async(req, res) => {
+    const requestPluginSettingParams = {
+      'plugin:isEnabledPlugins': req.body.isEnabledPlugins,
+    };
+
+    try {
+      await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestPluginSettingParams);
+      const pluginSettingParams = {
+        isEnabledPlugins: crowi.configManager.getConfig('crowi', 'plugin:isEnabledPlugins'),
+      };
+      return res.apiv3({ pluginSettingParams });
+    }
+    catch (err) {
+      const msg = 'Error occurred in updating plugin setting';
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(msg, 'update-pluginSetting-failed'));
+    }
+
+  });
+
   return router;
 };