HealthyIndexDetailView.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import { makeStyles, Theme } from '@material-ui/core';
  2. import { CHART_WIDTH, LINE_CHART_SMALL_HEIGHT } from './consts';
  3. import HealthyIndexRow from './HealthyIndexRow';
  4. import LineChartSmall from './LineChartSmall';
  5. import { ENodeService, INodeTreeStructure, IThreshold } from './Types';
  6. import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
  7. import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
  8. import { Dispatch, SetStateAction, useState } from 'react';
  9. const getStyles = makeStyles((theme: Theme) => ({
  10. mainView: {
  11. width: '100%',
  12. marginTop: '16px',
  13. },
  14. healthyIndexItem: {
  15. display: 'flex',
  16. marginTop: '8px',
  17. justifyContent: 'space-between',
  18. },
  19. healthyIndexLabel: {
  20. fontWeight: 500,
  21. fontSize: '12px',
  22. color: '#444',
  23. display: 'flex',
  24. alignItems: 'center',
  25. cursor: 'pointer',
  26. },
  27. healthyIndexLabelText: {},
  28. healthyIndexRow: {
  29. width: `${CHART_WIDTH}px`,
  30. },
  31. chartItem: {
  32. margin: '8px 0',
  33. display: 'flex',
  34. justifyContent: 'space-between',
  35. alignItems: 'center',
  36. },
  37. chartLabel: {
  38. width: `50px`,
  39. paddingLeft: '20px',
  40. fontSize: '12px',
  41. fontWeight: 500,
  42. color: '#444',
  43. },
  44. chart: {
  45. height: `${LINE_CHART_SMALL_HEIGHT}px`,
  46. width: `${CHART_WIDTH}px`,
  47. },
  48. }));
  49. const HealthyIndexTreeItem = ({
  50. node,
  51. threshold,
  52. }: {
  53. node: INodeTreeStructure;
  54. threshold: IThreshold;
  55. }) => {
  56. const classes = getStyles();
  57. const [open, setOpen] = useState(false);
  58. return (
  59. <>
  60. <div
  61. key={`${node.service}-${node.type}-${node.label}`}
  62. className={classes.healthyIndexItem}
  63. >
  64. <div
  65. className={classes.healthyIndexLabel}
  66. onClick={() => setOpen(!open)}
  67. >
  68. {open ? (
  69. <KeyboardArrowDownIcon fontSize="small" />
  70. ) : (
  71. <KeyboardArrowRightIcon fontSize="small" />
  72. )}
  73. <div className={classes.healthyIndexLabelText}>{`${
  74. node.type
  75. }-${node.label.slice(-5)}`}</div>
  76. </div>
  77. <div className={classes.healthyIndexRow}>
  78. <HealthyIndexRow statusList={node.healthyStatus} />
  79. </div>
  80. </div>
  81. {open && (
  82. <>
  83. <div className={classes.chartItem}>
  84. <div className={classes.chartLabel}>cpu</div>
  85. <div className={classes.chart}>
  86. <LineChartSmall
  87. data={node.cpu || []}
  88. format={(v: number) => v.toFixed(3)}
  89. unit={'Core'}
  90. threshold={threshold.cpu}
  91. />
  92. </div>
  93. </div>
  94. <div className={classes.chartItem}>
  95. <div className={classes.chartLabel}>memory</div>
  96. <div className={classes.chart}>
  97. <LineChartSmall
  98. data={node.memory || []}
  99. format={(v: number) => (v / 1024 / 1024 / 1024).toFixed(1)}
  100. unit={'GB'}
  101. threshold={threshold.memory}
  102. />
  103. </div>
  104. </div>
  105. </>
  106. )}
  107. </>
  108. );
  109. };
  110. const HealthyIndexWithTree = ({
  111. nodeTree,
  112. setSelectedService,
  113. threshold,
  114. }: {
  115. nodeTree: INodeTreeStructure;
  116. setSelectedService: Dispatch<SetStateAction<ENodeService>>;
  117. threshold: IThreshold;
  118. }) => {
  119. const classes = getStyles();
  120. return (
  121. <div className={classes.mainView}>
  122. {!!nodeTree && (
  123. <div className={classes.healthyIndexItem}>
  124. <div
  125. className={classes.healthyIndexLabel}
  126. onClick={() => setSelectedService(ENodeService.root)}
  127. >
  128. {nodeTree.label}
  129. </div>
  130. <div className={classes.healthyIndexRow}>
  131. <HealthyIndexRow statusList={nodeTree?.healthyStatus || []} />
  132. </div>
  133. </div>
  134. )}
  135. {!!nodeTree &&
  136. nodeTree.children.map(node => (
  137. <HealthyIndexTreeItem
  138. key={node.label}
  139. node={node}
  140. threshold={threshold}
  141. />
  142. ))}
  143. </div>
  144. );
  145. };
  146. const HealthyIndexWithoutTree = ({
  147. nodeTree,
  148. setSelectedService,
  149. }: {
  150. nodeTree: INodeTreeStructure;
  151. setSelectedService: Dispatch<SetStateAction<ENodeService>>;
  152. }) => {
  153. const classes = getStyles();
  154. return (
  155. <div className={classes.mainView}>
  156. {nodeTree.children.map(node => (
  157. <div
  158. key={`${node.service}-${node.type}`}
  159. className={classes.healthyIndexItem}
  160. >
  161. <div
  162. className={classes.healthyIndexLabel}
  163. onClick={() => setSelectedService(node.service)}
  164. >
  165. {node.label}
  166. </div>
  167. <div className={classes.healthyIndexRow}>
  168. <HealthyIndexRow statusList={node.healthyStatus} />
  169. </div>
  170. </div>
  171. ))}
  172. </div>
  173. );
  174. };
  175. const HealthyIndexDetailView = ({
  176. nodeTree,
  177. setSelectedService,
  178. threshold,
  179. }: {
  180. nodeTree: INodeTreeStructure;
  181. setSelectedService: Dispatch<SetStateAction<ENodeService>>;
  182. threshold: IThreshold;
  183. }) => {
  184. return nodeTree.service === ENodeService.milvus ? (
  185. <HealthyIndexWithoutTree
  186. nodeTree={nodeTree}
  187. setSelectedService={setSelectedService}
  188. />
  189. ) : (
  190. <HealthyIndexWithTree
  191. nodeTree={nodeTree}
  192. setSelectedService={setSelectedService}
  193. threshold={threshold}
  194. />
  195. );
  196. };
  197. export default HealthyIndexDetailView;