itizawa 5 лет назад
Родитель
Сommit
e7da131eae

+ 41 - 129
src/client/js/components/Admin/App/MailSetting.jsx

@@ -3,14 +3,17 @@ import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import loggerFactory from '@alias/logger';
 
-import { Modal, ModalHeader, ModalBody } from 'reactstrap';
+import {
+  TabContent, TabPane, Nav, NavItem, NavLink,
+} from 'reactstrap';
 import { withUnstatedContainers } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
 import AdminAppContainer from '../../../services/AdminAppContainer';
+import SmtpSetting from './SmtpSetting';
 
-const logger = loggerFactory('growi:appSettings');
+const logger = loggerFactory('growi:mailSettings');
 
 class MailSetting extends React.Component {
 
@@ -18,7 +21,9 @@ class MailSetting extends React.Component {
     super(props);
 
     this.state = {
-      isInitializeValueModalOpen: false,
+      activeTab: 'smtp-setting',
+      // Prevent unnecessary rendering
+      activeComponents: new Set(['smtp-setting']),
     };
 
     this.emailInput = React.createRef();
@@ -27,32 +32,13 @@ class MailSetting extends React.Component {
     this.userInput = React.createRef();
     this.passwordInput = React.createRef();
 
-    this.openInitializeValueModal = this.openInitializeValueModal.bind(this);
-    this.closeInitializeValueModal = this.closeInitializeValueModal.bind(this);
     this.submitFromAdressHandler = this.submitFromAdressHandler.bind(this);
-    this.submitHandler = this.submitHandler.bind(this);
-    this.initialize = this.initialize.bind(this);
   }
 
-  openInitializeValueModal() {
-    this.setState({ isInitializeValueModalOpen: true });
-  }
-
-  closeInitializeValueModal() {
-    this.setState({ isInitializeValueModalOpen: false });
-  }
-
-  async submitHandler() {
-    const { t, adminAppContainer } = this.props;
-
-    try {
-      await adminAppContainer.updateMailSettingHandler();
-      toastSuccess(t('toaster.update_successed', { target: t('admin:app_setting.mail_settings') }));
-    }
-    catch (err) {
-      toastError(err);
-      logger.error(err);
-    }
+  toggleActiveTab(activeTab) {
+    this.setState({
+      activeTab, activeComponents: this.state.activeComponents.add(activeTab),
+    });
   }
 
   async submitFromAdressHandler() {
@@ -68,27 +54,9 @@ class MailSetting extends React.Component {
     }
   }
 
-  async initialize() {
-    const { t, adminAppContainer } = this.props;
-
-    try {
-      const mailSettingParams = await adminAppContainer.initializeMailSettingHandler();
-      toastSuccess(t('toaster.initialize_successed', { target: t('admin:app_setting.smtp_settings') }));
-      // convert values to '' if value is null for overwriting values of inputs with refs
-      this.hostInput.current.value = mailSettingParams.smtpHost || '';
-      this.portInput.current.value = mailSettingParams.smtpPort || '';
-      this.userInput.current.value = mailSettingParams.smtpUser || '';
-      this.passwordInput.current.value = mailSettingParams.smtpPassword || '';
-      this.closeInitializeValueModal();
-    }
-    catch (err) {
-      toastError(err);
-      logger.error(err);
-    }
-  }
-
   render() {
     const { t, adminAppContainer } = this.props;
+    const { activeTab, activeComponents } = this.state;
 
     return (
       <React.Fragment>
@@ -111,91 +79,35 @@ class MailSetting extends React.Component {
             <button type="button" className="btn btn-primary" onClick={this.submitFromAdressHandler}>{ t('Update') }</button>
           </div>
         </div>
-        <div id="mail-smtp" className="tab-pane active mt-5">
-          <div className="row form-group mb-5">
-            <label className="col-md-3 col-form-label text-left">{t('admin:app_setting.smtp_settings')}</label>
-            <div className="col-md-4">
-              <label>{t('admin:app_setting.host')}</label>
-              <input
-                className="form-control"
-                type="text"
-                ref={this.hostInput}
-                defaultValue={adminAppContainer.state.smtpHost || ''}
-                onChange={(e) => { adminAppContainer.changeSmtpHost(e.target.value) }}
-              />
-            </div>
-            <div className="col-md-2">
-              <label>{t('admin:app_setting.port')}</label>
-              <input
-                className="form-control"
-                ref={this.portInput}
-                defaultValue={adminAppContainer.state.smtpPort || ''}
-                onChange={(e) => { adminAppContainer.changeSmtpPort(e.target.value) }}
-              />
-            </div>
-          </div>
-
-          <div className="row form-group mb-5">
-            <div className="col-md-3 offset-md-3">
-              <label>{t('admin:app_setting.user')}</label>
-              <input
-                className="form-control"
-                type="text"
-                ref={this.userInput}
-                defaultValue={adminAppContainer.state.smtpUser || ''}
-                onChange={(e) => { adminAppContainer.changeSmtpUser(e.target.value) }}
-              />
-            </div>
-            <div className="col-md-3">
-              <label>{t('Password')}</label>
-              <input
-                className="form-control"
-                type="password"
-                ref={this.passwordInput}
-                defaultValue={adminAppContainer.state.smtpPassword || ''}
-                onChange={(e) => { adminAppContainer.changeSmtpPassword(e.target.value) }}
-              />
-            </div>
-          </div>
-
-          <div className="row my-3">
-            <div className="offset-5">
-              <button type="button" className="btn btn-primary" onClick={this.submitHandler} disabled={adminAppContainer.state.retrieveError != null}>
-                { t('Update') }
-              </button>
-            </div>
-            <div className="offset-1">
-              <button
-                type="button"
-                className="btn btn-secondary"
-                onClick={this.openInitializeValueModal}
-                disabled={adminAppContainer.state.retrieveError != null}
-              >
-                {t('admin:app_setting.initialize_mail_settings')}
-              </button>
-            </div>
-          </div>
-        </div>
-
 
-        <Modal isOpen={this.state.isInitializeValueModalOpen} toggle={this.closeInitializeValueModal} className="initialize-mail-settings">
-          <ModalHeader tag="h4" toggle={this.closeInitializeValueModal} className="bg-danger text-light">
-            {t('admin:app_setting.initialize_mail_modal_header')}
-          </ModalHeader>
-          <ModalBody>
-            <div className="text-center mb-4">
-              {t('admin:app_setting.confirm_to_initialize_mail_settings')}
-            </div>
-            <div className="text-center my-2">
-              <button type="button" className="btn btn-outline-secondary mr-4" onClick={this.closeInitializeValueModal}>
-                {t('Cancel')}
-              </button>
-              <button type="button" className="btn btn-danger" onClick={this.initialize}>
-                {t('Reset')}
-              </button>
-            </div>
-          </ModalBody>
-        </Modal>
+        <Nav tabs>
+          <NavItem>
+            <NavLink
+              className={`${activeTab === 'smtp-setting' && 'active'} `}
+              onClick={() => { this.toggleActiveTab('smtp-setting') }}
+              href="#smtp-setting"
+            >
+              SMTP
+            </NavLink>
+          </NavItem>
+          <NavItem>
+            <NavLink
+              className={`${activeTab === 'ses-setting' && 'active'} `}
+              onClick={() => { this.toggleActiveTab('ses-setting') }}
+              href="#ses-setting"
+            >
+              SES(AWS)
+            </NavLink>
+          </NavItem>
+        </Nav>
+        <TabContent activeTab={activeTab}>
+          <TabPane tabId="smtp-setting">
+            {activeComponents.has('smtp-setting') && <SmtpSetting />}
+          </TabPane>
+          <TabPane tabId="ses-setting">
+            {activeComponents.has('ses-setting') && <p>TBD</p>}
+          </TabPane>
+        </TabContent>
       </React.Fragment>
     );
   }

+ 170 - 0
src/client/js/components/Admin/App/SmtpSetting.jsx

@@ -0,0 +1,170 @@
+
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+import loggerFactory from '@alias/logger';
+
+import {
+  Modal, ModalHeader, ModalBody,
+} from 'reactstrap';
+import { withUnstatedContainers } from '../../UnstatedUtils';
+import { toastSuccess, toastError } from '../../../util/apiNotification';
+
+
+import AppContainer from '../../../services/AppContainer';
+import AdminAppContainer from '../../../services/AdminAppContainer';
+
+const logger = loggerFactory('growi:smtpSettings');
+
+
+function SmtpSetting(props) {
+  const { adminAppContainer, t } = props;
+
+  const [isInitializeValueModalOpen, setIsInitializeValueModalOpen] = useState(false);
+
+  function openInitializeValueModal() {
+    setIsInitializeValueModalOpen(true);
+
+  }
+
+  function closeInitializeValueModal() {
+    setIsInitializeValueModalOpen(false);
+  }
+
+  async function submitHandler() {
+    const { t, adminAppContainer } = props;
+
+    try {
+      await adminAppContainer.updateMailSettingHandler();
+      toastSuccess(t('toaster.update_successed', { target: t('admin:app_setting.mail_settings') }));
+    }
+    catch (err) {
+      toastError(err);
+      logger.error(err);
+    }
+  }
+
+  async function initialize() {
+    const { t, adminAppContainer } = props;
+
+    try {
+      const mailSettingParams = await adminAppContainer.initializeMailSettingHandler();
+      toastSuccess(t('toaster.initialize_successed', { target: t('admin:app_setting.smtp_settings') }));
+      // convert values to '' if value is null for overwriting values of inputs with refs
+      // this.hostInput.current.value = mailSettingParams.smtpHost || '';
+      // this.portInput.current.value = mailSettingParams.smtpPort || '';
+      // this.userInput.current.value = mailSettingParams.smtpUser || '';
+      // this.passwordInput.current.value = mailSettingParams.smtpPassword || '';
+      closeInitializeValueModal();
+    }
+    catch (err) {
+      toastError(err);
+      logger.error(err);
+    }
+  }
+
+
+  return (
+    <React.Fragment>
+      <div id="mail-smtp" className="tab-pane active mt-5">
+        <div className="row form-group mb-5">
+          <label className="col-md-3 col-form-label text-left">{t('admin:app_setting.smtp_settings')}</label>
+          <div className="col-md-4">
+            <label>{t('admin:app_setting.host')}</label>
+            <input
+              className="form-control"
+              type="text"
+              // ref={this.hostInput}
+              defaultValue={adminAppContainer.state.smtpHost || ''}
+              onChange={(e) => { adminAppContainer.changeSmtpHost(e.target.value) }}
+            />
+          </div>
+          <div className="col-md-2">
+            <label>{t('admin:app_setting.port')}</label>
+            <input
+              className="form-control"
+              // ref={this.portInput}
+              defaultValue={adminAppContainer.state.smtpPort || ''}
+              onChange={(e) => { adminAppContainer.changeSmtpPort(e.target.value) }}
+            />
+          </div>
+        </div>
+
+        <div className="row form-group mb-5">
+          <div className="col-md-3 offset-md-3">
+            <label>{t('admin:app_setting.user')}</label>
+            <input
+              className="form-control"
+              type="text"
+              // ref={this.userInput}
+              defaultValue={adminAppContainer.state.smtpUser || ''}
+              onChange={(e) => { adminAppContainer.changeSmtpUser(e.target.value) }}
+            />
+          </div>
+          <div className="col-md-3">
+            <label>{t('Password')}</label>
+            <input
+              className="form-control"
+              type="password"
+              // ref={this.passwordInput}
+              defaultValue={adminAppContainer.state.smtpPassword || ''}
+              onChange={(e) => { adminAppContainer.changeSmtpPassword(e.target.value) }}
+            />
+          </div>
+        </div>
+
+        <div className="row my-3">
+          <div className="offset-5">
+            <button type="button" className="btn btn-primary" onClick={submitHandler} disabled={adminAppContainer.state.retrieveError != null}>
+              { t('Update') }
+            </button>
+          </div>
+          <div className="offset-1">
+            <button
+              type="button"
+              className="btn btn-secondary"
+              onClick={openInitializeValueModal}
+              disabled={adminAppContainer.state.retrieveError != null}
+            >
+              {t('admin:app_setting.initialize_mail_settings')}
+            </button>
+          </div>
+        </div>
+      </div>
+
+
+      <Modal isOpen={isInitializeValueModalOpen} toggle={closeInitializeValueModal} className="initialize-mail-settings">
+        <ModalHeader tag="h4" toggle={closeInitializeValueModal} className="bg-danger text-light">
+          {t('admin:app_setting.initialize_mail_modal_header')}
+        </ModalHeader>
+        <ModalBody>
+          <div className="text-center mb-4">
+            {t('admin:app_setting.confirm_to_initialize_mail_settings')}
+          </div>
+          <div className="text-center my-2">
+            <button type="button" className="btn btn-outline-secondary mr-4" onClick={closeInitializeValueModal}>
+              {t('Cancel')}
+            </button>
+            <button type="button" className="btn btn-danger" onClick={initialize}>
+              {t('Reset')}
+            </button>
+          </div>
+        </ModalBody>
+      </Modal>
+
+    </React.Fragment>
+  );
+}
+
+/**
+ * Wrapper component for using unstated
+ */
+const SmtpSettingWrapper = withUnstatedContainers(SmtpSetting, [AppContainer, AdminAppContainer]);
+
+SmtpSetting.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  adminAppContainer: PropTypes.instanceOf(AdminAppContainer).isRequired,
+};
+
+export default withTranslation()(SmtpSettingWrapper);