ElasticsearchManagement.jsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import { createSubscribedElement } from '../../UnstatedUtils';
  5. import AppContainer from '../../../services/AppContainer';
  6. import WebsocketContainer from '../../../services/WebsocketContainer';
  7. import { toastSuccess, toastError } from '../../../util/apiNotification';
  8. import StatusTable from './StatusTable';
  9. import ReconnectControls from './ReconnectControls';
  10. import NormalizeIndicesControls from './NormalizeIndicesControls';
  11. import RebuildIndexControls from './RebuildIndexControls';
  12. class ElasticsearchManagement extends React.Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. isConfigured: null,
  17. isConnected: null,
  18. isRebuildingProcessing: false,
  19. isRebuildingCompleted: false,
  20. isNormalized: null,
  21. indicesData: null,
  22. aliasesData: null,
  23. };
  24. this.reconnect = this.reconnect.bind(this);
  25. this.normalizeIndices = this.normalizeIndices.bind(this);
  26. this.rebuildIndices = this.rebuildIndices.bind(this);
  27. }
  28. async componentWillMount() {
  29. this.retrieveIndicesStatus();
  30. }
  31. componentDidMount() {
  32. this.initWebSockets();
  33. }
  34. initWebSockets() {
  35. const socket = this.props.websocketContainer.getWebSocket();
  36. socket.on('admin:addPageProgress', (data) => {
  37. this.setState({
  38. isRebuildingProcessing: true,
  39. });
  40. });
  41. socket.on('admin:finishAddPage', (data) => {
  42. this.setState({
  43. isRebuildingProcessing: false,
  44. isRebuildingCompleted: true,
  45. });
  46. });
  47. socket.on('admin:rebuildingFailed', (data) => {
  48. toastError(new Error(data.error), 'Rebuilding Index has failed.');
  49. });
  50. }
  51. async retrieveIndicesStatus() {
  52. const { appContainer } = this.props;
  53. try {
  54. const { info } = await appContainer.apiv3Get('/search/indices');
  55. this.setState({
  56. isConfigured: true,
  57. isConnected: true,
  58. indicesData: info.indices,
  59. aliasesData: info.aliases,
  60. isNormalized: info.isNormalized,
  61. });
  62. }
  63. catch (errors) {
  64. this.setState({ isConnected: false });
  65. // evaluate whether configured or not
  66. for (const error of errors) {
  67. if (error.code === 'search-service-unconfigured') {
  68. this.setState({ isConfigured: false });
  69. }
  70. }
  71. toastError(errors);
  72. }
  73. }
  74. async reconnect() {
  75. const { appContainer } = this.props;
  76. try {
  77. await appContainer.apiv3Post('/search/connection');
  78. toastSuccess('Reconnecting to Elasticsearch has succeeded');
  79. }
  80. catch (e) {
  81. toastError(e);
  82. return;
  83. }
  84. await this.retrieveIndicesStatus();
  85. }
  86. async normalizeIndices() {
  87. const { appContainer } = this.props;
  88. try {
  89. await appContainer.apiv3Put('/search/indices', { operation: 'normalize' });
  90. }
  91. catch (e) {
  92. toastError(e);
  93. }
  94. await this.retrieveIndicesStatus();
  95. toastSuccess('Normalizing has succeeded');
  96. }
  97. async rebuildIndices() {
  98. const { appContainer } = this.props;
  99. this.setState({ isRebuildingProcessing: true });
  100. try {
  101. await appContainer.apiv3Put('/search/indices', { operation: 'rebuild' });
  102. toastSuccess('Rebuilding is requested');
  103. }
  104. catch (e) {
  105. toastError(e);
  106. }
  107. await this.retrieveIndicesStatus();
  108. }
  109. render() {
  110. const { t } = this.props;
  111. const {
  112. isConfigured, isConnected, isRebuildingProcessing, isRebuildingCompleted,
  113. isNormalized, indicesData, aliasesData,
  114. } = this.state;
  115. return (
  116. <>
  117. <div className="row">
  118. <div className="col-xs-12">
  119. <StatusTable
  120. isConfigured={isConfigured}
  121. isConnected={isConnected}
  122. isNormalized={isNormalized}
  123. indicesData={indicesData}
  124. aliasesData={aliasesData}
  125. />
  126. </div>
  127. </div>
  128. <hr />
  129. {/* Controls */}
  130. <div className="row">
  131. <label className="col-xs-3 control-label">{ t('full_text_search_management.reconnect') }</label>
  132. <div className="col-xs-6">
  133. <ReconnectControls
  134. isConfigured={isConfigured}
  135. isConnected={isConnected}
  136. onReconnectingRequested={this.reconnect}
  137. />
  138. </div>
  139. </div>
  140. <hr />
  141. <div className="row">
  142. <label className="col-xs-3 control-label">{ t('full_text_search_management.normalize') }</label>
  143. <div className="col-xs-6">
  144. <NormalizeIndicesControls
  145. isRebuildingProcessing={isRebuildingProcessing}
  146. isRebuildingCompleted={isRebuildingCompleted}
  147. isNormalized={isNormalized}
  148. onNormalizingRequested={this.normalizeIndices}
  149. />
  150. </div>
  151. </div>
  152. <hr />
  153. <div className="row">
  154. <label className="col-xs-3 control-label">{ t('full_text_search_management.rebuild') }</label>
  155. <div className="col-xs-6">
  156. <RebuildIndexControls
  157. isRebuildingProcessing={isRebuildingProcessing}
  158. isRebuildingCompleted={isRebuildingCompleted}
  159. isNormalized={isNormalized}
  160. onRebuildingRequested={this.rebuildIndices}
  161. />
  162. </div>
  163. </div>
  164. </>
  165. );
  166. }
  167. }
  168. /**
  169. * Wrapper component for using unstated
  170. */
  171. const ElasticsearchManagementWrapper = (props) => {
  172. return createSubscribedElement(ElasticsearchManagement, props, [AppContainer, WebsocketContainer]);
  173. };
  174. ElasticsearchManagement.propTypes = {
  175. t: PropTypes.func.isRequired, // i18next
  176. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  177. websocketContainer: PropTypes.instanceOf(WebsocketContainer).isRequired,
  178. };
  179. export default withTranslation()(ElasticsearchManagementWrapper);