Yuki Takei 6 лет назад
Родитель
Сommit
3a8f7e2b91

+ 46 - 27
src/client/js/components/Admin/ElasticsearchManagement/ElasticsearchManagement.jsx

@@ -4,9 +4,11 @@ import { withTranslation } from 'react-i18next';
 
 import { createSubscribedElement } from '../../UnstatedUtils';
 import AppContainer from '../../../services/AppContainer';
+import WebsocketContainer from '../../../services/WebsocketContainer';
 import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import IndicesStatusTable from './IndicesStatusTable';
+import NormalizeIndicesControls from './NormalizeIndicesControls';
 import RebuildIndexControls from './RebuildIndexControls';
 
 class ElasticsearchManagement extends React.Component {
@@ -15,7 +17,10 @@ class ElasticsearchManagement extends React.Component {
     super(props);
 
     this.state = {
-      isNormalized: undefined,
+      isRebuildingProcessing: false,
+      isRebuildingCompleted: false,
+
+      isNormalized: null,
       indicesData: null,
       aliasesData: null,
     };
@@ -28,6 +33,31 @@ class ElasticsearchManagement extends React.Component {
     this.retrieveIndicesStatus();
   }
 
+  componentDidMount() {
+    this.initWebSockets();
+  }
+
+  initWebSockets() {
+    const socket = this.props.websocketContainer.getWebSocket();
+
+    socket.on('admin:addPageProgress', (data) => {
+      this.setState({
+        isRebuildingProcessing: true,
+      });
+    });
+
+    socket.on('admin:finishAddPage', (data) => {
+      this.setState({
+        isRebuildingProcessing: false,
+        isRebuildingCompleted: true,
+      });
+    });
+
+    socket.on('admin:rebuildingFailed', (data) => {
+      toastError(new Error(data.error), 'Rebuilding Index has failed.');
+    });
+  }
+
   async retrieveIndicesStatus() {
     const { appContainer } = this.props;
 
@@ -63,6 +93,8 @@ class ElasticsearchManagement extends React.Component {
   async rebuildIndices() {
     const { appContainer } = this.props;
 
+    this.setState({ isRebuildingProcessing: true });
+
     try {
       await appContainer.apiv3Put('/search/indices', { operation: 'rebuild' });
       toastSuccess('Rebuilding is requested');
@@ -74,32 +106,11 @@ class ElasticsearchManagement extends React.Component {
     await this.retrieveIndicesStatus();
   }
 
-  renderNormalizeControls() {
-    const { t } = this.props;
-
-    const isEnabled = !this.state.isNormalized && !this.state.isProcessing;
-
-    return (
-      <>
-        <button
-          type="submit"
-          className={`btn btn-outline ${isEnabled ? 'btn-info' : 'btn-default'}`}
-          onClick={this.normalizeIndices}
-          disabled={!isEnabled}
-        >
-          { t('full_text_search_management.normalize_button') }
-        </button>
-
-        <p className="help-block">
-          { t('full_text_search_management.normalize_description') }<br />
-        </p>
-      </>
-    );
-  }
-
   render() {
     const { t } = this.props;
-    const { isNormalized, indicesData, aliasesData } = this.state;
+    const {
+      isRebuildingProcessing, isRebuildingCompleted, isNormalized, indicesData, aliasesData,
+    } = this.state;
 
     return (
       <>
@@ -119,7 +130,12 @@ class ElasticsearchManagement extends React.Component {
         <div className="row">
           <label className="col-xs-3 control-label">{ t('full_text_search_management.normalize') }</label>
           <div className="col-xs-6">
-            { this.renderNormalizeControls() }
+            <NormalizeIndicesControls
+              isRebuildingProcessing={isRebuildingProcessing}
+              isRebuildingCompleted={isRebuildingCompleted}
+              isNormalized={isNormalized}
+              onNormalizingRequested={this.normalizeIndices}
+            />
           </div>
         </div>
 
@@ -129,6 +145,8 @@ class ElasticsearchManagement extends React.Component {
           <label className="col-xs-3 control-label">{ t('full_text_search_management.rebuild') }</label>
           <div className="col-xs-6">
             <RebuildIndexControls
+              isRebuildingProcessing={isRebuildingProcessing}
+              isRebuildingCompleted={isRebuildingCompleted}
               isNormalized={isNormalized}
               onRebuildingRequested={this.rebuildIndices}
             />
@@ -145,12 +163,13 @@ class ElasticsearchManagement extends React.Component {
  * Wrapper component for using unstated
  */
 const ElasticsearchManagementWrapper = (props) => {
-  return createSubscribedElement(ElasticsearchManagement, props, [AppContainer]);
+  return createSubscribedElement(ElasticsearchManagement, props, [AppContainer, WebsocketContainer]);
 };
 
 ElasticsearchManagement.propTypes = {
   t: PropTypes.func.isRequired, // i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  websocketContainer: PropTypes.instanceOf(WebsocketContainer).isRequired,
 };
 
 export default withTranslation()(ElasticsearchManagementWrapper);

+ 49 - 0
src/client/js/components/Admin/ElasticsearchManagement/NormalizeIndicesControls.jsx

@@ -0,0 +1,49 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+import { createSubscribedElement } from '../../UnstatedUtils';
+
+class NormalizeIndicesControls extends React.PureComponent {
+
+  render() {
+    const { t, isNormalized, isRebuildingProcessing } = this.props;
+
+    const isEnabled = (isNormalized != null) && !isNormalized && !isRebuildingProcessing;
+
+    return (
+      <>
+        <button
+          type="submit"
+          className={`btn btn-outline ${isEnabled ? 'btn-info' : 'btn-default'}`}
+          onClick={() => { this.props.onNormalizingRequested() }}
+          disabled={!isEnabled}
+        >
+          { t('full_text_search_management.normalize_button') }
+        </button>
+
+        <p className="help-block">
+          { t('full_text_search_management.normalize_description') }<br />
+        </p>
+      </>
+    );
+  }
+
+}
+
+/**
+ * Wrapper component for using unstated
+ */
+const NormalizeIndicesControlsWrapper = (props) => {
+  return createSubscribedElement(NormalizeIndicesControls, props, []);
+};
+
+NormalizeIndicesControls.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+
+  isRebuildingProcessing: PropTypes.bool.isRequired,
+  onNormalizingRequested: PropTypes.func.isRequired,
+  isNormalized: PropTypes.bool,
+};
+
+export default withTranslation()(NormalizeIndicesControlsWrapper);

+ 12 - 26
src/client/js/components/Admin/ElasticsearchManagement/RebuildIndexControls.jsx

@@ -5,7 +5,6 @@ import { withTranslation } from 'react-i18next';
 import { createSubscribedElement } from '../../UnstatedUtils';
 import AppContainer from '../../../services/AppContainer';
 import WebsocketContainer from '../../../services/WebsocketContainer';
-import { toastError } from '../../../util/apiNotification';
 
 import ProgressBar from '../Common/ProgressBar';
 
@@ -15,15 +14,10 @@ class RebuildIndexControls extends React.Component {
     super(props);
 
     this.state = {
-      isProcessing: false,
-      isCompleted: false,
-
       total: 0,
       current: 0,
       skip: 0,
     };
-
-    this.rebuildIndices = this.rebuildIndices.bind(this);
   }
 
   componentDidMount() {
@@ -35,40 +29,32 @@ class RebuildIndexControls extends React.Component {
 
     socket.on('admin:addPageProgress', (data) => {
       this.setState({
-        isProcessing: true,
         ...data,
       });
     });
 
     socket.on('admin:finishAddPage', (data) => {
       this.setState({
-        isProcessing: false,
-        isCompleted: true,
         ...data,
       });
     });
 
-    socket.on('admin:rebuildingFailed', (data) => {
-      toastError(new Error(data.error), 'Rebuilding Index has failed.');
-    });
-  }
-
-  async rebuildIndices() {
-    this.setState({ isProcessing: true });
-    this.props.onRebuildingRequested();
   }
 
   renderProgressBar() {
     const {
-      total, current, skip, isProcessing, isCompleted,
+      isRebuildingProcessing, isRebuildingCompleted,
+    } = this.props;
+    const {
+      total, current, skip,
     } = this.state;
-    const showProgressBar = isProcessing || isCompleted;
+    const showProgressBar = isRebuildingProcessing || isRebuildingCompleted;
 
     if (!showProgressBar) {
       return null;
     }
 
-    const header = isCompleted ? 'Completed' : `Processing.. (${skip} skips)`;
+    const header = isRebuildingCompleted ? 'Completed' : `Processing.. (${skip} skips)`;
 
     return (
       <ProgressBar
@@ -80,9 +66,9 @@ class RebuildIndexControls extends React.Component {
   }
 
   render() {
-    const { t, isNormalized } = this.props;
+    const { t, isNormalized, isRebuildingProcessing } = this.props;
 
-    const isEnabled = isNormalized && !this.state.isProcessing;
+    const isEnabled = isNormalized && !isRebuildingProcessing;
 
     return (
       <>
@@ -91,7 +77,7 @@ class RebuildIndexControls extends React.Component {
         <button
           type="submit"
           className="btn btn-inverse"
-          onClick={this.rebuildIndices}
+          onClick={() => { this.props.onRebuildingRequested() }}
           disabled={!isEnabled}
         >
           { t('full_text_search_management.rebuild_button') }
@@ -120,11 +106,11 @@ RebuildIndexControls.propTypes = {
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   websocketContainer: PropTypes.instanceOf(WebsocketContainer).isRequired,
 
+  isRebuildingProcessing: PropTypes.bool.isRequired,
+  isRebuildingCompleted: PropTypes.bool.isRequired,
+
   isNormalized: PropTypes.bool,
   onRebuildingRequested: PropTypes.func.isRequired,
 };
-RebuildIndexControls.defaultProps = {
-  isNormalized: false,
-};
 
 export default withTranslation()(RebuildIndexControlsWrapper);