StatusTable.jsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import { createSubscribedElement } from '../../UnstatedUtils';
  5. class StatusTable extends React.PureComponent {
  6. renderIndexInfoPanel(indexName, body = {}, aliases = []) {
  7. const collapseId = `collapse-${indexName}`;
  8. const aliasLabels = aliases.map((aliasName) => {
  9. return (
  10. <span key={`label-${indexName}-${aliasName}`} className="label label-primary mr-2">
  11. <i className="icon-tag"></i> {aliasName}
  12. </span>
  13. );
  14. });
  15. return (
  16. <div className="panel panel-default">
  17. <div className="panel-heading" role="tab">
  18. <h4 className="panel-title">
  19. <a role="button" data-toggle="collapse" data-parent="#accordion" href={`#${collapseId}`} aria-expanded="true" aria-controls={collapseId}>
  20. <i className="fa fa-fw fa-database"></i> {indexName}
  21. </a>
  22. <span className="ml-3">{aliasLabels}</span>
  23. </h4>
  24. </div>
  25. <div id={collapseId} className="panel-collapse collapse" role="tabpanel">
  26. <div className="panel-body">
  27. <pre>
  28. {JSON.stringify(body, null, 2)}
  29. </pre>
  30. </div>
  31. </div>
  32. </div>
  33. );
  34. }
  35. renderIndexInfoPanels() {
  36. const {
  37. indicesData,
  38. aliasesData,
  39. } = this.props;
  40. // data is null
  41. if (indicesData == null) {
  42. return null;
  43. }
  44. /*
  45. "indices": {
  46. "growi": {
  47. ...
  48. }
  49. },
  50. */
  51. const indexNameToDataMap = {};
  52. for (const [indexName, indexData] of Object.entries(indicesData)) {
  53. indexNameToDataMap[indexName] = indexData;
  54. }
  55. // no indices
  56. if (indexNameToDataMap.length === 0) {
  57. return null;
  58. }
  59. /*
  60. "aliases": {
  61. "growi": {
  62. "aliases": {
  63. "growi-alias": {}
  64. }
  65. }
  66. },
  67. */
  68. const indexNameToAliasMap = {};
  69. for (const [indexName, aliasData] of Object.entries(aliasesData)) {
  70. indexNameToAliasMap[indexName] = Object.keys(aliasData.aliases);
  71. }
  72. return (
  73. <div className="row">
  74. { Object.keys(indexNameToDataMap).map((indexName) => {
  75. return (
  76. <div key={`col-${indexName}`} className="col-xs-6">
  77. { this.renderIndexInfoPanel(indexName, indexNameToDataMap[indexName], indexNameToAliasMap[indexName]) }
  78. </div>
  79. );
  80. }) }
  81. </div>
  82. );
  83. }
  84. render() {
  85. const { t } = this.props;
  86. const { isConfigured, isConnected, isNormalized } = this.props;
  87. let connectionStatusLabel = <span className="label label-default">――</span>;
  88. if (isConfigured != null && !isConfigured) {
  89. connectionStatusLabel = <span className="label label-default">{ t('full_text_search_management.connection_status_label_unconfigured') }</span>;
  90. }
  91. else if (isConnected != null) {
  92. connectionStatusLabel = isConnected
  93. ? <span className="label label-success">{ t('full_text_search_management.connection_status_label_connected') }</span>
  94. : <span className="label label-danger">{ t('full_text_search_management.connection_status_label_disconnected') }</span>;
  95. }
  96. let indicesStatusLabel = <span className="label label-default">――</span>;
  97. if (isNormalized != null) {
  98. indicesStatusLabel = isNormalized
  99. ? <span className="label label-info">{ t('full_text_search_management.indices_status_label_normalized') }</span>
  100. : <span className="label label-warning">{ t('full_text_search_management.indices_status_label_unnormalized') }</span>;
  101. }
  102. return (
  103. <table className="table table-bordered">
  104. <tbody>
  105. <tr>
  106. <th>{ t('full_text_search_management.connection_status') }</th>
  107. <td>{connectionStatusLabel}</td>
  108. </tr>
  109. <tr>
  110. <th>{ t('full_text_search_management.indices_status') }</th>
  111. <td>{indicesStatusLabel}</td>
  112. </tr>
  113. <tr>
  114. <th className="col-sm-4">{ t('full_text_search_management.indices_summary') }</th>
  115. <td className="p-4">
  116. { this.renderIndexInfoPanels() }
  117. </td>
  118. </tr>
  119. </tbody>
  120. </table>
  121. );
  122. }
  123. }
  124. /**
  125. * Wrapper component for using unstated
  126. */
  127. const StatusTableWrapper = (props) => {
  128. return createSubscribedElement(StatusTable, props, []);
  129. };
  130. StatusTable.propTypes = {
  131. t: PropTypes.func.isRequired, // i18next
  132. isConfigured: PropTypes.bool,
  133. isConnected: PropTypes.bool,
  134. isNormalized: PropTypes.bool,
  135. indicesData: PropTypes.object,
  136. aliasesData: PropTypes.object,
  137. };
  138. export default withTranslation()(StatusTableWrapper);